如何从不同的进程修改textview?

时间:2012-02-14 07:59:51

标签: python twitter gtk pygtk multiprocessing

所以我正在制作一个GUI来获取推文。我制作了一个可以接收信号并更改textview的事件框。 我正在使用多处理来更改textview,但它不会改变。我甚至尝试改变窗户的大小。但没有变化。我可以获得textview的textbuffer但不能改变它。

import pygtk
pygtk.require('2.0')
import gtk
from multiprocessing import Process

class multi:
    def __init__(self):
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_size_request(800,400)
        self.window.set_title("Twitter Box")
        self.window.set_border_width(4)
        self.window.connect("destroy", self.close_application)

        self.vbox1 = gtk.EventBox()
        self.vbox1.set_size_request(750,450)
        self.vbox1.connect('leave_notify_event',self.go_multi)
        self.window.add(self.vbox1)
        self.vbox1.show()

        self.tweetview = gtk.TextView()
        self.tweetbuffer = self.tweetview.get_buffer()
        self.tweetbuffer.set_text('Why not working?')
        self.vbox1.add(self.tweetview)
        self.tweetview.show()

        self.window.show()

    def close_application(self, widget):
        gtk.main_quit()

    def go_multi(self, widget, data=None):
        p = Process(target = self.change_textview)
        p.start()
        p.join()

    def change_textview(self):
        print 'changing text'
        startiter = self.tweetbuffer.get_start_iter()
        enditer = self.tweetbuffer.get_end_iter()
        text = self.tweetbuffer.get_text(startiter, enditer)
        print text
        if text:
            self.tweetbuffer.set_text('Changed....')
        else:
            self.tweetbuffer.set_text('')
        return 

def main():
    multi()
    gtk.main()

if __name__ == '__main__':
    main()

我正在制作GUI来获取推文。有时由于连接速度慢和GUI冻结,检索时间线需要很长时间。所以,我想这样做,它会创建一个进程,它将获取时间轴并设置tweetbuffer。但是我无法在tweetbuffer中设置文本。

3 个答案:

答案 0 :(得分:2)

必须运行主循环才能处理渲染事件,然后才能看到任何内容。

此外,您不能从第二个线程调用GTK函数。

阅读本文以帮助您入门:Multi-threaded GTK applications – Part 1: Misconceptions

以下是如何将这些知识应用于PyGTK:Threads on PyGTK

答案 1 :(得分:2)

我没有完全理解你为什么这样做:

def go_multi(self, widget, data=None):
    p = Process(target = self.change_textview)
    p.start()
    p.join()

因为,即使在它应该工作的远程可能性中,你基本上都在调用change_textview函数并等待进程完成。

清除了这一点,我认为你根本不需要多处理,而是让你的gui多线程化。

一开始制作一个Gtk多线程可能有点棘手,但这不是一项艰巨的任务。
您有两种方法:

  1. 使用GLib.idle_add更新您的小部件(或GObject.idle_add,我从未完全理解为什么有时候它们不一样)
  2. 或按照[here]的说明进行操作。它基本上说:

    • 在致电Gtk.main()之前,请调用以下方法:

       GObject.threads_init()
       Gdk.threads_init()
      
    • 在您的主题中,使用以下代码包围更新Gtk小部件的代码:

       Gdk.threads_enter()
       # your code here
       Gdk.threads_leave()
      

答案 2 :(得分:0)

如果您仍希望在所有答案之后继续这样做:
免责声明:
我不知道这个答案有多大用处。
说明:
我试着用你的逻辑。我还导入了Queue以在进程之间共享一些数据。我想从documentation看到它是必要的。您可以在下面的代码示例中找到其他一些信息。

import pygtk
pygtk.require('2.0')
import gtk
from multiprocessing import Process, Queue

class multi:
    def __init__(self):
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_size_request(800,400)
        self.window.set_title("Twitter Box")
        self.window.set_border_width(4)
        self.window.connect("destroy", self.close_application)

        self.vbox1 = gtk.EventBox()
        self.vbox1.set_size_request(750,450)
        self.vbox1.connect('leave_notify_event',self.go_multi)
        self.window.add(self.vbox1)
        self.vbox1.show()
        self.tweetview = gtk.TextView()
        self.tweetbuffer = self.tweetview.get_buffer()
        self.tweetbuffer.set_text('Why not working?')
        self.vbox1.add(self.tweetview)
        self.tweetview.show()

        self.window.show()

    def close_application(self, widget):
        gtk.main_quit()

    def go_multi(self, widget, data=None):
        q = Queue()
        p = Process(target = self.change_textview, args=(q,))
        p.start()
        self.tweetbuffer.set_text(q.get())
        p.join()

    def change_textview(self, q):
        print 'changing text'
        startiter = self.tweetbuffer.get_start_iter()
        enditer = self.tweetbuffer.get_end_iter()
        text = self.tweetbuffer.get_text(startiter, enditer)
        print text
        if text:
            q.put(('Changed....'))
        else:
            q.put((''))
def main():
    multi()
    gtk.main()

if __name__ == '__main__':
    main()