在 Python GTK (Glade) 中分别关闭两个 windows

Close separately two windows in Python GTK (Glade)

我最近开始使用 Python GTK 和 Glade 开发一些简单的 GUI。我创建了一个 GUI,它由一个带按钮的主 window 组成,而按下按钮的动作是第二个 window 的弹出窗口,上面有一个 matplotlib 图。

我面临的问题是,当我关闭第二个 window 时,第一个也会关闭,我希望能够分别终止它们。

下面是 python 代码,here 是带有 GUI 布局的空地文件。

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

导入来自vext.gi、numpy和matplotlibpython包,我使用的Glade版本是3.22.1,我的OS 是初级 Linux 5.1 赫拉。

您需要更改呼叫:

.connect("delete-event", Gtk.main_quit)

以便他们仅在这是最后一次打开时才调用 Gtk.main_quit window。

将对 Gtk.main_quit 的直接调用替换为:

def exit(window, event):    
    if not any(w.get_visible() for w in Gtk.Window.list_toplevels() if w is not window):
        Gtk.main_quit()

这使得关闭 window 只会在它是最后一个可见的 window 时退出应用程序。


如果你只做:

window.hide()
return True

在您的销毁事件处理程序中,您永远不会关闭应用程序。

将我不认为是问题的内容结合起来,因为我无法 运行 你的程序与我建议的代码会导致 main_quit 在所有 [=31] 时被调用=] 已关闭。

经过一些研究 () 和一些实验后,我得出结论,不应关闭由我的主 window 按钮触发的第二个弹出窗口 window使用事件函数 Gtk.main_quit(),但应该使用事件函数 hide() 隐藏它。因此,第一个主要 window 将保持打开状态。

但是,由于 matplotlib 图是绘制在 FigureCanvas 上的,它包含在我的第二个弹出窗口 window 的子窗口小部件(滚动条 window)中,因此需要删除事件popup-window 销毁滚动条 window 以便能够重新绘制并避免有关现有子部件的错误。

所以在我原来问题的代码中进行以下修改添加所需的功能:

[1] 从 glade 文件中删除滚动条 window 小部件

[2] 在弹出窗口顶部添加滚动条 window 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]更改popup的事件函数window:

window2.connect("delete-event", self.destroy)

销毁函数定义为:

def destroy(self, widget, event):
    scrolledwindow = widget.get_child()
    scrolledwindow.destroy()
    widget.hide()
    return True

然后无论我关闭第二个 window 多少次并按下主 window 中的按钮,情节都绘制在(隐藏的)第二个 window 上。