You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GTK开发:如何预设与恢复选中的打印机?

解决GtkPrintUnixDialog预设指定打印机的问题

我之前也踩过这个坑!直接调用print_settings.set("printer", NAME)之所以无效,是因为GtkPrintUnixDialog初始化时,不会单纯依赖PrintSettings里的名称字符串去匹配打印机——它需要的是一个实际的GtkPrinter对象引用,系统默认打印机的优先级会覆盖你设置的字符串值。下面给你详细的解决方案和示例代码:

核心解决思路

  1. 保存设置时:正常保存PrintSettings的所有键值(其中已经包含了打印机名称)
  2. 恢复设置时:
    • 从保存的设置中读取打印机名称
    • 通过名称获取对应的GtkPrinter对象
    • 将这个对象直接设置给GtkPrintUnixDialog,而不是只修改PrintSettings

Python示例代码

import gtk
import json

def save_print_settings(settings):
    # 将PrintSettings转为字典并保存到文件
    config = {}
    def collect_key(key, value, data):
        data[key] = value
    settings.foreach(collect_key, config)
    
    with open("print_config.json", "w") as f:
        json.dump(config, f)

def load_print_settings():
    # 从文件加载设置并还原为PrintSettings对象
    settings = gtk.PrintSettings()
    try:
        with open("print_config.json", "r") as f:
            config = json.load(f)
        for key, value in config.items():
            settings.set(key, value)
    except FileNotFoundError:
        pass  # 首次运行无配置,使用默认设置
    return settings

def show_print_dialog():
    dialog = gtk.PrintUnixDialog()
    saved_settings = load_print_settings()
    dialog.set_print_settings(saved_settings)
    
    # 关键:获取并设置指定打印机
    printer_name = saved_settings.get("printer")
    if printer_name:
        # 同步获取打印机对象(第三个参数True表示等待打印机列表加载完成)
        target_printer = gtk.printer_get_for_name(None, printer_name, True)
        if target_printer:
            dialog.set_printer(target_printer)
    
    # 处理对话框响应
    response = dialog.run()
    if response == gtk.RESPONSE_OK:
        # 保存用户修改后的新设置
        new_settings = dialog.get_print_settings()
        save_print_settings(new_settings)
    
    dialog.destroy()

if __name__ == "__main__":
    show_print_dialog()
    gtk.main()

C语言示例代码

#include <gtk/gtk.h>
#include <json-c/json.h>
#include <glib/gstdio.h>

void save_print_settings(GtkPrintSettings *settings) {
    // 将PrintSettings转为哈希表再序列化到JSON文件
    GHashTable *settings_hash = gtk_print_settings_to_hash_table(settings);
    json_object *json_obj = json_object_new_object();
    
    GHashTableIter iter;
    gpointer key, val;
    g_hash_table_iter_init(&iter, settings_hash);
    while (g_hash_table_iter_next(&iter, &key, &val)) {
        json_object_object_add(json_obj, (gchar*)key, json_object_new_string((gchar*)val));
    }
    
    const gchar *json_str = json_object_to_json_string(json_obj);
    g_file_set_contents("print_config.json", json_str, -1, NULL);
    
    json_object_put(json_obj);
    g_hash_table_destroy(settings_hash);
}

GtkPrintSettings* load_print_settings() {
    GtkPrintSettings *settings = gtk_print_settings_new();
    gchar *json_str = NULL;
    
    if (!g_file_get_contents("print_config.json", &json_str, NULL, NULL)) {
        return settings; // 无配置文件,返回默认设置
    }
    
    json_object *json_obj = json_tokener_parse(json_str);
    g_free(json_str);
    
    if (!json_obj) return settings;
    
    // 遍历JSON对象,还原PrintSettings
    json_object_object_foreach(json_obj, key, val) {
        gtk_print_settings_set(settings, key, json_object_get_string(val));
    }
    
    json_object_put(json_obj);
    return settings;
}

void show_print_dialog() {
    GtkWidget *dialog = gtk_print_unix_dialog_new(NULL, NULL);
    GtkPrintSettings *saved_settings = load_print_settings();
    gtk_print_unix_dialog_set_print_settings(GTK_PRINT_UNIX_DIALOG(dialog), saved_settings);
    
    // 关键:设置指定打印机
    const gchar *printer_name = gtk_print_settings_get(saved_settings, "printer");
    if (printer_name) {
        GtkPrinter *target_printer = gtk_printer_get_for_name(NULL, printer_name, TRUE, NULL);
        if (target_printer) {
            gtk_print_unix_dialog_set_printer(GTK_PRINT_UNIX_DIALOG(dialog), target_printer);
            g_object_unref(target_printer); // 释放对象引用,避免内存泄漏
        }
    }
    
    // 处理对话框响应
    gint response = gtk_dialog_run(GTK_DIALOG(dialog));
    if (response == GTK_RESPONSE_OK) {
        GtkPrintSettings *new_settings = gtk_print_unix_dialog_get_print_settings(GTK_PRINT_UNIX_DIALOG(dialog));
        save_print_settings(new_settings);
        g_object_unref(new_settings);
    }
    
    g_object_unref(saved_settings);
    gtk_widget_destroy(dialog);
}

int main(int argc, char *argv[]) {
    gtk_init(&argc, &argv);
    show_print_dialog();
    gtk_main();
    return 0;
}

注意事项

  • 确保你保存的打印机名称是系统中已存在的,否则gtk_printer_get_for_name()会返回NULL,这时对话框会自动 fallback 到系统默认打印机
  • C语言版本需要注意GObject的引用计数管理,避免内存泄漏
  • 如果你的程序需要非阻塞加载打印机列表,可以使用异步APIgtk_printer_get_for_name_async(),示例中用的同步方式适合简单场景

内容的提问来源于stack exchange,提问作者Matthias Urlichs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:01:37