Search code examples
pythonpython-2.7pyqtpyqt4qtextbrowser

PyQt keeps closing most likely due to timer error


I am trying to get a line of text to display in the pyqt4 text browser. I am able to get it to display, but whenever I start to resize the window while I am running the function the PyQt window closes. Currently, it just closes without display errors or anything else. Before it would display this error:

QObject::startTimer: timers cannot be started from another thread

I have tried both .append() and .instertPlainText(). The append is where I got the error from. Thank you for your help, sorry if this is unclear.

Here is my code:

class MyForm(QtGui.QMainWindow):                                                                               
   def __init__(self, parent=None):                                                                         
      QtGui.QWidget.__init__(self, parent)                                                                           
      self.ui = Ui_MainWindow()                                                                          
      self.ui.setupUi(self)
      self.stopAutoRun=0
      self.ui.autoButton.clicked.connect(self.autoRun)
      self.waitTime=.2
   '''
   ________________________________________________________________________________
                                          autoRun
   Description: will continously look for a new JSON file and process it once it appears
  _______________________________________________________
  '''
  def autoRun(self):
     self.task1=threading.Thread(target=self.autoRunThread)                                                                                                        
     self.task1.setDaemon(True)                                                                                                                      
     self.task1.start()

  def autoRunThread(self):
     self.task1=threading.currentThread()
     while getattr(self.task1,"run",True):
        commands=powerSupply.setValuesFile()
        data=powerSupply.readValues()
        self.ui.commandOutput.insertPlainText(str(data))
        time.sleep(self.waitTime)

