2011-01-28 8 views
2

私は、GUIを備えたマルチスレッドのPythonプログラムを作成しています。いくつかのモジュールは、テキストと背景色を変更してGUIに「触れて」います。私は現在PyGTKを使用しており、GUIが「サイレント」(エラーメッセージなし、プログラムが終了する)時にクラッシュし、セグメンテーションフォルトが発生することがあります。マルチスレッドPythonプログラムに最適なGUIフレームワークはどれですか?

This siteは、GTKは完全にスレッドセーフではなく、PyGTKマルチスレッドプログラミングは手間がかかります。問題を起こす可能性の少ないマルチスレッドプログラム用のPython GUIフレームワークが優れていますか?

+1

GTKはスレッドセーフではありませんが、それは、あなたは間違いなくGTKを使用して、マルチスレッドコードを書くことができますので、注意してくださいスレッドの。しかし、GTKを使ってマルチスレッドコードを書くことは、GTKを使ってマルチスレッドコードを書こうとすると、実際には難しいかもしれません。 – mouad

答えて

4

ああ、私は間違いなくPyQt4をお勧めします。最初に、私はすべてSIGNALEMITナンセンスを得ていませんでしたが、これでプログラムを作ったので、QThreadモジュールは驚くほど便利です。

安定性に関して、私はこれまでずっとクラッシュしたことはありません。私は半機能コードをデバッグしていましたが、QTには何の問題もありませんでした。それは無効なシグナルスロットを持つボタンをクリックするたびにコンソールウィンドウにエラーを投げただけです。

GTKは、一方では、何も間違いなくまったくスプラッドしています。あなたの非常に記述的でフレンドリーなSegmentation Fault。それが、私がPyQtがうまく動作することがわかった理由の1つでした。エラーが発生すると、実際に何が間違っているのかが分かります。

私はそれが個人的な好みだと確信していますが、もう1つは、Mac、Linux、Windows上のネイティブなGUIです。 Windows上のGTK +(私は間違ってはいません。私はUbuntuを使用しています)は、このX-orgの感覚を持っています。

幸運を祈る!


だけPyQtは、もう少し魅力的にするために、ここにアプリケーションをバインド私の本からの抜粋は、(それは少し厄介です)です:

class Binder(QtCore.QThread): 
    ''' 
    Class for binding the actual book 
    ''' 

    def __init__(self, parent = None): 
    super(Binder, self).__init__(parent) 



    def initialize(self, pages, options, outfile): 
    self.pages = pages 
    self.options = options 
    self.outFile = outfile 

    self.book = organizer.Book() 
    self.enc = Encoder(self.options) 
    self.ocr = ocr.OCR(self.options) 

    self.connect(self.enc, QtCore.SIGNAL('updateProgress(int, int)'), self.updateProgress) 



    def updateProgress(self, percent, item): 
    self.emit(QtCore.SIGNAL('updateProgress(int, QString)'), int(percent), 'Binding the book...') 
    self.emit(QtCore.SIGNAL('updateBackground(int, QColor)'), int(item), QtGui.QColor(170, 255, 170, 120)) 

    if int(percent) == 100: 
     time.sleep(0.5) 
     self.emit(QtCore.SIGNAL('finishedBinding')) 



    def run(self): 
    self.die = False 

    for page in self.pages: 
     self.add_file(page, 'page') 

    if not self.die: 
     self.analyze() 

    if not self.die: 
     self.book.get_dpi() 

    if self.options['ocr'] and not self.die: 
     self.get_ocr() 

    if not self.die: 
     self.enc.initialize(self.book, self.outFile) 
     self.enc.start() 
+1

信号とスロットは、最近のPyQtとPySideは、それらに本当に素晴らしいインターフェースを提供します。 –

+2

また、新しいPyQtsの新しいスタイルのシグナルを見てみましょう。これはSignalとSlotsの使い方をあまり冗長にしていません:http://stackoverflow.com/questions/4031489/why-is-pyqt-connect-syntax-so-verbose/4032125#4032125 – sateesh

+0

うわー、それはかなりクールです。ありがとう! – Blender

0

あなたがスレッドからGUIを更新する場合は、あなたがかもしれませんgobject.idle_add()を使用して、GUI更新機能が後でループで呼び出されるようにするには、QtのようなほとんどのGUIフレームワークでは、メインループがアイドル状態のときに後で呼び出されるコールバックを追加する必要があります。 GTKは、gtk.gdk.lockコンテキストマネージャを使用するか、またはgtk.gdk.threads_entergtk.gdk.threads_leaveをGUI呼び出しの周りに呼び出して、スレッドからGUI関数を呼び出すこともサポートしています。

gobject.idle_add(lambda: window.whatever(arg1, arg2)) 

それとも、実行します:

だからどちらかを行う

with gtk.gdk.lock: 
    window.whatever(arg1, arg2) 
+1

GTK +では、メインスレッドの外からUIを更新したい場合はg_threads_ {enter、leave}が必要です。そうしないと、異常なメッセージやエラーメッセージが無作為にクラッシュする可能性があります。ただし、Windowsではサポートされていないため、クロスプラットフォームのアプリケーションではg_idle_addを使用する必要があります。 –

+0

ああ、今、私は自分のアプリでg_threads_enter/g_threads_leaveを呼び出していたことを覚えています。私はそれを私の答えに追加します、ありがとう。 –

関連する問題