0

私は自分のペットプロジェクトを開発しています。Facebook から受信トレイ フォルダーをダウンロードする小さなアプリです。CLI と GUI (PyQt) モードの両方で利用できるようにしたい。私の考えは、通信用のクラスを作成し、次にフロントエンドを作成するというものでした。ダウンロード プロセスがブロックされていることはわかっていますが、これは CLI モードでは問題ありませんが、GUI では問題です。あることはわかっていますがQNetworkAccessManager、すでに作成したクラスを再実装してから、2 つのクラスを同時に維持する必要があります。

私はしばらく探していましたが、オブジェクトを作成してメソッドを使用するよりもサブクラスQObjectFBクラスをサブクラス化し、信号を実装する1つのソリューションを思いつきましたが、トレッドの作成と停止に注意する必要があります。QThreadmoveToThread()

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 を提供するためです。

4

0 に答える 0