Glade + Python 如何关闭第二个 window

Glade + Python how to close second window

我正在尝试使用 Glade+Python 编写包含两个 windows 的简单应用程序。 请看看我的代码。 起始文件:

import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
from handlers import *

builder = Gtk.Builder.new_from_file("okno1.glade")
window = builder.get_object("okno") #Main window of the application
window_about = builder.get_object("okno2") #second window of the application - should not be shown at the beginning

builder.connect_signals(Handlers()) #here i connect class "Handlers" which make some actions with signals from both windows
window.connect("delete-event", Gtk.main_quit) # i connect "delete-event" with main window. If we close it, whole app should be closed - works as it should
window_about.connect("delete-event", Gtk.Window.hide) #Here is problematic line....
Gtk.main()

和带有处理程序的文件 class:

class Handlers:

def okno_button_clicked_cb(self, widget):
    '''this method takes care about button on main window'''
    widget.show_all()
    
def okno2_button_clicked_cb(self, widget):
    '''this method takes care about button on second window'''
    widget.hide()

工作应用程序如下所示:

左边是主要 Window。如果我点击它上面的按钮,右边的 window 就会出现。如果我在第二个 window 上单击按钮 - 它会消失。当我再次单击主 window 上的按钮时,第二个 window 出现 - 一切正常。但是,如果我单击第二个 window 顶部的“X”按钮,第二个 window 就会消失,如果我再次单击主 window 上的按钮,第二个 window 会出现但没有它的按钮....问题在哪里????我认为第二个 window (window_about) 的“删除事件”有问题。但是我应该用什么来代替 Gtk.Window.hide?????

请帮忙,我完全没有想法:-(

P.S。这是“okno1.glade”:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.4 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkWindow" id="okno">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="default_width">440</property>
    <property name="default_height">250</property>
    <child>
      <object class="GtkFixed">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkButton" id="okno_button">
            <property name="label" translatable="yes">otworz durgie okno</property>
            <property name="width_request">100</property>
            <property name="height_request">80</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
            <signal name="clicked" handler="okno_button_clicked_cb" object="okno2" swapped="no"/>
          </object>
          <packing>
            <property name="x">232</property>
            <property name="y">134</property>
          </packing>
        </child>
      </object>
    </child>
    <child type="titlebar">
      <placeholder/>
    </child>
  </object>
  <object class="GtkWindow" id="okno2">
    <property name="can_focus">False</property>
    <property name="modal">True</property>
    <property name="default_width">440</property>
    <property name="default_height">250</property>
    <child>
      <object class="GtkFixed">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <child>
          <object class="GtkButton" id="okno2_button">
            <property name="label" translatable="yes">zamknij okno
</property>
            <property name="width_request">100</property>
            <property name="height_request">80</property>
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">True</property>
            <signal name="clicked" handler="okno2_button_clicked_cb" object="okno2" swapped="no"/>
          </object>
          <packing>
            <property name="x">237</property>
            <property name="y">132</property>
          </packing>
        </child>
      </object>
    </child>
    <child type="titlebar">
      <placeholder/>
    </child>
  </object>
</interface>

我会解释问题及其解决方案,但如果您只想要解决方案而不需要解释,完整的解决方案代码在答案的末尾。


问题来了。您可能注意到,当您单击 okno_button 时,终端会打印一条错误消息:

TypeError: Gtk.Widget.hide() takes exactly 1 argument (2 given)

这意味着当 Gtk 调用你连接到 delete-event 信号的 hide() 函数时,它给它 两个 个参数,而不是 一个。在这种情况下,一个参数是 self,因为 hide() 是一个 class 方法。当 window 关闭(并发送 delete-event 信号)时,hide() 得到两个参数:self window-close 事件。

此错误消息的解决方案是编写一个单独的函数, 接受两个参数。这是一个简单的例子:

def hide_window(window, event):
    window.hide()

但是,如果您使用此功能而不是 hide() (window_about.connect("delete-event", hide_window)),该按钮仍然会消失。这是因为 Gtk 的 delete-event 删除了 window(这并不奇怪)。

要防止 window 自行删除,您可以在 hide_window() 函数的末尾 return True。在回调函数的末尾使用 return True 告诉 Gtk 不要对事件做出反应;你已经照顾好了。这是一个很好的技巧,在文本编辑器之类的东西中特别有用,程序员想要覆盖文本小部件的默认行为。


综上所述,这是完整的工作代码,其中 hide_window() 函数仅 隐藏 关闭时的 window; window 没有被删除。

import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
from handlers import *

def hide_window(window, event):
    window.hide()
    return True

builder = Gtk.Builder.new_from_file("okno1.glade")
window = builder.get_object("okno")
window_about = builder.get_object("okno2")

builder.connect_signals(Handlers())
window.connect("delete-event", Gtk.main_quit)
window_about.connect("delete-event", hide_window)
Gtk.main()