Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

syncing issues and application not closing upon exit of window



  • I wrote a progam that takes data from an instrument and paints graphics on the screen representing the data using qpainter. I'm using a loop that implements QApplication.processEvents() at the end and an gui.updateGraphics() fn that tells the interface when to update. the application lingers when the window is closed, so i added a conditional at the end of the loop that breaks if the esc key is hit, but the issue still persists.

    if __name__ == "__main__":
        vars.t0 = time.clock()
        app = QApplication(sys.argv)
        gui = interfaceLab.indicators()
        gui.show()
    
        dev.devConnect()
        scope1 = vars.scope1
        # scope2 = vars.scope2
        dev.initLJ()
        dev.initScope(scope1)
        # dev.initScope(scope2)
        dev.ioConfig(scope1)
        # dev.ioConfig(scope2)
    
        while True:
            dev.acqConfig(scope1)
            w1 = dev.getDataCh1(scope1)
            scaled_wave1 = dev.scaleWave(w1,scope1)
            w2 = dev.getDataCh2(scope1)
            scaled_wave2 = dev.scaleWave(w2,scope1)
            w3 = dev.getDataCh3(scope1)
            scaled_wave3 = dev.scaleWave(w3,scope1)
            w4 = dev.getDataCh4(scope1)
            scaled_wave4 = dev.scaleWave(w4,scope1)
    
            # dev.acqConfig(scope2)
            # h1 = dev.getDataCh1(scope2)
            # scaled_waveH1 = dev.scaleWave(h1,scope2)
            # h2 = dev.getDataCh2(scope2)
            # scaled_waveH2 = dev.scaleWave(h2,scope2)
    
            tempAIN0 = dev.getDataLJAIN0()
            tempAIN1 = dev.getDataLJAIN1()
            tempAIN2 = dev.getDataLJAIN2()
            tempAIN3 = dev.getDataLJAIN3()
    
            vars.temp1 = tempAIN0
            vars.temp2 = tempAIN1
            vars.temp3 = tempAIN2
            vars.temp4 = tempAIN3
    
            vars.primP = activePowerPrim*10000
            vars.secP = activePowerSec*10000
    
           if vars.esc == True:
                dev.errorCheck(scope1)
                dev.closeAll(scope1)
                break
    

    the interface file is:

    class indicators(QWidget):
        vars.t0 = time.clock()
        update_grahics = False # flag for updating graphics
        global windowDim # global variable for window dimensions
        global windowPos # global variable for window dimensions
        screenRes = [1920,1080] # screen dimensions [x,y]
        windowDim = [1750,960]  # window dimensions [x,y]
        windowPos = [(screenRes[0]-windowDim[0])/2,(screenRes[1]-windowDim[1])/2]   # window position [x,y]
    
        #class initialization
        def __init__(self):
            super().__init__()
            self.initUI() # run initUI fn
    
        #fn to initialize UI
        def initUI(self):
            self.setGeometry(windowPos[0], windowPos[1], windowDim[0], windowDim[1]) # build screen
            self.setWindowTitle('Megatron') # set window title
    
            # Set window background color
            self.setAutoFillBackground(True)
            p = self.palette()
            p.setColor(self.backgroundRole(), Qt.black)
            self.setPalette(p)
            self.show()
    
        def keyPressEvent(self, e):
            if e.key() == Qt.Key_Escape:
                vars.esc = True
                self.close()
    
        #fn that triggers graphics update
        def updateGraphics(self):
            self.update_graphics = True # set update flag to true
            self.repaint() # repaint
    
        #fn to paint
        def paintEvent(self, event):
            qp = QPainter() # create instance of qpainter
            qp.begin(self) # begin painting
            qp.setRenderHint(QPainter.Antialiasing) # render with antialiasing
            self.graphics(qp) # evaluate graphics function, pass in qpainter
            qp.end() # end painting
    
        def graphics(self, qp):
            if self.update_graphics:
    
    

    lots of painting here, such as this 'lcd', then:

        #lcds
                scaleFact = 1/(self.logicalDpiX()/96)
                numRows = 12
                numColumns = 3
                rectDim = [windowDim[0]/numColumns,windowDim[1]/numRows]
                padding = 10
                digs = 5
                fontSize = int(rectDim[0]*rectDim[1]/1490)
                qp.setFont(QtGui.QFont("Agency FB", fontSize*scaleFact, QtGui.QFont.Bold))
                qp.setPen(QPen(QColor(226, 47, 223)))
        
    
            gui.updateGraphics()
            QApplication.processEvents()
    
            # print("Active Primary Power: {} kW".format(vars.primP))
            # print("Active Secondary Power: {} kW".format(vars.secP))
            
            self.update_graphics = False # set the flag back to False
    
        sys.exit(app.exec_())
    

    my question is, is there a better way to be controlling when this gui is updating than a loop with this flag scheme (such as eventtimer?) also: i've gotten a few thread errors in the past, do I need to implement threading? and most importantly how do I close this, some sort of closeEvent?!


  • Lifetime Qt Champion

    Hi,

    What about using the approach of the mandelbrot example ?

    You'll render your graphic in a secondary thread and send a ready to show QImage to your GUI.



  • thank you; this example may be helpful, i will play around with it.



  • ok i don't think i actually need to add threading now (but i may at some point later), but the problem of closing the window AND the program still remains. is there a 'on window close' pyqt fn? or is there something i'm forgetting to do to close Qapplication?


  • Lifetime Qt Champion

    The QWidget::closeEvent method is likely what you are looking for.



  • I never create a QWidget. I just removed app.exec_() from sys.exit(app.exec_()) leaving just sys.exit() at the end of my program, this seemed to fix it. My program is just an infinite loop that closes upon hitting the esc key or close the window through closeEvent, so do I just not need the app.exec_() argument?


  • Lifetime Qt Champion

    I misread your sample code.

    You should rather move that infinite loop in its own thread. What you are doing is that you are blocking the event loop so it can't process correctly.

    Again, the mandlebrot example shows a nice way to do that.



  • @SGaist thanks for your help!


  • Lifetime Qt Champion

    You're welcome !

    Since you have it working now, please mark the thread as solved using the "Topic Tools" button so that other forum users may know a solution has been found :)


Log in to reply