GTK - 程序不遵循预期的功能顺序

时间:2015-04-15 09:31:18

标签: python multithreading gtk

我对这个网站很陌生,所以我希望在提出要求时遵守所有规则。关于问题:

我正在使用Glade构建GTK + / Python3程序。当用户单击“读取文件”按钮时,将调用某些耗时的函数。这是一个给你一个想法的片段:

def onReadFile(self, widget, data=None):

    ### I want the statusbar (had the same problem with a progressbar) 
    ### to push() and display at this point
    self.statusbar.push(self.contextID, "Reading file...")

    ### Unfortunately, my program waits for all this to finish
    ### before displaying the statusbar.push() far too late
    text = back.readFile(self.inFile)
    splitText = back.textSplit(text)
    choppedArray = back.wordChop(splitText)
    back.wordCount(choppedArray, self.currDict)
    currSortedArray = back.wordOrder(self.currDict)

    handles.printResults(currSortedArray, "resCurrGrid", self.builder)

主要的想法是,事情并没有按照我期望的顺序发生,而且我不知道为什么(事情仍然没有发生错误)。我四处阅读(herethere并认为线程可能是我的问题,但我不确定,因为我没有发现任何人提出的问题与我的问题太相似。

为什么statusbar.push()等到最后才能显示其消息?

更新

我已尝试按照线程示例here对其进行排序,但我无法适应'那课对我基于班级的课程的布局。

这就是它的样子(为了简洁和相关性而剪裁):

from gi.repository import Gtk, GLib, GObject
import threading
import back
import handles

class Application:

    def __init__(self):
        # I build from glade
        self.builder = Gtk.Builder()
        ...

        # I want this window to show later
        self.progWindow = self.builder.get_object("progWindow")

        self.window = self.builder.get_object("mainWindow")
        self.window.show()

        # I believe this code should go here in the __init__, though
        # I'm quite possibly wrong
        thread = threading.Thread(target=self.onReadFile)
        thread.daemon = True
        thread.start()

    ...

    def upProgress(self):
        self.progWindow.show()

        return False

    def onReadFile(self, widget, data=None):

        # Following the example I linked to, this to my understanding
        # should show the progWindow by asking the main Gtk thread
        # to execute it
        GLib.idle_add(self.upProgress)

        # Time-consuming operations
        text = back.readFile(self.inFile)
        splitText = back.textSplit(text)
        ...

if __name__ == "__main__":
    GObject.threads_init()

    main = Application()

    Gtk.main()

threading.Thread(target=self.onReadFile)时遇到以下错误,但它最接近'工作'我明白了:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.2/threading.py", line 740, in _bootstrap_inner
self.run()
  File "/usr/lib/python3.2/threading.py", line 693, in run
self._target(*self._args, **self._kwargs)
TypeError: onReadFile() takes at least 2 arguments (1 given)

我唯一的想法是:

  1. 我需要相当不同的结构,因为我使用的是一个类(我在链接中的例子不是。)
  2. 我未能通过必要的辩论,但对于我的生活,我看不到什么。
  3. 我在生活中失败了。
  4. 如果你可以提供帮助,那很棒,如果你能做到,但可以提出一个很棒的教程。我的头发不能拉扯。

    如果我要发布一个完整的工作示例,请告诉我。

1 个答案:

答案 0 :(得分:2)

因为GTK +重绘是从运行回调的同一执行线程发生的。因此,如果您在需要重绘的回调中执行某些操作,那么在回调退出之后实际上不会发生这种情况。

解决方案是通过使用线程或使用异步I / O来解除长时间运行的操作。

如果您使用线程,请记住只有一个线程可以执行GTK +调用。

您也可以通过使用类似from this answer之类的内容让GTK +处理来自回调内的待处理事件来手动解决此问题:

while Gtk.events_pending(): Gtk.main_iteration()