林间空地Python如何关闭第二个窗口

发布于 2025-01-16 00:29:45 字数 4643 浏览 5 评论 0原文

我正在尝试使用 Glade+Python 编写带有两个窗口的简单应用程序。 请看一下我的代码。 启动文件:

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 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()

工作应用程序看起来像这样: 输入图片此处描述

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

请帮忙,我完全没有主意了:-(

PS 这里是“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>

I am trying to write simple aplication with two windows using Glade+Python.
Take look at my code please.
Start file:

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()

And file with handler 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()

Working app loks like this:
enter image description here

Thare is main Window on left. If I click on the button on it, window on right appears. If I click button on second window - it dissapears. When I click again button on main window second window appears - everything works fine. But if I click "X" button on the top of second window, second window dissapear, and if I click again button on main window, second window appears but without its button.... Where is the problem???? I think something is wrong with "delete event" of second window (window_about). But what should I use instead of Gtk.Window.hide????

Please help, I am completely out of ideas :-(

P.S. here is "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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

帥小哥 2025-01-23 00:29:45

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


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

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

这意味着当 Gtk 调用您连接到 hide() 函数时删除事件信号,它给它两个参数,而不是一个。在本例中,一个参数是 self,因为 hide() 是一种类方法。当窗口关闭(并且发送 delete-event 信号)时,hide() 将获取两个参数:self和窗口关闭事件。

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

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

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

为了防止窗口删除自身,您可以在 hide_window() 函数末尾返回 True。在回调函数末尾使用 return True 告诉 Gtk 不要对事件做出反应;你已经处理好了。这是一个很好的技巧,在文本编辑器等程序员想要覆盖文本小部件的默认行为的情况下特别方便。


话虽如此,这里是完整的工作代码,其中 hide_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()

I'll explain the problem and its solution, but if you just want the solution without the explanation, the full solution code is at the end of the answer.


Here's the problem. You probably notice that, when you click okno_button, the terminal prints an error message:

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

This means that when Gtk calls the hide() function that you connected to the delete-event signal, it's giving it two arguments, instead of one. In this case, the one argument is self, since hide() is a class method. When the window is closed (and the delete-event signal is sent), hide() is getting two arguments: self, and the window-close event.

The solution to this error message is to write a separate function that does take two arguments. Here is a simple example:

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

However, if you use this function instead of hide() (window_about.connect("delete-event", hide_window)), the button still disappears. This is because Gtk's delete-event deletes the window (no surprise there).

To prevent the window from deleting itself, you can return True at the end of your hide_window() function. Using return True at the end of a callback function tells Gtk not to react to the event; that you've already taken care of it. This is a nice trick that comes in especially handy in things like text editors, where programmers want to override the default behaviors of a text widget.


All that being said, here is the full working code, with the hide_window() function that only hides the window when it's closed; the window isn't deleted.

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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文