PyQt: обновление графического интерфейса пользователя из обратного вызова

Используя Python3 и PyQt4, у меня есть функция (run), которая принимает в качестве входных данных вызываемый объект для предоставления обновлений статуса.

class Windows(QtGui.QWidget):
    # Creates a widget containing:
    # - a QLineEdit (status_widget)
    # - a button, connected to on_run_clicked

    def on_run_clicked(self):
        def update(text):
            self.widget.setText(text)

        threading.Thread(target=run, args=(update, )).start()

Это работает нормально (т.е. текстовые обновления правильно отображаются в виджете). Однако, когда я заменяю QLineEdit на QTextEdit и использую метод append для добавления текста, я получаю:

QObject :: connect: невозможно поставить в очередь аргументы типа 'QTextCursor'

(Убедитесь, что QTextCursor зарегистрирован с помощью qRegisterMetaType ().)

Он по-прежнему работает, но указывает на то, что я делаю что-то не так, и я не уверен, что продолжу работать, когда будет больше активных потоков. Обычно я делаю этот тип обновлений, используя сигналы и слоты, но функция run не зависит от PyQt. Вопросы следующие:

  1. Почему это работает без предупреждения для QLineEdit, а не для QTextEdit?
  2. Как правильно поступать в такой ситуации?

person Hernan    schedule 23.08.2012    source источник


Ответы (1)


Я не знаю конкретной причины, по которой один класс работает, а другой - нет, и я не знаю разницы между использованием потоков Python и потоков Qt ... однако я могу сказать вам, что это очень временно, если вы не настраивайте его должным образом. А именно, вы не можете (или, по крайней мере, не должны) изменять объекты GUI из потока. Опять же, не уверен, в чем разница между питоном и потоком Qt. Но безопасный способ изменить ваш интерфейс из графического интерфейса - посылать сигналы в ваше окно ... самый простой способ, который я знаю, - это потоки Qt.

class MyThread(QtCore.QThread):
    updated = QtCore.pyqtSignal(str)

    def run( self ):
        # do some functionality
        for i in range(10000):
            self.updated.emit(str(i))

class Windows(QtGui.QWidget):
    def __init__( self, parent = None ):
        super(Windows, self).__init__(parent)

        self._thread = MyThread(self)
        self._thread.updated.connect(self.updateText)

        # create a line edit and a button

        self._button.clicked.connect(self._thread.start)

    def updateText( self, text ):
        self.widget.setText(text)
person Eric Hulser    schedule 23.08.2012
comment
Этот вопрос является хорошей отправной точкой для решения проблемы потоков Python и Qt. Резюме: всегда используйте потоки Qt при взаимодействии с Qt; в противном случае используйте потоки Python. - person ekhumoro; 23.08.2012
comment
Что является правильным, если вы не контролируете функцию запуска, но можете дать ей обратный вызов? Кажется, проще всего выполнить излучение функции обратного вызова, верно? Кроме того, это сообщение labs.qt.nokia.com / 2010/06/17 / youre-do-it-mis говорит, что вам не следует создавать подкласс QThread, применимо ли это также к PyQt? - person Hernan; 24.08.2012
comment
Ха, это интересно - я такого раньше не видел. Мне нужно будет прочитать это более подробно. Я отражаю комментарии в этом потоке, если вы не должны создавать подкласс QThread, то их документация сильно устарела ... - person Eric Hulser; 24.08.2012
comment
@EricHulser Ага. Кажется, это так. Здесь есть интересный пост на C ++ mayaposch.wordpress.com/2011/11/01/ - person Hernan; 24.08.2012