如何从不同进程修改TextView?
我正在制作一个图形界面(GUI)来获取推文。我创建了一个事件框,可以接收信号并更改文本视图。我使用多进程来更新文本视图,但它就是不改变。我甚至尝试过调整窗口的大小,但都没有效果。我可以获取文本视图的文本缓冲区,但就是无法修改它。
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()
我正在制作一个图形界面来获取推文。有时候,由于网络连接慢,获取时间线会非常耗时,这导致图形界面卡住。因此,我想让它创建一个进程来获取时间线并设置推文缓冲区。但我无法在推文缓冲区中设置文本。
3 个回答
0
如果你在看完所有回答后还是想继续这个方向:
免责声明:
我不知道这个回答有多有用。
解释:
我试着用你的思路。我还导入了 Queue
来在不同的进程之间共享一些数据。我觉得这是必要的,因为我在文档中看到过。你可以在下面的代码示例中找到一些其他信息。
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()
2
你必须运行主循环,才能处理渲染事件,这样东西才会显示出来。
另外,你不能在第二个线程中调用GTK的函数。
想要入门的话,可以看看这个:多线程GTK应用程序 - 第1部分:误解
这里有关于如何将这些知识应用到PyGTK的内容:PyGTK中的线程
2
我不太明白你为什么要这样做:
def go_multi(self, widget, data=None):
p = Process(target = self.change_textview)
p.start()
p.join()
因为,即使在极小的可能性下它能工作,你实际上是在调用 change_textview
函数,并等待这个过程完成。
说到这里,我觉得你根本不需要使用多进程,应该改用多线程来处理你的图形界面。
一开始让 Gtk 支持多线程可能会有点棘手,但其实并不难。
你可以通过两种方式来实现:
- 使用
GLib.idle_add
(或者GObject.idle_add
,我从来没完全搞明白为什么有时候它们不一样)来更新你的控件。 或者按照 [这里] 的说明来做。基本上它说:
在你调用
Gtk.main()
之前,先调用以下方法:GObject.threads_init() Gdk.threads_init()
在你的线程中,用以下代码包裹更新 Gtk 控件的代码:
Gdk.threads_enter() # your code here Gdk.threads_leave()