4

少し長い投稿になるかもしれませんが、最後までお付き合いいただきありがとうございました。ここに問題があります (かなり基本的な問題だと思います。PiSide と Qt の経験が浅いため、難しくなっています。) メイン ウィンドウに 1 つのメニュー項目 (「プロセス」と仮定します) があります。コードは次のとおりです-

from PySide import QtCore, QtGui

class Ui_MainWindow(object):

      def setupUi(self, MainWindow, AppObj):
            .
            .
            self.statusbar = QtGui.QStatusBar(MainWindow)
            self.statusbar.setObjectName("statusbar")
            MainWindow.setStatusBar(self.statusbar)
            .
            .
            .
           self.actionProcess = QtGui.QAction(MainWindow)
           self.actionProcess.setObjectName("actionProcess")
           self.actionProcess.triggered.connect(self.myappObj.menuActionProcess) 
           .

ここで、self.myappobj は、アプリのメイン ロジック コントローラーとして機能する、作成したアプリ クラスを指します。コード -

from PySide import QtCore, QtGui
from MainWindow import Ui_MainWindow

class App(QtGui.QDialog):
      def __init__(self, parent=None):
          self.__mainWindow = QtGui.QMainWindow()
          self.__mainWindowDesignContext = Ui_MainWindow()
          self.__mainWindowDesignContext.setupUi(self.__mainWindow, self)
          self.__mainWindow.show()
      def menuActionProcess(self):
          self.processThread = BatchProcesser()
          self.progressBar = QtGui.QProgressBar()
          statusBar.addWidget(self.progressBar)
          self.progressBar.show()
          self.progressBar.setMinimum(0)
          self.progressBar.setMaximum(100)
          QtCore.QObject.connect(self.processThread, QtCore.SIGNAL("progress(int)"),self.progressBar, QtCore.SLOT("setValue(int)"), QtCore.Qt.DirectConnection)
          if not self.processThread.isRunning():
              self.processThread.exiting = False
              self.processThread.start()

したがって、ここでやろうとしていることは、メイン ウィンドウを作成することであることが簡単にわかります。そこに「Process」というメニューを追加し、クリックすると、アプリ クラスのコールバック menuActionProcess メソッドがトリガーされます。ここで、プログレス バーを作成し、それをメイン ウィンドウのステータス バーにアタッチします (実際のコードには他にも多くの機能があります。ここに示すのは、必要な部分を疑似例として再配置したものです)。最後に、上記のコードで言及されている BatchProcesser クラスで、これを実行しています。

from PySide.QtGui import *
from PySide.QtCore import *

class BatchProcesser(QThread):
     __errorHappened = False
     def __init__(self, parent=None):
         QThread.__init__(self, parent)
         self.exiting = False
     def run(self):
         for a in range(101):
            print a
            QThread.msleep(100)
            self.emit(SIGNAL("progress(int)"), a)
            print a

私の理解では、これにより、メインスレッドとは異なるスレッドでステータスバーに接続されたプログレスバーが更新されるはずです。これにより、ユーザーは GUI を自由に操作できます。

今、これをリンしようとすると、[プロセス] メニューを押すまでは問題ありません。次に、プログレスバーは緩和されますが更新されず、コンソールがエラーでいっぱいになります-

0 QPixmap: GUI スレッドの外でピックスマップを使用するのは安全ではありません

QPixmap: GUI スレッドの外でピックスマップを使用するのは安全ではありません

QPixmap: GUI スレッドの外でピックスマップを使用するのは安全ではありません

QPixmap: GUI スレッドの外でピックスマップを使用するのは安全ではありません

0

1

QPixmap: GUI スレッドの外でピックスマップを使用するのは安全ではありません

QPixmap: GUI スレッドの外でピックスマップを使用するのは安全ではありません

QPixmap: GUI スレッドの外でピックスマップを使用するのは安全ではありません

QPixmap: GUI スレッドの外でピックスマップを使用するのは安全ではありません

[xcb] デキュー中にキューにある不明なリクエスト

[xcb] これはおそらくマルチスレッド クライアントであり、XInitThreads は呼び出されていません

[xcb] 中止、申し訳ありません。

python: ../../src/xcb_io.c:178: dequeue_pending_request: アサーション `!xcb_xlib_unknown_req_in_deq' が失敗しました。

中止 (コアダンプ)

私にはどんな助けも非常に必要です。エラーの元の理由を見つけたり、指摘したり、同じように修正したりすることができません。

4

1 に答える 1

5

問題は、信号をスロットに接続する方法にあります。

      QtCore.QObject.connect(self.processThread, QtCore.SIGNAL("progress(int)"),self.progressBar, QtCore.SLOT("setValue(int)"), QtCore.Qt.DirectConnection)

ここでは、DirectConnectionを明示的に適用します。これは間違っています!スロットを呼び出し元のスレッドで処理します。これは、progressBarのGUI更新が、GUIスレッドではなく、プロセススレッドで行われることを意味します。ただし、描画はGUIスレッドでのみ許可されます。

あるスレッドからの信号を別のスレッドからのスロットに接続することはまったく問題ありません。ただし、AutoConnection(スレッドを認識して使用するデフォルトQueuedConnection)またはのいずれかが必要ですQueuedConnection

この行で問題が解決するはずです。

      QtCore.QObject.connect(self.processThread, QtCore.SIGNAL("progress(int)"),self.progressBar, QtCore.SLOT("setValue(int)"), QtCore.Qt.QueuedConnection)

http://doc.qt.io/archives/qt-4.7/qt.html#ConnectionType-enumを参照してください。

于 2012-08-27T09:22:49.423 に答える