Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

python - Correct way to convert old SIGNAL and SLOT to new style?

I'm currently trying to convert an old python program from Python 2 to Python 3, and update from PyQt4 to PyQt5. The application uses the old style signal and slots that are not supported under PyQt5. I have figured out most of what needs to be done, but below are a few lines that I can't seem to get working:

self.emit(SIGNAL('currentChanged'), row, col)
self.emit(SIGNAL("activated(const QString &)"), self.currentText())
self.connect(self,SIGNAL("currentChanged(const QString&)"), self.currentChanged)

The top two lines, I have no idea where to start since they don't seem to be attached to anything. The last example I'm not quite sure what to do with (const QString &).

I'm not entirely sure how to approach these, and I'm still learning python, but any help would be appreciated.

EDIT: The documentation doesn't really seem to go into depth on these cases, at least in a way that I understand.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The exact answer to this will depend on what kind of object self is. If it is a Qt class that already defines those signals, then the new-style syntax would be this:

self.currentChanged[int, int].emit(row, col)
self.activated[str].emit(self.currentText())
self.currentChanged[str].connect(self.handleCurrentChanged)

However, if any of those aren't pre-defined, you would need to define custom signals for them, like this:

class MyClass(QWidget):
    # this defines two overloads for currentChanged
    currentChanged = QtCore.pyqtSignal([int, int], [str])
    activated = QtCore.pyqtSignal(str)

    def __init__(self, parent=None):
        super(MyClass, self).__init__(parent)
        self.currentChanged[str].connect(self.handleCurrentChanged)   

    def handleCurrentChanged(self, text):
        print(text)

The old-style syntax allowed custom signals to be emitted dynamically (i.e. without defining them first), but that is not possible any more. With the new-style syntax, custom signals must always be explicitly defined.

Note that, if there is only one overload defined for a signal, the selector can be omitted:

    self.activated.emit(self.currentText())

For more information, see these articles in the PyQt Docs:

EDIT:

For your actual code, you need to make the following changes for the currentChanged signals:

  1. In Multibar.py (around line 30):

    This defines a custom signal (because QWidget does not have it):

    class MultiTabBar(QWidget):
        # add the following line
        currentChanged = pyqtSignal(int, int)
    
  2. In Multibar.py (around line 133):

    This emits the custom signal defined in (1):

    # self.emit(SIGNAL('currentChanged'), row, col)
    self.currentChanged.emit(row, col)
    
  3. In ScWindow.py (around line 478):

    This connects the signal defined in (1):

        # self.connect(self.PieceTab,SIGNAL("currentChanged"),self.pieceTabChanged)
        self.PieceTab.currentChanged.connect(self.pieceTabChanged)
    
  4. In ItemList.py (around line 73):

    The QFileDialog class already defines this signal, and there is only one overload of it. But the name of the slot must be changed, because it is shadowing the built-in signal name (which has become an attribute in the new-style syntax). So the connection should be made like this:

        # self.connect(self,SIGNAL("currentChanged(const QString&)"),self.currentChanged)
        self.currentChanged.connect(self.onCurrentChanged)
    
  5. In ItemList.py (around line 78):

    This renames the slot for the connection made in (4):

        # def currentChanged(self, file):
        def onCurrentChanged(self, file):
    

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...