ui:

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(1270, 805)
        MainWindow.setMinimumSize(QtCore.QSize(0, 0))
        MainWindow.setMouseTracking(True)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.verticalLayout_3 = QtGui.QVBoxLayout(self.centralwidget)
        self.verticalLayout_3.setObjectName(_fromUtf8("verticalLayout_3"))
        spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
        self.verticalLayout_3.addItem(spacerItem)
        self.gridLayout_3 = QtGui.QGridLayout()
        self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3"))
        self.verticalLayout = QtGui.QVBoxLayout()
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
        spacerItem1 = QtGui.QSpacerItem(20, 60, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
        self.verticalLayout.addItem(spacerItem1)
        self.openButton = QtGui.QPushButton(self.centralwidget)
        self.openButton.setMinimumSize(QtCore.QSize(140, 28))
        self.openButton.setMaximumSize(QtCore.QSize(140, 28))
        self.openButton.setObjectName(_fromUtf8("openButton"))
        self.verticalLayout.addWidget(self.openButton)
        spacerItem2 = QtGui.QSpacerItem(20, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
        self.verticalLayout.addItem(spacerItem2)
        self.runButton = QtGui.QPushButton(self.centralwidget)
        self.runButton.setMinimumSize(QtCore.QSize(140, 28))
        self.runButton.setMaximumSize(QtCore.QSize(140, 28))
        self.runButton.setObjectName(_fromUtf8("runButton"))
        self.verticalLayout.addWidget(self.runButton)
        spacerItem3 = QtGui.QSpacerItem(20, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
        self.verticalLayout.addItem(spacerItem3)
        self.autoButton = QtGui.QPushButton(self.centralwidget)
        self.autoButton.setObjectName(_fromUtf8("autoButton"))
        self.verticalLayout.addWidget(self.autoButton)
        spacerItem4 = QtGui.QSpacerItem(20, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
        self.verticalLayout.addItem(spacerItem4)
        self.stopAutoButton = QtGui.QPushButton(self.centralwidget)
        self.stopAutoButton.setObjectName(_fromUtf8("stopAutoButton"))
        self.verticalLayout.addWidget(self.stopAutoButton)
        spacerItem5 = QtGui.QSpacerItem(20, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
        self.verticalLayout.addItem(spacerItem5)
        self.outputButton = QtGui.QPushButton(self.centralwidget)
        self.outputButton.setMinimumSize(QtCore.QSize(140, 28))
        self.outputButton.setMaximumSize(QtCore.QSize(140, 28))
        self.outputButton.setStyleSheet(_fromUtf8("\n"
""))
        self.outputButton.setObjectName(_fromUtf8("outputButton"))
        self.verticalLayout.addWidget(self.outputButton)
        spacerItem6 = QtGui.QSpacerItem(20, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
        self.verticalLayout.addItem(spacerItem6)
        self.powerOffButton = QtGui.QPushButton(self.centralwidget)
        self.powerOffButton.setStyleSheet(_fromUtf8("background-color: rgb(255, 0, 0);"))
        self.powerOffButton.setObjectName(_fromUtf8("powerOffButton"))
        self.verticalLayout.addWidget(self.powerOffButton)
        spacerItem7 = QtGui.QSpacerItem(20, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
        self.verticalLayout.addItem(spacerItem7)
        self.powerButton = QtGui.QPushButton(self.centralwidget)
        self.powerButton.setMinimumSize(QtCore.QSize(140, 28))
        self.powerButton.setMaximumSize(QtCore.QSize(100, 28))
        self.powerButton.setMouseTracking(True)
        self.powerButton.setAcceptDrops(False)
        self.powerButton.setStatusTip(_fromUtf8(""))
        self.powerButton.setStyleSheet(_fromUtf8("background-color: rgb(255, 0, 0);"))
        self.powerButton.setObjectName(_fromUtf8("powerButton"))
        self.verticalLayout.addWidget(self.powerButton)
        spacerItem8 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
        self.verticalLayout.addItem(spacerItem8)
        self.gridLayout_3.addLayout(self.verticalLayout, 0, 0, 1, 1)
        self.horizontalLayout_2 = QtGui.QHBoxLayout()
        self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2"))
        self.verticalLayout_2 = QtGui.QVBoxLayout()
        self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
        self.label = QtGui.QLabel(self.centralwidget)
        self.label.setObjectName(_fromUtf8("label"))
        self.verticalLayout_2.addWidget(self.label)
        self.commandInput = QtGui.QTextBrowser(self.centralwidget)
        self.commandInput.setMinimumSize(QtCore.QSize(600, 300))
        self.commandInput.setObjectName(_fromUtf8("commandInput"))
        self.verticalLayout_2.addWidget(self.commandInput)
        self.horizontalLayout_2.addLayout(self.verticalLayout_2)
        self.gridLayout_3.addLayout(self.horizontalLayout_2, 0, 1, 1, 1)
        self.verticalLayout_3.addLayout(self.gridLayout_3)
        self.label_2 = QtGui.QLabel(self.centralwidget)
        self.label_2.setObjectName(_fromUtf8("label_2"))
        self.verticalLayout_3.addWidget(self.label_2)
        self.commandOutput = QtGui.QTextBrowser(self.centralwidget)
        self.commandOutput.setMaximumSize(QtCore.QSize(16777215, 100))
        self.commandOutput.setObjectName(_fromUtf8("commandOutput"))
        self.verticalLayout_3.addWidget(self.commandOutput)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 1270, 26))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
        self.openButton.setToolTip(_translate("MainWindow", "manually chose a JSON file to run", None))
        self.openButton.setText(_translate("MainWindow", "Open File", None))
        self.runButton.setToolTip(_translate("MainWindow", "runs the chosen JSON file", None))
        self.runButton.setText(_translate("MainWindow", "Run File", None))
        self.autoButton.setToolTip(_translate("MainWindow", "starts to automatically run new JSON files in directory", None))
        self.autoButton.setText(_translate("MainWindow", "Auto Run", None))
        self.stopAutoButton.setToolTip(_translate("MainWindow", "Stops the auto run funtion", None))
        self.stopAutoButton.setText(_translate("MainWindow", "Stop Auto Run", None))
        self.outputButton.setToolTip(_translate("MainWindow", "changes where the file is being stored during while this GUI instance is open", None))
        self.outputButton.setText(_translate("MainWindow", "Change Output File", None))
        self.powerOffButton.setToolTip(_translate("MainWindow", "Turns off Voltage output", None))
        self.powerOffButton.setText(_translate("MainWindow", "Voltage Off", None))
        self.powerButton.setToolTip(_translate("MainWindow", "Closes Voltage Output and shuts down GUI", None))
        self.powerButton.setText(_translate("MainWindow", "Voltage Off and Exit", None))
        self.label.setText(_translate("MainWindow", "Command Input", None))
        self.label_2.setText(_translate("MainWindow", "Command Output", None))

Solution

  • The main thread is the only thread where the GUI should be updated, if you want to update any part of the view from another thread you must use the signals, in your case:

    class MyForm(QtGui.QMainWindow):  
        signal = QtCore.pyqtSignal(str)
    
        def __init__(self, parent=None):                                                                         
            QtGui.QMainWindow.__init__(self, parent) 
            self.ui = Ui_MainWindow()                                                                          
            self.ui.setupUi(self)
            self.signal.connect(self.ui.commandOutput.insertPlainText)
            [...]
    
        def autoRun(self):
            [...]
    
        def autoRunThread(self):
            self.task1=threading.currentThread()
            while getattr(self.task1,"run",True):
                commands=powerSupply.setValuesFile()
                data=powerSupply.readValues()
                self.signal.emit(str(data))
                time.sleep(self.waitTime)