1

我正在使用 Python 3.7 和 PyGTK 3.0 开发一个 GUI 应用程序。我的 GUI 由多个 GTK.Notebooks 组成,它们都在同一个组中,并且它们的所有选项卡都设置为可拆卸的。这样,我可以从一个笔记本中拖出一页并将其放到另一个笔记本上。这适用于我正在使用的大多数小部件,但我正在努力让它与 GTK.Socket 一起使用。我想运行外部程序并将它们的 GUI 显示为其中一个笔记本中的页面。这很好用,但是当我将页面拖到不同的笔记本时,页面是空的。

我尝试连接到页面添加和页面删除信号并将一些调试信息打印到控制台。我注意到在 GTK.Socket 的每次移动(拖放到另一个笔记本)中,GTK.Socket 都会获得一个新 ID。在第一次移动之后,ID 已经与 Socket 创建和添加后的 ID 不同。这让我想到,每次移动页面时,都会创建一个新的 Socket,显然外部程序没有注意到这种变化,仍然会绘制到旧的 Socket 上,我无法再显示了。

这是我的问题的 MWE。它创建一个窗口,其中两个笔记本设置在 HPaned 容器中。每个 Notebook 都获得一个 TextView 作为它们的第一页(因此它不是空的),并且正确的 Notebook 也获得一个 Socket(在这种情况下,它中继​​到 gtkwave 会话)。我还通过一些调试输出添加了页面添加和页面删除的侦听器。

import subprocess
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

def handleAdd(notebook, child, pageNum):
    print("Handle add")
    if isinstance(child, Gtk.Socket):
        print("ID after ADD: " + hex(child.get_id()))

def handleRemove(notebook, child, pageNum):
    print("Handle remove")
    if isinstance(child, Gtk.Socket):
        print("ID after REMOVE: " + hex(child.get_id()))

window = Gtk.Window()

paned = Gtk.HPaned()

notebookLeft = Gtk.Notebook()
notebookRight = Gtk.Notebook()
notebookLeft.connect("page-added", handleAdd)
notebookLeft.connect("page-removed", handleRemove)
notebookRight.connect("page-added", handleAdd)
notebookRight.connect("page-removed", handleRemove)

textviewLeft = Gtk.TextView()
textviewRight = Gtk.TextView()

notebookLeft.append_page(textviewLeft)
notebookLeft.set_tab_detachable(textviewLeft, True)
notebookLeft.set_tab_reorderable(textviewLeft, True)
notebookLeft.set_group_name("Main")
notebookRight.append_page(textviewRight)
notebookRight.set_tab_detachable(textviewRight, True)
notebookRight.set_tab_reorderable(textviewRight, True)
notebookRight.set_group_name("Main")

socket = Gtk.Socket()
notebookRight.append_page(socket)
notebookRight.set_tab_detachable(socket, True)
notebookRight.set_tab_reorderable(socket, True)

paned.add1(notebookLeft)
paned.add2(notebookRight)
window.add(paned)

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

window.show_all()

print("First socket id " + hex(socket.get_id()))
process = subprocess.Popen(["gtkwave", "/home/benedikt/repos/synpathic/synpathic/testsrc/tb_blake2b.ghw", "-X", hex(socket.get_id())])

Gtk.main()

如果运行代码,您将看到以下消息:

...
ID after ADD: 0x0
(test.py:18825): Gtk-CRITICAL **: 11:42:07.507: gtk_socket_get_id: assertion '_gtk_widget_get_anchored (GTK_WIDGET (socket))' failed
First socket id 0x7400010
... (GTKWave messages) ...

第一个 ID 是 0x0,因为尚未将 Socket 添加到 Window,这是预期的行为。这也解释了错误(如果我不连接信号,错误就消失了)。就在调用 Gtk.main() 之前,Socket 是有效的,并且可以打印 ID。现在移动带有 GTKWave 会话的选项卡,您将看到每次移动的以下消息:

...
ID after ADD: 0x74001ae
...

此 ID 与第一个有效 ID 不同,并且每次移动都不同。我希望这个 ID 保持不变,以便仍然可以显示外部 GUI。为什么要创建一个新的 Socket,我该如何解决这个问题?

4

0 回答 0