I recently started developing some simple GUIs using Python GTK and Glade. I've created a GUI which consists of a main window with a button while the action of pressing the button is the popup of a second window with a matplotlib plot on it.
The problem I face is that when i close the second window then the first one is also closed and i would like to be able and terminate them separately.
Below is the python code and here is the glade file with GUI's layout.
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import numpy as np
from matplotlib.figure import Figure
from matplotlib.axes import Subplot
from matplotlib.backends.backend_gtk3agg import (
FigureCanvasGTK3Agg as FigureCanvas)
class PlotApp:
def __init__(self):
gladefile = 'GTK-two-windows.glade'
self.builder = Gtk.Builder()
self.builder.add_from_file(gladefile)
main_win = self.builder.get_object("window1")
main_win.connect("delete-event", Gtk.main_quit)
button = self.builder.get_object('button')
button.connect('clicked', self.plot)
main_win.show_all()
def plot(self, widget):
window2 = self.builder.get_object("window2")
window2.connect("delete-event", Gtk.main_quit)
scrolledwindow = self.builder.get_object("scrolledwindow")
# ----- Start of Matplotlib specific code -----
figure = Figure(figsize=(8, 6), dpi=71)
axis = figure.add_subplot(111)
t = np.arange(0.0, 3.0, 0.01)
s = np.sin(2*np.pi*t)
axis.plot(t, s)
axis.set_xlabel('time [s]')
axis.set_ylabel('voltage [V]')
canvas = FigureCanvas(figure) # a Gtk.DrawingArea
canvas.set_size_request(800, 600)
scrolledwindow.add_with_viewport(canvas)
# ----- End of Matplotlib specific code -----
window2.show_all()
if __name__ == "__main__":
main = PlotApp()
Gtk.main()
The imports are from vext.gi, numpy and matplotlib python packages, the Glade version I use is 3.22.1 and my OS is Elementary Linux 5.1 Hera.
After some research (Reopen window throws Gtk-CRITICAL **: gtk_widget_get_window: assertion 'GTK_IS_WIDGET (widget)' failed) and some experimenting I concluded that the second-popup window, which is triggered by the button of my main window, should not be closed with the event function Gtk.main_quit(), but it should be hidden using the event function hide(). As a result the first-main window will remain open.
However, since the matplotlib plot is plotted on a FigureCanvas which is contained on the child widget (scrollbar window) of my second-popup window, then it is required the delete-event of popup-window to destroy the scrollbar window in order to be able to replot and avoid errors about existing child widgets.
So in the code of my original question the following modifications add the required functionality:
[1] Delete the scrollbar window widget from glade file
[2] Add a scrollbar window on top of popup window:
scrolledwindow = Gtk.ScrolledWindow()
#----- Start of Matplotlib specific code -----
figure = Figure(figsize=(8, 6), dpi=71)
axis = figure.add_subplot(111)
t = np.arange(0.0, 3.0, 0.01)
s = np.sin(2*np.pi*t)
axis.plot(t, s)
axis.set_xlabel('time [s]')
axis.set_ylabel('voltage [V]')
canvas = FigureCanvas(figure) # a Gtk.DrawingArea
canvas.set_size_request(800, 600)
scrolledwindow.add_with_viewport(canvas)
#scrolledwindow.add(canvas)
# ----- End of Matplotlib specific code -----
window2.add(scrolledwindow)
window2.show_all()
[3] Change the event function of popup window:
window2.connect("delete-event", self.destroy)
where the destroy function is defined as:
def destroy(self, widget, event):
scrolledwindow = widget.get_child()
scrolledwindow.destroy()
widget.hide()
return True
Then no matter how many times I close the second window and press the button in main window, the plot is plotted on the (hidden) second window.