0

メイン ウィンドウ ラッパー クラス (たとえば A) と、ラッパーで使用される別のクラス (たとえば B) があります。B には、subprocess.check_call(command) 呼び出しを順番に持つメソッドがあります。このプロセスと通信し、メイン ウィンドウ QTextEdit に Qprocess stdout と stderr を表示し、メイン ウィンドウ QLineEdit から Qprocess stdin にデータを送り返すために、QProcess を使用するように変更しています。

そのために私は持っています:

class A(....):
   def __init__(self):
      ....
      QtCore.QObject.connect(self.ui.actionNew, QtCore.SIGNAL("triggered()", self.selectedNew)
      self.qprocess = QtCore.QProcess()
      self.connect(self.qprocess, QtCore.SIGNAL("readyReadStandardOutput()", self.readStdOut)
      self.connect(self.qprocess, QtCore.SIGNAL("readyReadStandardError()", self.readStdErr)

    def readStdOut(self):
        self.ui.text_edit.append(QtCore.QString(self.qprocess.readAllStandardOutput()))

    def readStdErr(self):
        self.ui.text_edit.append(QtCore.QString(self.qprocess.readAllStandardError()))

    def selectedNew(self:)
        ...
        newB = B(self.qprocess)
        newB.doWork(params)

 class B():
     def __init__(self, qprocess):
         self.qp = qprocess

     def doWork(params):
         ...
         # creating a thread to not block the main thread
         class ConsoleThread(threading.Thread):

             def __init__(self, qprocess):
                self.tqp = qprocess
                threading.Thread.__init__(self)

             def run(self):
                 self.qtp.execute("script_that_waits_for_user_input_during_execution")

          # starting the thread and passing it the QProcess instance from B
          ConsoleThread(self.qp).start()
          print(self.qp.state()) # this returns 0, when I expected 2, obviously something wrong

最後に、「script_that_waits_for_user_input_during_execution」の出力はQTextEditに表示されませんが、コンソールにはまだ出力されています。A に信号が返されていないようで、 A.readStdOut() メソッドに到達していません。一般的な考え方は、さまざまなコマンド ライン スクリプトをラップする GUI アプリを用意することです。したがって、QProcess から出力を正しく取得し、GUI から書き込むことで通信できるようにする方法が必要です。もちろん、関数を B から A に移動すれば (不要な手順がなくなるため)、おそらくそれほど複雑ではないかもしれませんが、同時に、GUI ラッパーはロジックから分離する必要があると思います。

ありがとう!

4

1 に答える 1

1

QProcessこの例では多くの奇妙なことを行っているため、 a の使用を誤解している可能性があると思います。

  1. クラス A のインスタンスは、メンバーとして作成された QProcess を取得し、信号が接続されます
  2. が呼び出されるたびselectedNew()に、B の新しいインスタンスが作成され、毎回同じ QProcess インスタンスが渡されます。
  3. doWorkが呼び出され、毎回ローカル クラス定義が作成されますが、インスタンスを作成してクラスを破棄するだけです。スレッドは、自由に実行される新しい QProcess を作成する QProcess インスタンスで staticmethod を呼び出します。
  4. では、あたかも QProcess インスタンスにずっと何かが起こったかのように、asych スレッドを開始した直後に右doWorkの状態を確認します。QProcess

主に、毎回新しいプロセスを開始するスレッドがあり、元のプロセスが開始されていないために変更されていない値を確認します。また、シグナルは元のプロセスに関連付けられているため、呼び出されることはありません。この状況全体を単純化するために必要なのは、実行するたびに新しい QProcess だけです。

Aまず、そのクラスを実際に適切に動作するものにクリーンアップしましょう。

class A():
    def __init__(self):
      ...
      self.ui.actionNew.triggered.connect(self.selectedNew)

    def readStdOut(self):
        self.ui.text_edit.append(str(self.qprocess.readAllStandardOutput()))

    def readStdErr(self):
        self.ui.text_edit.append(str(self.qprocess.readAllStandardError()))

    def selectedNew(self):
        ...
        qprocess = QtCore.QProcess(self)
        qprocess.readyReadStandardOutput.connect(self.readStdOut)
        qprocess.readyReadStandardError.connect(self.readStdErr)

        qprocess.start("script_that_waits_for_user_input", params)

        print qprocess.state() == qprocess.Running

init で QProcess を作成する代わりに、何かを実行したいときにオンデマンドで作成します。次に、そのインスタンスのシグナルをスロットに接続し、QProcess で start を呼び出します。これにより、実際にプロセスが開始され、スロットが呼び出されます。

Bコマンドラインスクリプトを別のクラスにラップしたい場合を除き、クラスを何に使用するつもりなのかわかりません。その場合、 QProcess の作成を完全に class に移動し、クラスシグナルをメンバーにB接続します。Ab_instance.qprocess

アップデート

この QProcess の責任をBクラスに移して、さまざまな種類の作業を実行するさまざまなクラス タイプを使用できるようにするには、次のようにします。

class A(QtGui.QMainWindow):
    ...

    def readStdOut(self):
        qprocess = self.sender()
        self.ui.text_edit.append(QtCore.QString(qprocess.readAllStandardOutput()))

    def readStdErr(self):
        qprocess = self.sender()
        self.ui.text_edit.append(QtCore.QString(qprocess.readAllStandardError()))


    def selectedNew(self):
        ...
        b = B()
        b.qprocess.readyReadStandardOutput.connect(self.readStdOut)
        b.qprocess.readyReadStandardError.connect(self.readStdErr)

        b.doWork(params)

        print b.qprocess.state() == qprocess.Running


class B(QtCore.QObject):
    def __init__(self):
        ...
        self.qprocess = QtCore.QProcess(self)

    def doWork(params):
        ...
        self.qprocess.start("script_that_waits_for_user_input", params)

クラスAは の新しいインスタンスを作成し、のプロセスBのシグナルをB独自のスロットに接続します。次に、コマンドのパラメーターを指定して を呼び出しますdoWorkB実際にスレッドを開始し、それを所有します。

于 2012-08-23T23:47:23.870 に答える