GTK开发:如何预设与恢复选中的打印机?
解决GtkPrintUnixDialog预设指定打印机的问题
我之前也踩过这个坑!直接调用print_settings.set("printer", NAME)之所以无效,是因为GtkPrintUnixDialog初始化时,不会单纯依赖PrintSettings里的名称字符串去匹配打印机——它需要的是一个实际的GtkPrinter对象引用,系统默认打印机的优先级会覆盖你设置的字符串值。下面给你详细的解决方案和示例代码:
核心解决思路
- 保存设置时:正常保存PrintSettings的所有键值(其中已经包含了打印机名称)
- 恢复设置时:
- 从保存的设置中读取打印机名称
- 通过名称获取对应的
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的引用计数管理,避免内存泄漏
- 如果你的程序需要非阻塞加载打印机列表,可以使用异步API
gtk_printer_get_for_name_async(),示例中用的同步方式适合简单场景
内容的提问来源于stack exchange,提问作者Matthias Urlichs
相关产品推荐
相关产品推荐

