私はubuntuターミナルから文字列を読み込み、その文字列をボタンのラベルとして設定しようとしています。それはいくつかの反復のために完全に動作し、その後フリーズしたり、エラーで閉じます。私はそれが凍ったり閉じたりするときのパターンを見つけることができませんでした。私はgtkライブラリとPython 2.7を使用しています。ボタンラベルテキストの更新中にPython GUIがフリーズまたは閉じる
UIがフリーズした後のスクリーンショットを以下に示します。上記のスクリーンショットに示されているように
、それは正常値234、56を更新した後、213文字列を受信した後、エラーで終了しました。また、UIのボタンも213の値を持つことがわかります。
エラーが表示されたり終了したりすることなく、UIがフリーズすることがあります。
Iは以下のコード
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
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())
上記のコードは、(オフコース上記の3つのファイルを作成した後)python thread.py
を入力して実行することができます。この凍結問題を解決するための解決策を提案してください。
**メインループを実行する同じスレッド以外のスレッドからGTK関数を呼び出さないでください**。その代わりに、 'GLib.idle_add(...)'を使用して、GUIスレッドで関数の実行をスケジュールします。また、 'run'メソッドを決して定義しないので、' gui2'の 'Thrd'クラスは役に立ちません。 – user4815162342
@ user4815162342ご意見ありがとうございます。 'Glib.idle_add()'を追加しようとしましたが、うまくいきませんでした。たぶん、私はまだ何か間違っている。私はPythonとUIの新機能です。私はあなたの答えを受け入れることができるように、あなたは修正されたコードを答えとして掲示してください。 –
あなたの例で他の問題を修正しましたか?まず、 "Exception !!!!"と表示される汎用例外ハンドラを取り除く必要があります。これを削除すると、実際のバックトレースが提供されます。 (Python 2で走っているときは、 'input'を' raw_input'に変更しなければなりませんでした。そうでなければ、任意の文字列で発生させました。) 'vkey1'には構文エラーがあります。これらのエラーを修正したら、 'textinit'の不要なスレッドの作成を' button0.set_label(str(ch)) 'への単純な呼び出しで置き換え、' gui2.textinit() 'の呼び出しを' GLib.idle_add( gui2.textinit) '、あなたの例はうまくいきました。 – user4815162342