加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

在MS Windows上重用GTK中不同父级的模态对话框 – 破碎的焦点

发布时间:2020-12-14 05:40:05 所属栏目:Windows 来源:网络整理
导读:我正在重用GTK中的模态对话框 – 我使用gtk_window_set_transient_for设置它的父对话框,运行它,然后将它的父对象重置为另一个对话框并再次运行它. 在Linux上一切都很好,但在MS Windows上第二次显示此对话框时,所有GTK窗口都混淆了哪一个是活动的. 这是一个测
我正在重用GTK中的模态对话框 – 我使用gtk_window_set_transient_for设置它的父对话框,运行它,然后将它的父对象重置为另一个对话框并再次运行它.

在Linux上一切都很好,但在MS Windows上第二次显示此对话框时,所有GTK窗口都混淆了哪一个是活动的.

这是一个测试程序:

#include <gtk/gtk.h>

GtkWidget* main_window;

void run_reused_dialog(
    GtkWidget* reused_dialog,const gchar *parent_title,const gchar *reused_dialog_title
) {
    GtkWidget* parent_dialog = gtk_dialog_new_with_buttons(
        parent_title,GTK_WINDOW(main_window),GTK_DIALOG_MODAL,GTK_STOCK_OK,GTK_RESPONSE_ACCEPT,NULL
    );
    gtk_container_add(
        GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(parent_dialog))),gtk_label_new(parent_title)
    );
    gtk_widget_show_all(parent_dialog);
    gtk_dialog_run(GTK_DIALOG(parent_dialog));

    gtk_window_set_transient_for(GTK_WINDOW(reused_dialog),GTK_WINDOW(parent_dialog));
    gtk_window_set_title(GTK_WINDOW(reused_dialog),reused_dialog_title);
    GtkWidget* reused_dialog_label = gtk_label_new(GTK_WINDOW(reused_dialog)->title);
    gtk_container_add(
        GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(reused_dialog))),reused_dialog_label
    );
    gtk_widget_show_all(reused_dialog);
    gtk_dialog_run(GTK_DIALOG(reused_dialog));
    gtk_widget_hide(reused_dialog);
    gtk_container_remove(
        GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(reused_dialog))),reused_dialog_label
    );
    gtk_widget_hide(parent_dialog);
    gtk_widget_destroy(parent_dialog);
}

int main(int argc,char *argv[])
{
    gtk_init(&argc,&argv);
    main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(main_window,"delete-event",G_CALLBACK(gtk_main_quit),NULL);
    gtk_widget_show_all(main_window);

    /* This is a dialog which will be reused */
    GtkWidget* reused_dialog = gtk_dialog_new_with_buttons(
        "Reused dialog",NULL
    );
    gtk_container_add(
        GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(reused_dialog))),gtk_label_new(GTK_WINDOW(reused_dialog)->title)
    );

    /* Show first dialog which will display reused dialog */
    run_reused_dialog(
        reused_dialog,"First dialog. Click OK to display reused dialog","Reused dialog. Click OK to close"
    );

    /* Show second dialog which will display reused dialog */
    run_reused_dialog(
        reused_dialog,"Second dialog. Click OK to display reused dialog","Reused dialog. Switch to another application and switch back"
    );

    gtk_main();
    return 0;
}

当显示“重用对话框.切换到另一个应用程序并切换回”对话框时,它会忽略鼠标,但会对键盘输入作出反应.有时切换到另一个应用程序并返回触发此问题.

问题:

>我做错了什么或者它是Windows GTK端口的错误?
>如何在不使用每次使用时重新创建此对话框的情况下解决它?
>我是否可以重复使用GTK对话框?

带有所需GTK库的示例程序源和已编译的可执行文件是here.这是使用i686-pc-mingw32-gcc gtk-reused-dialog.c进行交叉编译的.$(mingw32-pkg-config –cflags –libs gtk -2.0 )-mwindows在Fedora Linux 15上使用mingw32-gtk2包并安装了它的依赖项.

解决方法

这是我的猜测:

>问题与焦点攫取有关;
>窗口小部件仅在模态标志changes its state时调用抓取API;
>平台之间的差异主要是由于实施细节;
>你不能只有一个模态窗口.

在显示reused_dialog时,不清楚哪个对话框是模态的(parent_window仍然存活).

正确的解决方案:我怀疑如果您重构代码以显示来自回调的reused_dialog(例如,使用response信号),您将获得所需的结果,因为这是通常的方法?.

如果您不想重构,可以尝试其中一种解决方案/解决方案(大致按照我认为更好的顺序):

>在运行之前,始终取消激活reused_dialog的模态状态; gtk_dialog_run()will set it再次触发请求:

...
gtk_window_set_modal(GTK_WINDOW(reused_dialog),FALSE);
gtk_dialog_run(GTK_DIALOG(reused_dialog));
...

>在运行之前手动抓住reused_dialog中的焦点:

...
gtk_grab_add(reused_dialog);
gtk_dialog_run(GTK_DIALOG(reused_dialog));
...

>运行后取消激活parent_window的模态状态:

...
gtk_dialog_run(GTK_DIALOG(parent_dialog));
gtk_window_set_modal(GTK_WINDOW(parent_dialog),FALSE);
...

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读