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