Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. UI scrambling, painter not active using QCheckbox() in PyQT
Forum Updated to NodeBB v4.3 + New Features

UI scrambling, painter not active using QCheckbox() in PyQT

Scheduled Pinned Locked Moved Unsolved Qt for Python
9 Posts 3 Posters 1.1k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    kgenbio
    wrote on last edited by
    #1

    I have a fairly large QT app that is having an issue where I am trying to update a QToggle() pragmatically and it periodically causes my whole UI to look scrambled.

    My app is started with a QMainWindow that also creates a QWidget, in a layout, on the main window called "fluid control". This fluidic control is an attribute to the QMainWindow class, and I am familiar with how signal/slots work to update the UI. Since fluid control is an an attribute to the QMainWindow, as long as the same thread that spawned the fluidic control widget is the one updating the UI, it should be fine.

    This fluid control widget updates many spin boxes, buttons, etc. However, what messes up the UI is QCheckbox(), specifically when I try to update its state (and widget UI) programmatically .

    @pyqtSlot(bool)
    def update_vol_toggle_slot(self, toggle):
        self.dispense_vol_toggle.setChecked(toggle)
    

    The code above is how I update the toggle. When it messes up I get the error:

    QPainter::begin: Paint device returned engine == 0, type: 3
    QPainter::setCompositionMode: Painter not active
    QPainter::fillRect: Painter not active
    QPainter::end: Painter not active, aborted
    

    Is there a safer or better way to update a QCheckbox() programmatically

    Pl45m4P 1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      Any chances you are calling that slot directly from a different thread ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      1
      • K Offline
        K Offline
        kgenbio
        wrote on last edited by kgenbio
        #3

        @SGaist Hello, I creating the QWidget() which contains this slot/signal from my UI thread.

        I spawn my UI, which creates a QWidget called FluidicControl, which contains a QGridLayout PumpUiDevice. No threading or multiprocessing anywhere for any of these.

        Despite what I said above, is this issue indicative of the slot being called from the wrong thread? If that was the error is from then somehow I must be mistaken. Below is a small example of how everything is called. do QWidgets() start their own thread behind the scenes for event handling?

        class Ui(QtWidgets.QMainWindow):
        
            def __init__(self):
                self.fluidic_ui = FluidicControl()
        
        class FluidicControl(QtWidgets.QWidget):
            def __init__(self):
                self.pump_ui = PumpUiDevice()
        
        class PumpUiDevice(QGridLayout):
            update_vol_toggle_s = pyqtSignal(bool)
        

        Edit: another important thing I just want to make sure i am right on, the signal is being fired from a separate thread, but I thought that's what signals and slots were used for, so the slot is called in the thread you want. Am I mistaken on that?

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          No, QWidgets don't have any threads.

          Why did you subclass QGridLayout ? There's rarely reason to subclass layout classes.

          Where exactly is that signal you are firing from a different thread ?

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          K 1 Reply Last reply
          0
          • K kgenbio

            I have a fairly large QT app that is having an issue where I am trying to update a QToggle() pragmatically and it periodically causes my whole UI to look scrambled.

            My app is started with a QMainWindow that also creates a QWidget, in a layout, on the main window called "fluid control". This fluidic control is an attribute to the QMainWindow class, and I am familiar with how signal/slots work to update the UI. Since fluid control is an an attribute to the QMainWindow, as long as the same thread that spawned the fluidic control widget is the one updating the UI, it should be fine.

            This fluid control widget updates many spin boxes, buttons, etc. However, what messes up the UI is QCheckbox(), specifically when I try to update its state (and widget UI) programmatically .

            @pyqtSlot(bool)
            def update_vol_toggle_slot(self, toggle):
                self.dispense_vol_toggle.setChecked(toggle)
            

            The code above is how I update the toggle. When it messes up I get the error:

            QPainter::begin: Paint device returned engine == 0, type: 3
            QPainter::setCompositionMode: Painter not active
            QPainter::fillRect: Painter not active
            QPainter::end: Painter not active, aborted
            

            Is there a safer or better way to update a QCheckbox() programmatically

            Pl45m4P Online
            Pl45m4P Online
            Pl45m4
            wrote on last edited by
            #5

            @kgenbio said in UI scrambling, painter not active using QCheckbox() in PyQT:

            The code above is how I update the toggle. When it messes up I get the error:

            QPainter::begin: Paint device returned engine == 0, type: 3
            QPainter::setCompositionMode: Painter not active
            QPainter::fillRect: Painter not active
            QPainter::end: Painter not active, aborted
            Is there a safer or better way to update a QCheckbox() programmatically
            

            Do you paint (use a QPainter) outside some widget's paintEvent handler?


            If debugging is the process of removing software bugs, then programming must be the process of putting them in.

            ~E. W. Dijkstra

            1 Reply Last reply
            0
            • SGaistS SGaist

              No, QWidgets don't have any threads.

              Why did you subclass QGridLayout ? There's rarely reason to subclass layout classes.

              Where exactly is that signal you are firing from a different thread ?

              K Offline
              K Offline
              kgenbio
              wrote on last edited by
              #6

              @SGaist

              The FluidicControl class has an event handler that is started and constantly checks for new events, which then fires off signals.

              class FluidicControl(QtWidgets.QWidget):
              
                 def __init__(self):
                      main_loop_thread = Thread(target=self.main_loop)
                      main_loop_thread.start()
              
                  def main_loop(self):
                      while self._run_flag:
                          try:
                              msg = self.fluidic_event_queue.get(block=False)
                              self.handle_event(msg)
                          except:
                              pass
              

              signals are fired off from the "handle_event()" function. they signal/slot connections are made in the fluidiccontrol init function.

              Pl45m4P 1 Reply Last reply
              0
              • K kgenbio

                @SGaist

                The FluidicControl class has an event handler that is started and constantly checks for new events, which then fires off signals.

                class FluidicControl(QtWidgets.QWidget):
                
                   def __init__(self):
                        main_loop_thread = Thread(target=self.main_loop)
                        main_loop_thread.start()
                
                    def main_loop(self):
                        while self._run_flag:
                            try:
                                msg = self.fluidic_event_queue.get(block=False)
                                self.handle_event(msg)
                            except:
                                pass
                

                signals are fired off from the "handle_event()" function. they signal/slot connections are made in the fluidiccontrol init function.

                Pl45m4P Online
                Pl45m4P Online
                Pl45m4
                wrote on last edited by
                #7

                @kgenbio

                Do you access the UI from this thread / loop? Or draw on your widget?
                You must only access the UI from the main Qt UI thread.

                Any chance that youe own main_loop blocks or interrupts the Qt event loop so widgets can't get updated/re-painted?


                If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                ~E. W. Dijkstra

                K 1 Reply Last reply
                0
                • Pl45m4P Pl45m4

                  @kgenbio

                  Do you access the UI from this thread / loop? Or draw on your widget?
                  You must only access the UI from the main Qt UI thread.

                  Any chance that youe own main_loop blocks or interrupts the Qt event loop so widgets can't get updated/re-painted?

                  K Offline
                  K Offline
                  kgenbio
                  wrote on last edited by
                  #8

                  @Pl45m4

                  This thread fires off pyqt signals only, it does not access the UI itself. I am unsure what thread the slots are handled in, i figured they were going to run in the main GUI thread.

                  Is the thread that signals are fired from the same as the thread where the slot is run?

                  1 Reply Last reply
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    You are firing a signal that belongs to a widget class which shall only happen in the main thread. Use the worker object approach with a QObject based class no QWidget there.

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved