我正在尝试从ubuntu终端读取一个字符串,并将该字符串设置为按钮的标签。它适用于某些迭代,然后冻结或关闭错误。我找不到任何关于何时冻结或关闭的模式。我使用的是gtk库和python 2.7。
下面可以看到UI冻结后的屏幕截图。
如上面的屏幕截图所示,它已成功更新值234,56,然后在收到213字符串后退出并显示错误。您还可以观察到UI中的按钮也具有213值。
有时,用户界面会冻结而不会显示任何错误或退出。
我使用了以下代码
1。 thread.py (从终端调用的主程序)
import thread
import time
import gui2
import vkeys1
import os
try:
thread.start_new_thread( vkeys1.main, ( ) )
thread.start_new_thread( gui2.main, ( ) )
except:
print "Error: unable to start thread"
# To stop this script from closing
os.system("mkfifo d1 2> error.log")
fd = os.open('d1', os.O_RDONLY)
ch = os.read(fd,1) # No writer
2. vkeys1.py (它从终端读取输入并调用textinit())
import gui2
def main() :
while True:
try :
gui2.ch = str(input('\nInput a string : '))
gui2.textinit()
except :
print(" \n\n Exception!! \n\n")
3。 gui2.py (更新按钮标签)
from gi.repository import Gtk, GdkPixbuf, Gdk, GLib
import Image
import os, sys
import time
import vkeys1
import threading
global ch # ch is used at vkeys1.py to store the input
ch = 'dummy content'
button0 = Gtk.Button(label="Initially empty")
class TableWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="String retrieval widget")
self.set_size_request(500,200)
self.connect_after('destroy', self.destroy)
self.main_box=Gtk.VBox()
self.main_box.set_spacing(5)
self.label = Gtk.Label(" ")
table = Gtk.Table(7,4, True)
self.add(self.main_box)
self.main_box.pack_start(self.label, False, False, 0)
self.main_box.pack_start(table, False, False, 0)
table.attach(button0, 0, 4, 0, 1)
self.show_all()
def destroy(window, self):
Gtk.main_quit()
def textinit(): # called from vkeys1.py
class Thrd(threading.Thread) :
def __init__(self) :
threading.Thread.__init__(self)
print('\nReceived string')
print(str(ch))
print('\n')
button0.set_label(str(ch)) # Button label updated here
Thrd2 = Thrd()
Thrd2.start()
return
def main():
app=TableWindow()
app.set_keep_above(True)
app.set_gravity(Gdk.Gravity.SOUTH_WEST)
Gtk.main()
if __name__ == "__main__":# for any error exit
sys.exit(main())
可以通过键入python thread.py
(在创建上述3个文件之后)来运行上述代码。请提出任何解决方案以克服这种冻结问题。
答案 0 :(得分:2)
崩溃的最可能原因是您的代码从运行主循环的线程以外的线程调用GTK代码,而documentation states是不允许的。
要解决此问题,请将gui2.textinit()
的来电替换为GLib.idle_add(gui2.textinit)
(请注意textinit
后缺少括号)。
关于代码的几点评论:
通用异常处理程序正在屏蔽发生的异常。删除它,当出现问题时你会看到有用的追溯。
如果您在Python 2下运行,您可能希望将input
更改为raw_input
,否则代码会阻塞任何不是有效Python表达式的输入。
textinit
创建一个永远不会运行实际线程的线程对象。从threading.Thread
继承时,必须覆盖run
函数,该函数将在调用start()
后在新线程中调用。在构造函数中完成任务不会有任何效果。
thread.start_new_thread
是一个低级API,不应在正常情况下使用,并且会在Python 3中降级为_thread
。而不是thread.start_new_thread(fn, ())
,请使用{{ 1}},具有相同的含义,并返回一个threading.Thread(target=fn)
对象。