我有一个窗口,我希望更改一个窗口小部件中的值以更改另一个窗口小部件;因此在小部件的事件处理程序中,我"刷新"该窗口删除其小部件并再次创建它们。在我的实际代码中,我有几个小部件,这是我的解决方法,以及#34;更新"他们。如果有更好的方法来更新其他小部件,如果用于生成它们的其中一个值发生更改,请随时告诉我。
但是,在下面的示例中,小部件似乎变为空白,我收到此消息:
(test4.py:19274): Gtk-CRITICAL **: gtk_container_remove: assertion
'_gtk_widget_get_parent (widget) == GTK_WIDGET (container) ||
GTK_IS_ASSISTANT (container) || GTK_IS_ACTION_BAR (container) ||
GTK_IS_POPOVER_MENU (container)' failed
(test4.py:19274): Gtk-CRITICAL **: gtk_adjustment_get_value: assertion
'GTK_IS_ADJUSTMENT (adjustment)' failed
(test4.py:19274): Gtk-CRITICAL **: gtk_widget_has_focus: assertion
'GTK_IS_WIDGET (widget)' failed
(test4.py:19274): Gtk-CRITICAL **: gtk_widget_has_focus: assertion
'GTK_IS_WIDGET (widget)' failed
test4.py:69: Warning: g_object_ref: assertion 'G_IS_OBJECT (object)' failed
Gtk.main()
[...]
我在这里附上了我的代码:
import sys
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
# Documentation: https://graph-tool.skewed.de/static/doc/index.html
class SpecialBox(Gtk.Box):
def __init__(self, GUI):
Gtk.Box.__init__(self)
self.GUI = GUI
self.liststore = Gtk.ListStore(str, int, int)
self.liststore.append(["Apple", 0, 100])
self.liststore.append(["Pear", 0, 100])
self.liststore.append(["Orange", 0, 100])
treeview = Gtk.TreeView(model=self.liststore)
filter_name = Gtk.CellRendererText()
column_text = Gtk.TreeViewColumn("Fruit is good", filter_name, text=0)
treeview.append_column(column_text)
self.filter_low = Gtk.CellRendererSpin()
self.filter_low.connect("edited", self.low_on_amount_edited)
self.filter_low.set_property("editable", True)
low_adjustment = Gtk.Adjustment(0, 0, 99, 1, 10, 0)
self.filter_low.set_property("adjustment", low_adjustment)
low_spin = Gtk.TreeViewColumn("Random Number", self.filter_low, text=1)
treeview.append_column(low_spin)
self.add(treeview)
def low_on_amount_edited(self, widget, path, value):
value = int(value)
self.liststore[path][1] = value
self.GUI.restart_window(str(value))
class GUI:
def __init__(self):
self.win = Gtk.Window()
self.window_grid = Gtk.Grid()
self.special_box = Gtk.Box(spacing=10)
self.label = Gtk.Label("Number label")
self.win.connect("delete-event", Gtk.main_quit)
self.start_window()
def start_window(self):
self.special_box.pack_start(SpecialBox(self), True, True, 0)
self.window_grid.add(self.special_box)
self.window_grid.add(self.label)
self.win.add(self.window_grid)
self.win.show_all()
def restart_window(self, label="Number"):
self.window_grid.destroy()
self.window_grid = Gtk.Grid()
self.special_box = Gtk.Box(spacing=10)
self.label = Gtk.Label(label)
self.start_window()
def main():
app = GUI()
Gtk.main()
if __name__ == "__main__":
sys.exit(main())
上面的代码生成错误,但由于某种原因,下面的代码工作正常(我基本上只是用一个按钮替换了上面的小部件):
import sys
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
# Documentation: https://graph-tool.skewed.de/static/doc/index.html
class SpecialButton(Gtk.Box):
def __init__(self, GUI):
Gtk.Box.__init__(self)
self.GUI = GUI
self.set_border_width(10)
self.message = "Special Text"
button = Gtk.Button.new_with_label(self.message)
button.connect("clicked", self.on_click)
self.pack_start(button, True, True, 0)
def on_click(self, widget):
self.GUI.restart_window(self.message)
class GUI:
def __init__(self):
self.win = Gtk.Window()
self.window_grid = Gtk.Grid()
self.box = Gtk.Box(spacing=10)
self.label = Gtk.Label("Default label")
self.win.connect("delete-event", Gtk.main_quit)
self.start_window()
def start_window(self):
self.box.pack_start(SpecialButton(self), True, True, 0)
self.window_grid.add(self.box)
self.window_grid.add(self.label)
self.win.add(self.window_grid)
self.win.show_all()
def restart_window(self, label="Default label"):
self.window_grid.destroy()
self.window_grid = Gtk.Grid()
self.box = Gtk.Box(spacing=10)
self.label = Gtk.Label(label)
self.start_window()
def main():
app = GUI()
Gtk.main()
if __name__ == "__main__":
sys.exit(main())
答案 0 :(得分:0)
这里的问题是,当该窗口小部件的事件处理程序正在运行时,您正在销毁窗口小部件。该小部件是您的CellRendererSpin
。
当此Spinbutton的值发生变化时,它会触发low_on_amount_edited)
:
self.filter_low.connect("edited", self.low_on_amount_edited)
调用GUI.restart_window
:
self.GUI.restart_window(str(value))
破坏SpecialBox
小部件及其所有子小部件,包括Spinbutton:
self.window_grid.destroy()
在小部件做某事时摧毁小部件并不奇怪。
要解决此问题,您只需将调用推迟到GUI.restart_window
,直到Spinbutton的事件处理程序完成。为此,您可以使用idle_add
,它将回调排队以由Gtk主循环执行:
from gi.repository import Gtk, Gdk, GLib
class SpecialBox(Gtk.Box):
def low_on_amount_edited(self, widget, path, value):
value = int(value)
self.liststore[path][1] = value
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT, self.GUI.restart_window, str(value))