Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Convert SIGNAL to new Signal Format
Forum Updated to NodeBB v4.3 + New Features

Convert SIGNAL to new Signal Format

Scheduled Pinned Locked Moved Solved General and Desktop
11 Posts 3 Posters 2.0k 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.
  • jeremy_kJ Offline
    jeremy_kJ Offline
    jeremy_k
    wrote on last edited by
    #2

    For reference: https://www.riverbankcomputing.com/static/Docs/PyQt5/signals_slots.html#connecting-disconnecting-and-emitting-signals

    The syntax for connecting a signal is object.signalName.connect(slot). There are two alternatives mentioned in the Connecting Signals Using Keyword Arguments section.

    For the first example, it would be:
    self.serialPortEdit.returnPressed.connect(self.connectButton.clicked)

    Emit a signal via object.signalName.emit(args...). For example:
    self.new_data.emit(reading)

    Asking a question about code? http://eel.is/iso-c++/testcase/

    M 1 Reply Last reply
    3
    • jeremy_kJ jeremy_k

      For reference: https://www.riverbankcomputing.com/static/Docs/PyQt5/signals_slots.html#connecting-disconnecting-and-emitting-signals

      The syntax for connecting a signal is object.signalName.connect(slot). There are two alternatives mentioned in the Connecting Signals Using Keyword Arguments section.

      For the first example, it would be:
      self.serialPortEdit.returnPressed.connect(self.connectButton.clicked)

      Emit a signal via object.signalName.emit(args...). For example:
      self.new_data.emit(reading)

      M Offline
      M Offline
      mjs513
      wrote on last edited by
      #3

      @jeremy_k
      Thanks for getting back to me and making it a lot clearer on what has to change.

      I changed item 2 to:

      self.serWorker.connect(new_data(PyQt_PyObject))
      ```  and made the changes that you showed but getting one error on:
      

      self.serialPortEdit.returnPressed.connect(self.connectButton.clicked)

      which is
      

      TypeError: connect() failed between returnPressed() and clicked()

      changing it to this seemed to make it work:
      

      self.connectButton.clicked.connect(self.serialPortEdit.returnPressed)

      JonBJ 1 Reply Last reply
      0
      • M mjs513

        @jeremy_k
        Thanks for getting back to me and making it a lot clearer on what has to change.

        I changed item 2 to:

        self.serWorker.connect(new_data(PyQt_PyObject))
        ```  and made the changes that you showed but getting one error on:
        

        self.serialPortEdit.returnPressed.connect(self.connectButton.clicked)

        which is
        

        TypeError: connect() failed between returnPressed() and clicked()

        changing it to this seemed to make it work:
        

        self.connectButton.clicked.connect(self.serialPortEdit.returnPressed)

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #4

        @mjs513 said in Convert SIGNAL to new Signal Format:

        self.connectButton.clicked.connect(self.serialPortEdit.returnPressed)

        No, that's the other way round! It would equate to:

        self.connect(self.connectButton, SIGNAL("clicked()"), self.serialPortEdit, SIGNAL("returnPressed()"))
        

        which is not what your case #1 wants.

        Python connection syntax is:
        signalObject .signalMethod .connect(slotObject .slotMethod )

        Your original

        self.serialPortEdit.returnPressed.connect(self.connectButton.clicked)
        

        looks like right intention to me. I would guess the "TypeError: connect() failed between returnPressed() and clicked()" is because there is a problem here: returnPressed() signal passes no arguments but clicked() signal takes on optional [checked=false] parameter. I wonder if PyQt5 regards these signatures as incompatible and won't let you connect them directly, you will have to use a lambda?

        1 Reply Last reply
        0
        • M Offline
          M Offline
          mjs513
          wrote on last edited by
          #5
          This post is deleted!
          1 Reply Last reply
          0
          • M Offline
            M Offline
            mjs513
            wrote on last edited by
            #6

            @jeremy_k - @JonB

            Yeah looks like that is the correct format:

            self.serialPortEdit.returnPressed.connect(self.connectButton.clicked)
            

            With the way I made it the button doesn't work or even show up.

            but really don;t know how to use or what you mean by lamda.

            also now my conversion of item 2:

            self.connect(self.serWorker, SIGNAL("new_data(PyQt_PyObject)"), self.newData)
            

            to

            self.serWorker.connect(new_data(PyQt_PyObject))
            

            gives the following error

            AttributeError: 'SerialWorker' object has no attribute 'connect'. Did you mean: 'disconnect'?
            

            Thanks again

            JonBJ 1 Reply Last reply
            0
            • M mjs513

              @jeremy_k - @JonB

              Yeah looks like that is the correct format:

              self.serialPortEdit.returnPressed.connect(self.connectButton.clicked)
              

              With the way I made it the button doesn't work or even show up.

              but really don;t know how to use or what you mean by lamda.

              also now my conversion of item 2:

              self.connect(self.serWorker, SIGNAL("new_data(PyQt_PyObject)"), self.newData)
              

              to

              self.serWorker.connect(new_data(PyQt_PyObject))
              

              gives the following error

              AttributeError: 'SerialWorker' object has no attribute 'connect'. Did you mean: 'disconnect'?
              

              Thanks again

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by JonB
              #7

              @mjs513 said in Convert SIGNAL to new Signal Format:

              self.serWorker.connect(new_data(PyQt_PyObject))

              AttributeError: 'SerialWorker' object has no attribute 'connect'. Did you mean: 'disconnect'?

              Previosuly answered:

              Python connection syntax is:

              signalObject .signalMethod .connect(slotObject .slotMethod )

              M 1 Reply Last reply
              1
              • JonBJ JonB

                @mjs513 said in Convert SIGNAL to new Signal Format:

                self.serWorker.connect(new_data(PyQt_PyObject))

                AttributeError: 'SerialWorker' object has no attribute 'connect'. Did you mean: 'disconnect'?

                Previosuly answered:

                Python connection syntax is:

                signalObject .signalMethod .connect(slotObject .slotMethod )

                M Offline
                M Offline
                mjs513
                wrote on last edited by
                #8

                @JonB
                Think I found the problem. Doing a search for serial worker I found that its actually a qthread class:

                class SerialWorker(QThread):
                
                  def __init__(self, parent = None, ser = None):
                    QThread.__init__(self, parent)
                    self.exiting = False
                    self.ser = ser
                        
                  def run(self):
                    print ("sampling start..")
                    self.acc_file = open(acc_file_name, 'w')
                    self.magn_file = open(magn_file_name, 'w')
                    count = 100
                    in_values = 9
                    reading = [0.0 for i in range(in_values)]
                    # read data for calibration    
                    while not self.exiting:
                      # determine word size
                      temp = 'b'
                      self.ser.write(temp.encode())
                      self.ser.write(chr(count))
                      for j in range(count):
                        for i in range(in_values):
                          if word == 4:
                            reading[i] = unpack('hh', self.ser.read(4))[0]
                          if word == 2:
                            reading[i] = unpack('h', self.ser.read(2))[0]            
                        self.ser.read(2) # consumes remaining '\r\n'
                        if reading[8] == 0:
                          reading[6] = 1
                          reading[7] = 1
                          reading[8] = 1      
                        # prepare readings to store on file
                        acc_readings_line = "%d %d %d\r\n" % (reading[0], reading[1], reading[2])
                        self.acc_file.write(acc_readings_line)
                        magn_readings_line = "%d %d %d\r\n" % (reading[6], reading[7], reading[8])
                        self.magn_file.write(magn_readings_line)
                      # every count times we pass some data to the GUI
                      #self.emit(SIGNAL("new_data(PyQt_PyObject)"), reading)
                      self.new_data.emit(reading)
                      print ("."),
                    # closing acc and magn files
                    self.acc_file.close()
                    self.magn_file.close()
                    return 
                  
                  def __del__(self):
                    self.exiting = True
                    self.wait()
                    print( "SerialWorker exits..")
                

                I have been looking at
                https://www.pythontutorial.net/pyqt/pyqt-qthread/
                and
                https://www.pythonguis.com/tutorials/transmitting-extra-data-qt-signals/

                any suggestions or better way

                JonBJ 1 Reply Last reply
                0
                • M mjs513

                  @JonB
                  Think I found the problem. Doing a search for serial worker I found that its actually a qthread class:

                  class SerialWorker(QThread):
                  
                    def __init__(self, parent = None, ser = None):
                      QThread.__init__(self, parent)
                      self.exiting = False
                      self.ser = ser
                          
                    def run(self):
                      print ("sampling start..")
                      self.acc_file = open(acc_file_name, 'w')
                      self.magn_file = open(magn_file_name, 'w')
                      count = 100
                      in_values = 9
                      reading = [0.0 for i in range(in_values)]
                      # read data for calibration    
                      while not self.exiting:
                        # determine word size
                        temp = 'b'
                        self.ser.write(temp.encode())
                        self.ser.write(chr(count))
                        for j in range(count):
                          for i in range(in_values):
                            if word == 4:
                              reading[i] = unpack('hh', self.ser.read(4))[0]
                            if word == 2:
                              reading[i] = unpack('h', self.ser.read(2))[0]            
                          self.ser.read(2) # consumes remaining '\r\n'
                          if reading[8] == 0:
                            reading[6] = 1
                            reading[7] = 1
                            reading[8] = 1      
                          # prepare readings to store on file
                          acc_readings_line = "%d %d %d\r\n" % (reading[0], reading[1], reading[2])
                          self.acc_file.write(acc_readings_line)
                          magn_readings_line = "%d %d %d\r\n" % (reading[6], reading[7], reading[8])
                          self.magn_file.write(magn_readings_line)
                        # every count times we pass some data to the GUI
                        #self.emit(SIGNAL("new_data(PyQt_PyObject)"), reading)
                        self.new_data.emit(reading)
                        print ("."),
                      # closing acc and magn files
                      self.acc_file.close()
                      self.magn_file.close()
                      return 
                    
                    def __del__(self):
                      self.exiting = True
                      self.wait()
                      print( "SerialWorker exits..")
                  

                  I have been looking at
                  https://www.pythontutorial.net/pyqt/pyqt-qthread/
                  and
                  https://www.pythonguis.com/tutorials/transmitting-extra-data-qt-signals/

                  any suggestions or better way

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by
                  #9

                  @mjs513 said in Convert SIGNAL to new Signal Format:

                    #self.emit(SIGNAL("new_data(PyQt_PyObject)"), reading)
                    self.new_data.emit(reading)
                  

                  Just as you have this for emitting the signal so for item #2 you need

                  # self.connect(self.serWorker, SIGNAL("new_data(PyQt_PyObject)"), self.newData)
                  self.serWorker.new_data.connect(self.newData)
                  
                  M 1 Reply Last reply
                  0
                  • JonBJ JonB

                    @mjs513 said in Convert SIGNAL to new Signal Format:

                      #self.emit(SIGNAL("new_data(PyQt_PyObject)"), reading)
                      self.new_data.emit(reading)
                    

                    Just as you have this for emitting the signal so for item #2 you need

                    # self.connect(self.serWorker, SIGNAL("new_data(PyQt_PyObject)"), self.newData)
                    self.serWorker.new_data.connect(self.newData)
                    
                    M Offline
                    M Offline
                    mjs513
                    wrote on last edited by
                    #10

                    @JonB
                    Thanks for all your help - found that you also need to add this to the class:

                    new_data_signal = pyqtSignal('PyQt_PyObject')
                    

                    Once I did that got it all operational - just had to fix up a few minor thigs.

                    JonBJ 1 Reply Last reply
                    0
                    • M mjs513 has marked this topic as solved on
                    • M mjs513

                      @JonB
                      Thanks for all your help - found that you also need to add this to the class:

                      new_data_signal = pyqtSignal('PyQt_PyObject')
                      

                      Once I did that got it all operational - just had to fix up a few minor thigs.

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by JonB
                      #11

                      @mjs513
                      That pyqtSignal(...) is a PyQt-ism. I think you have to use it any time you want to define your own signal.

                      However, none of this relates to your earlier problem of

                      self.connect(self.serialPortEdit, SIGNAL("returnPressed()"), self.connectButton, SIGNAL("clicked()"))
                      

                      I have now had a chance to try this. On my PyQt 5.15.6 the equivalent of the attempted

                      self.serialPortEdit.returnPressed.connect(self.connectButton.clicked)
                      

                      gives an error message like yours but with a bit more detail:

                      QObject::connect: Incompatible sender/receiver arguments
                              QLineEdit::returnPressed() --> QPushButton::clicked(bool)
                      Traceback (most recent call last):
                        File "/home/jon/PyQt5/testconnect1.py", line 20, in <module>
                          window()
                        File "/home/jon/PyQt5/testconnect1.py", line 14, in window
                          le.returnPressed.connect(pb.clicked)
                      TypeError: connect() failed between returnPressed() and clicked()
                      

                      You can see from QLineEdit::returnPressed() --> QPushButton::clicked(bool) it is saying returnPressed() takes no argument but QPushButton::clicked(bool) does (a bool for whether any checkbox on the button is checked). Which is what I assumed the problem would be. Although this defaults to False if not passed, it is still enough to make those two signals' signatures incompatible, you cannot directly get returnPressed() signal to call clicked(bool).

                      In principle this is where you would use the lambda syntax I mentioned for the slot, like one of these:

                      self.serialPortEdit.returnPressed.connect( lambda: self.connectButton.clicked() )
                      self.serialPortEdit.returnPressed.connect( lambda: self.connectButton.clicked(False) )
                      

                      But this results in

                      le.returnPressed.connect(lambda: pb.clicked())
                      TypeError: native Qt signal is not callable
                      

                      PyQt apparently does not like us directly calling QPushButton.clicked(), because it is a "native Qt signal". We would be allowed to do this in C++. I don't know how you would get to call it from PyQt. [Following is unnecessary, see UPDATE section below.]

                      The only way I know to do this now would be:

                      self.serialPortEdit.returnPressed.connect( lambda: self.connectButton.click() )
                      

                      I still use a lambda, but I call QPushButton.click() which is a slot to "emulate" a click rather than calling the QPushButton.clicked() signal which Qt emits. In this case I could also skip the lambda (because their arguments --- none --- are compatible) and attach this slot directly to the signal:

                      self.serialPortEdit.returnPressed.connect( self.connectButton.click )
                      

                      UPDATE
                      OK, I get why, PyQt5 never lets you call a signal method directly, you always have to use emit(). So to use clicked() signal directly and not have to use the click() slot (which we are lucky even exists), you should use:

                      self.serialPortEdit.returnPressed.connect( lambda: self.connectButton.clicked.emit() )
                      
                      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