【问题标题】:How to test if GTK+ dialog has been created?如何测试是否已创建 GTK+ 对话框?
【发布时间】:2015-11-30 20:08:03
【问题描述】:

我已经使用 Wnck 来检查是否已经创建了这样的窗口:

    screen = Wnck.Screen.get_default()
    screen.force_update()  # recommended per Wnck documentation
    window_list = screen.get_windows()

    for window in window_list:
        print(window.get_name())
        if window.has_name():
            if window.get_name() == self.xld_main_window.get_title():
                window_found = True
                break
    assert window_found, 'The Gtk.Window named {window_name} has not been found.'\
        .format(window_name=self.xld_main_window.get_title())

    # clean up Wnck (saves resources, check documentation)
    window = None
    screen = None

但是,由于对话框没有显示在任务列表中,因此我无法以这种方式找到它们。检查它们是否显示(和模态/非模态)的适当方法是什么?

【问题讨论】:

    标签: python testing dialog gtk3 wnck


    【解决方案1】:

    Eye of Hellthis answer 获取部分内容,其中说明了如何获取打开的窗口,您可以这样做:

    from gtk import gdk
    
    name = "MyDialog"
    
    root = gdk.get_default_root_window()
    matches = []
    for id in root.property_get("_NET_CLIENT_LIST"):
        window = gdk.window_foreign_new(id)
        if window and window.property_get("WM_NAME")[2] == name:
            matches.append(window)
    
    for match in matches:
        print(match, match.get_modal_hint())
    

    【讨论】:

    • 抱歉,我询问的是对话框而不是窗口。我已经在 OP 中使用了该函数来检查窗口,但它不适用于对话框(或者某处还有另一个错误)。
    【解决方案2】:

    Wnck.Screen.get_windows 方法返回所有窗口,包括对话框。没有区别,因为该函数返回当前映射的任何 Wnck.Window。来源是这样的:

    * The #WnckScreen represents a physical screen. A screen may consist of
    * multiple monitors which are merged to form a large screen area. The
    * #WnckScreen is at the bottom of the libwnck stack of objects: #WnckWorkspace
    * objects exist a #WnckScreen and #WnckWindow objects are displayed on a
    * #WnckWorkspace.
    *
    * The #WnckScreen corresponds to the notion of
    * <classname>GdkScreen</classname> in GDK.
    
    GList*
    wnck_screen_get_windows (WnckScreen *screen)
    {
      g_return_val_if_fail (WNCK_IS_SCREEN (screen), NULL);
    
      return screen->priv->mapped_windows;
    }
    

    其中screen-&gt;priv 指向struct,其中包含一些窗口列表(映射的、堆叠的)、指向活动窗口的指针等。一些WnckWindow 可以设置WNCK_WINDOW_DIALOG 并成为一个对话框。

    WnckWindow 类还提供了一个函数transient_is_most_recently_activated(),用于了解在WnckTaskList 中选择时焦点是否应该转到瞬态子窗口,或者将瞬态窗口及其父窗口最小化。例如,要知道My Application 窗口是否有最近激活的瞬态:

    screen = Wnck.Screen.get_default()
    screen.force_update()  # recommended per Wnck documentation
    window_list = screen.get_windows()
    
    for window in window_list:
        if window.get_name() == 'My Application':
            print(window.transient_is_most_recently_activated())
    

    下面的脚本将对话框捕获为其他映射窗口(无论它们是模态/非模态还是它们来自的应用程序)。

    import gi
    gi.require_version('Gtk', '3.0')
    gi.require_version('Wnck', '3.0')
    from gi.repository import Gtk, Wnck
    
    class DialogExample(Gtk.Dialog):
    
        def __init__(self, parent):
            Gtk.Dialog.__init__(self, "My Dialog", parent, 0, #or Gtk.DialogFlags.MODAL
                (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
                 Gtk.STOCK_OK, Gtk.ResponseType.OK))
    
            self.set_default_size(100, 100)
    
            label = Gtk.Label("This is a dialog to display additional information")
    
            box = self.get_content_area()
            box.add(label)
            self.show_all()
    
    class DialogWindow(Gtk.Window):
    
        def __init__(self):
            Gtk.Window.__init__(self, title="Dialog Example")
            self.set_border_width(6)
            button = Gtk.Button("Open dialog")
            button.connect("clicked", self.on_button_clicked)
            self.add(button)
    
        def on_button_clicked(self, widget):
            dialog = DialogExample(self)
            response = dialog.run()
    
            if response == Gtk.ResponseType.OK:
                print("The OK button was clicked")
            elif response == Gtk.ResponseType.CANCEL:
                print("The Cancel button was clicked")
    
            screen = Wnck.Screen.get_default()
            screen.force_update()  # recommended per Wnck documentation
            window_list = screen.get_windows()
    
            for window in window_list:
                print(window.get_name())
    
            window, window_list = (None,)*2
            screen = None
    
            dialog.destroy()
    
    win = DialogWindow()
    win.connect("delete-event", Gtk.main_quit)
    win.show_all()
    
    window = None
    screen = None
    Gtk.main()
    

    使用 Gdk 而不是 Wnck,您可以在稍低的级别上做同样的事情。

    【讨论】:

    • 感谢您的回答,但请注意:“Wnck.Screen.get_windows 方法返回所有窗口,包括对话框。” 不正确。如果对话框在函数返回的窗口列表中,我永远不会发布这个问题。现在已经有一段时间了,但我能想象的唯一另一个错误是,在获取窗口列表之前我必须稍等片刻,但由于现在对话框不可见,我不认为创建对话框应该花费很多时间。你知道其他原因吗,为什么对话框不在那个窗口列表中?
    • 还请注意,对话框不会出现在我系统上的任何任务栏中。所以如果 wnck 使用某种任务栏检查,它就不会像这样工作。
    • 我能够运行您的示例,现在我确信,在我的 pytest 测试中一定还有其他错误,导致对话框没有出现在列表中。也许我可以找到它与您的示例一起使用。
    • 如果您正在寻找链接到特定应用程序的对话,您可以测试dialog_window.get_transient() == main_window
    猜你喜欢
    • 2011-02-27
    • 1970-01-01
    • 2017-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-15
    • 2012-03-09
    • 1970-01-01
    相关资源
    最近更新 更多