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. Getting unexpected results with QTimer.
QtWS25 Last Chance

Getting unexpected results with QTimer.

Scheduled Pinned Locked Moved Unsolved Qt for Python
9 Posts 3 Posters 660 Views
  • 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.
  • P Offline
    P Offline
    Paul_F
    wrote on last edited by Paul_F
    #1

    I am hoping someone can help me with this. The code below controls an On screen display volume widget. A QTimer is started to wait 3 seconds before hiding the widget when a button is released. If a volume button is pressed again within those 3 seconds, the timer must be killed.

    If I press a button repeatedly instead of held down, something weird happens. it's as if none of the timers have been killed; If I press a button, say 5 times fast, the widget hides 3 seconds after the first button press, and repeats the print message 4 times too. In other words, 5 different timers are running. It also has consequences for the widget, it starts flickering after three seconds. When the button is held down, the loop performs flawlessly and does not initiate a timer until the button is released - Even though the autorepeats simulates a button press plus a button release. I am a bit stumped, who can help me here?

    Thank you.

    The code in question:

    class Carma(QtWidgets.QWidget):
    
        def __init__(self,init):
            super().__init__()
    
            if self.init == True:
                self.volstep = 1  # Volume step
                self.osd_delaytime = 3  # seconds
                self.mainvolume = 50  # startup volume
                self.volrate = 20  # volume change speed when using +-
                self.choice = -1
                self.vol_delay_ms = 500
                self.vol_interval_ms = 100
                self.timer = QtCore.QTimer()
                self.init_ui()
    
    
    
        def setVolume(self):
            vol_int_ms = int((1/self.volrate)*1000)
            self.buttons_src[6].setStyleSheet("border-image: url(images/bezel-button.png)")
            self.buttons_src[6].setAutoRepeat(True)
            self.buttons_src[6].setAutoRepeatDelay(self.vol_delay_ms)
            self.buttons_src[6].setAutoRepeatInterval(vol_int_ms)
            self.buttons_src[6].pressed.connect(lambda: self.voldn())
            self.buttons_src[6].clicked.connect(lambda: self.volhidetimer(2))
            self.buttons_src[7].setStyleSheet("border-image: url(images/bezel-button.png)")
            self.buttons_src[7].setAutoRepeat(True)
            self.buttons_src[7].setAutoRepeatDelay(self.vol_delay_ms)
            self.buttons_src[7].setAutoRepeatInterval(vol_int_ms)
            self.buttons_src[7].pressed.connect(lambda: self.volup())
            self.buttons_src[7].clicked.connect(lambda: self.volhidetimer(2))
            self.init = False
    
        def voldn(self):
            self.timer.stop()
            print("voldn pressed", self.mainvolume)
            self.buttons_src[6].setStyleSheet("border-image: url(images/bezel-buttonp.png)")
            if self.osd_vol_widget.isHidden():
                self.osd_vol_widget.show()
            if 1 <= self.mainvolume <= 100:
                self.mainvolume -= self.volstep
                self.osd_vol_bar.setValue(self.mainvolume)
                self.osd_vol_label.setText(str(self.mainvolume))
    
        def volup(self):
            self.timer.stop()
            print("volup pressed", self.mainvolume)
            self.buttons_src[7].setStyleSheet("border-image: url(images/bezel-buttonp.png)")
            if self.osd_vol_widget.isHidden():
                self.osd_vol_widget.show()
            if 0 <= self.mainvolume <= 99:
                self.mainvolume += self.volstep
                self.osd_vol_bar.setValue(self.mainvolume)
                self.osd_vol_label.setText(str(self.mainvolume))
    
        def volhidetimer(self, delaytime):
            if not any(self.buttons_src[i].isDown() for i in (6, 7)):
                self.buttons_src[6].setStyleSheet("border-image: url(images/bezel-button.png)")
                self.timer.singleShot(delaytime * 1000, lambda: self.volhide())
                print("Start timer volume hide")
    
        def volhide(self):
            if not any(self.buttons_src[i].isDown() for i in (6, 7)):
                self.osd_vol_widget.hide()
                print("Volume widget hidden")
    
    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      The singleShot method is a class function. You are creating a new independent single shot timer each time you call it.

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

      P 1 Reply Last reply
      2
      • SGaistS SGaist

        Hi,

        The singleShot method is a class function. You are creating a new independent single shot timer each time you call it.

        P Offline
        P Offline
        Paul_F
        wrote on last edited by
        #3

        @SGaist Understood. How can I prevent this?

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

          Make set your timer as single shot and just restart it.

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

          P 1 Reply Last reply
          2
          • P Paul_F

            @SGaist Understood. How can I prevent this?

            eyllanescE Offline
            eyllanescE Offline
            eyllanesc
            wrote on last edited by
            #5

            @Paul_F The implementation that @SGaist points to is something like:

            self.timer = QtCore.QTimer(singleShot=True)
            self.timer.timeout.connect(self.volhide)
            

            then change to:

            self.timer.setInterval(delaytime * 1000)
            self.timer.start()
            

            If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

            P 1 Reply Last reply
            3
            • eyllanescE eyllanesc

              @Paul_F The implementation that @SGaist points to is something like:

              self.timer = QtCore.QTimer(singleShot=True)
              self.timer.timeout.connect(self.volhide)
              

              then change to:

              self.timer.setInterval(delaytime * 1000)
              self.timer.start()
              
              P Offline
              P Offline
              Paul_F
              wrote on last edited by
              #6

              @eyllanesc Thank you, but I just sorted it.

              instead of .singleshot I used setSingleShot and .timeout.connect and started it manually. Now it works, no more flickering.

              eyllanescE 1 Reply Last reply
              0
              • SGaistS SGaist

                Make set your timer as single shot and just restart it.

                P Offline
                P Offline
                Paul_F
                wrote on last edited by
                #7

                @SGaist Thank you, it now works flawlessly!

                1 Reply Last reply
                0
                • P Paul_F

                  @eyllanesc Thank you, but I just sorted it.

                  instead of .singleshot I used setSingleShot and .timeout.connect and started it manually. Now it works, no more flickering.

                  eyllanescE Offline
                  eyllanescE Offline
                  eyllanesc
                  wrote on last edited by eyllanesc
                  #8

                  @Paul_F That's what my code does:

                  self.timer = QtCore.QTimer(singleShot=True)
                  

                  is the same as:

                  self.timer = QtCore.QTimer()
                  self.timer.setSingleShot(True)
                  

                  And please don't abuse lambda functions.

                  If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

                  P 1 Reply Last reply
                  1
                  • eyllanescE eyllanesc

                    @Paul_F That's what my code does:

                    self.timer = QtCore.QTimer(singleShot=True)
                    

                    is the same as:

                    self.timer = QtCore.QTimer()
                    self.timer.setSingleShot(True)
                    

                    And please don't abuse lambda functions.

                    P Offline
                    P Offline
                    Paul_F
                    wrote on last edited by
                    #9

                    @eyllanesc I tend to get errors if I don't so I just put it in. I just started three months ago with python, with only 80's basic as a base. So cut me some slack ;)

                    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