私は自分のペットプロジェクトを開発しています。Facebook から受信トレイ フォルダーをダウンロードする小さなアプリです。CLI と GUI (PyQt) モードの両方で利用できるようにしたい。私の考えは、通信用のクラスを作成し、次にフロントエンドを作成するというものでした。ダウンロード プロセスがブロックされていることはわかっていますが、これは CLI モードでは問題ありませんが、GUI では問題です。あることはわかっていますがQNetworkAccessManager
、すでに作成したクラスを再実装してから、2 つのクラスを同時に維持する必要があります。
私はしばらく探していましたが、オブジェクトを作成してメソッドを使用するよりもサブクラスQObject
とFB
クラスをサブクラス化し、信号を実装する1つのソリューションを思いつきましたが、トレッドの作成と停止に注意する必要があります。QThread
moveToThread()
Python クラスを何かにラップして、次のように動作させることは可能QNetworkAccessManager
ですか? したがって、メソッドはすぐに戻り、オブジェクトはデータの準備ができるとシグナルを発します。
更新
コメントありがとうございます。私は2つのメインクラスを持っています。最初のものはSimpleGraph
単に非表示に呼び出されますurllib2.urlopen()
。クエリを準備し、Facebook から取得したデコードされた json を返します。実際の作業はFBMDown
クラスで行われています。
class FBMDown(object):
def __init__(self, token):
self.graph = SimpleGraph(token)
self.last_msg_count = 0
def _message_count(self, thread_id):
#TODO: Sanitize thread_id
p = {'q': 'SELECT message_count FROM thread WHERE thread_id = {0} LIMIT 1'.format(thread_id)}
self.last_msg_count = int(self.graph.call(params=p, path='fql')['data'][0]['message_count'])
return self.last_msg_count
したがって、ここで_message_count
が呼び出されると、指定されたスレッド ID のメッセージ数が返されます。この方法は CLI モードでうまく機能し、ブロッキングは問題になりません。このクラスを (可能であれば) のようQNetworkAccessManager
に非同期で動作するクラスにラップしたいので、GUI をブロックすることはありませんが、データの準備ができたときにシグナルを発します。私が今知っている唯一のテクニックは、 をサブクラス化することQObject
です。次のようになります。
class QFBMDown(QtCore.QObject):
msg_count_signal = QtCore.pyqtSignal(int)
def __init__(self, parent=None):
QtCore.QObject.__init__(self, parent)
def get_msg_count(self):
#Here happens the IO
time.sleep(2)
self.msg_count_signal.emit(1)
そして、これは私のWindowsクラスです:
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.centralwidget = QtGui.QWidget(self)
self.button_getmsgcount = QtGui.QPushButton(self.centralwidget)
self.setCentralWidget(self.centralwidget)
self.i = 0
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.block_indicator)
self.timer.start(20)
#self.worker = QtCore.QThread()
self.fbobj = QFBMDown()
#self.fbobj.moveToThread(self.worker)
#self.worker.start()
self.button_getmsgcount.clicked.connect(self.fbobj.get_msg_count)
self.fbobj.msg_count_signal.connect(self.show_msg_count)
def block_indicator(self):
self.button_getmsgcount.setText(str(self.i))
self.i += 1
def show_msg_count(self, data):
print 'Got {0} msgs in the thread'.format(data)
ボタンを押すと、GUIがブロックされます。13、15、16行目のコメントを外すと(スレッドを作成し、fbobj
このスレッドに移動してから開始します)、ブロックされず、ほぼ希望どおりに機能しますが、毎回手動ですべてを行う必要があり、スレッドのシャットダウンを処理します (現在、終了する前にスレッドをシャットダウンするQMainWindow
の メソッドを実装していますが、これは正しい方法ではないと確信しています)。closeEvent
私がやりたいことは可能ですか?新しいクラスを実装して、同じことをしている 2 つのクラスを維持したくありません。私がこのようにすることを強く主張している理由は、私のアプリを Qt なしで動作させるためですが、コマンドライン引数を入力したくない人のために素敵な GUI を提供するためです。