Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python GTK:在GTK.ApplicationWindow上重新绘制小部件时出现问题_Python_Gtk - Fatal编程技术网

Python GTK:在GTK.ApplicationWindow上重新绘制小部件时出现问题

Python GTK:在GTK.ApplicationWindow上重新绘制小部件时出现问题,python,gtk,Python,Gtk,我正在用Python为一个已经存在的程序创建一个GTK GUI。设想以下结构: program |----gtk |-----application.py |-----mainwindow.py |-----mainwidgets.py 当然,这是简化的。但是GUI的工作原理有点像这样:application.py是一个Gtk.application,它在mainwidgets中创建对象的实例,提供后端函数,这些函数作为回调传递给mainwindow.py,

我正在用Python为一个已经存在的程序创建一个GTK GUI。设想以下结构:

program
|----gtk
      |-----application.py
      |-----mainwindow.py
      |-----mainwidgets.py
当然,这是简化的。但是GUI的工作原理有点像这样:application.py是一个Gtk.application,它在mainwidgets中创建对象的实例,提供后端函数,这些函数作为回调传递给mainwindow.py,mainwindow.py将小部件放置在Gtk.ApplicationWindow中

有几个案例我遇到了麻烦。我会看两个我认为相关的

让我们先看一个简单的。mainwidget中定义了一个简单的按钮,在我的程序中用作状态栏

class Statusbar(Gtk.Widget):
    def __init__(self, on_button_do):
        super(Gtk.Widget, self).__init__()
        self.callback = on_button_do
        self.button_label_int = 0
        self.button = Gtk.Button.new_with_label(str(button_label_int)

    def increment_button_label(self):
        self.button_label_int += 1
        self.button.set_label(str(button_label))
然后,当主窗口接收到信号时,指示它调用 状态栏。增量按钮标签()。一旦接收到该信号,由于分段故障,几乎立即崩溃,不再提供有关该问题的更多信息

class AppWindow(Gtk.ApplicationWindow):

    __gsignals__ = {
                "new_log": (GObject.SIGNAL_RUN_FIRST, None, ())
                }

    def __init__(self, statusbar, sidebar, *args, **kwargs):
        super(Gtk.ApplicationWindow, self).__init__(*args, **kwargs)

        self.statusbar = statusbar
        self.sidebar = sidebar

        self.notificationBox = Gtk.Box()
        self.notificationBox.pack_start(self.statusbar.get_button(), True, True, 0)

        # MAINBOX: THE BIGGER BOX OF ALL THE LITTLE BOXES
        self.mainBox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        self.mainBox.pack_start(self.
        self.mainBox.pack_start(self.notificationBox, False, False, 0)

        self.add(self.mainBox)

        self.show_all()

    def do_new_log(self):
        """What should the window do when it gets a new_log signal"""
        statusbar.increment_button_label()
另一个(相关的?)问题是更新小部件的显示:我的边栏。侧边栏实际上只是一个Gtk.ListStore和一个Gtk.TreeView,没有什么特别之处。在application.py中,您会发现如下代码:

def do_startup(self):

    Gtk.Application.do_startup(self)  # deep GTK magic

    self.sidebar = Sidebar(self.workspace_manager,
                           self.changeWorkspace,
                           CONF.getLastWorkspace())
然后,侧边栏的实例被传递到mainwindow.py以放入一个框中。目前一切正常

当我试图向侧边栏添加信息时,问题就出现了。它的后端部分可以工作,因为如果我重新启动应用程序,我可以在侧边栏中看到新条目。侧边栏从该后端获取信息:

class Sidebar(Gtk.Widget):

    def __init__(self, workspace_manager, callback_to_change_workspace, conf):
        super(Gtk.Widget, self).__init__()
        self.callback = callback_to_change_workspace
        self.ws_manager = workspace_manager
        self.lastWorkspace = conf

    def createTitle(self):
        title = Gtk.Label()
        title.set_text("Workspaces")
        return title

    def workspaceModel(self):
        self.workspace_list_info = Gtk.ListStore(str)
        for ws in self.ws_manager.getWorkspacesNames():
            treeIter = workspace_list_info.append([ws])
            if ws == self.lastWorkspace:
                self.defaultSelection = treeIter

    def workspaceView(self):
        self.lst = Gtk.TreeView(self.workspace_list_info)
        renderer = Gtk.CellRendererText()
        column = Gtk.TreeViewColumn("Workspaces", renderer, text=0)
        self.lst.append_column(column)

        # select by default the last active workspace
        if self.defaultSelection is not None:
            self.selectDefault = self.lst.get_selection()
            self.selectDefault.select_iter(self.defaultSelection)

        self.selection = self.lst.get_selection()
        self.selection.connect("changed", self.callback)
maindindow试图做的是将sidebar.lst放入一个框中。那很好。问题是,当我通过一个对话框添加一个工作区时,我并没有出现,正如我前面所说的


你知道是什么导致了这些问题吗?出于GTK的某些原因,这种组织问题的方式不合适吗?我认为代码本身很好:毕竟,工作区是添加的,GTK不会崩溃。只是做得不好。而且,这个按钮一开始显示得很好,甚至发出信号。但一旦我试图改变它的标签,一切都爆炸了

好的,这实际上与多个线程和信号有关。通过覆盖发射信号解决了这个问题

class _IdleObject(GObject.GObject):
"""
Override GObject.GObject to always emit signals in the main thread
by emmitting on an idle handler
"""
def __init__(self):
    GObject.GObject.__init__(self)

def emit(self, *args):
    GObject.idle_add(GObject.GObject.emit, self, *args)

好的,这实际上与多个线程和信号有关。通过覆盖发射信号解决了这个问题

class _IdleObject(GObject.GObject):
"""
Override GObject.GObject to always emit signals in the main thread
by emmitting on an idle handler
"""
def __init__(self):
    GObject.GObject.__init__(self)

def emit(self, *args):
    GObject.idle_add(GObject.GObject.emit, self, *args)

尝试在这个问题的例子中添加一个小的独立的例子:您当前提供的信息似乎不足以解决这个问题。另外,您是否正在使用多线程?请尝试在问题示例中添加一个小的独立线程:您当前提供的信息似乎不足以解决此问题。另外,您是否使用多线程?