【问题标题】:GTK - program doesn't follow intended order of functionsGTK - 程序不遵循预期的功能顺序
【发布时间】:2015-04-17 15:21:26
【问题描述】:

我对这个网站很陌生,所以我希望我在提问时遵守所有规则。解决问题:

我正在制作一个使用 Glade 构建的 GTK+ / Python3 程序。当用户单击按钮读取文件时,会调用某些耗时的函数。这是一个给你一个想法的sn-p:

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. 我的生活很失败。

如果您能提供帮助,那太好了,如果您不能但可以推荐一个很棒的教程,那就太好了。我的头发不能拉太多。

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

【问题讨论】:

    标签: python multithreading gtk


    【解决方案1】:

    因为 GTK+ 重绘发生在运行回调的同一执行线程中。因此,如果您在回调中执行需要重绘的操作,那么直到回调退出后才会真正发生。

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

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

    你也可以手动解决这个问题,让 GTK+ 处理回调内部的未决事件,使用类似 from this answer 的东西:

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

    【讨论】:

    • 很棒的信息,谢谢。似乎我必须阅读有关线程和异步 I/O 的内容。我会看看,但如果你能指出我的任何地方,将不胜感激。
    猜你喜欢
    • 2017-06-08
    • 1970-01-01
    • 1970-01-01
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 2017-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多