Various Issues with PyQt6

RoadrunnerWMC roadrunnerwmc at gmail.com
Wed Feb 10 17:11:39 GMT 2021


Thank you! I'll look forward to the next release.


On Tue, Feb 9, 2021 at 7:45 AM Phil Thompson
<phil at riverbankcomputing.com> wrote:
>
> On 07/02/2021 20:33, RoadrunnerWMC wrote:
> > Hello. I'm trying to port a PyQt5 application to PyQt6, but am running
> > into a few issues, which I think are bugs in PyQt6 itself. I've
> > distilled them down to minimum reproducible examples, all of which
> > work fine on PyQt5. My environment is Ubuntu 20.04 (KDE Neon), using
> > the system-provided Python 3.8.5.
> >
> > Here's an issue with signals/slots signature matching:
> >
> >     from PyQt6 import QtCore, QtGui, QtWidgets
> >
> >     class MainWindow(QtWidgets.QMainWindow):
> >         def __init__(self):
> >             super().__init__()
> >             self.myList = QtWidgets.QListWidget()
> >
> > self.myList.itemActivated.connect(self.itemActivatedHandler)
> >
> >         @QtCore.pyqtSlot(QtWidgets.QListWidgetItem)
> >         def itemActivatedHandler(self, item):
> >             print('Item activated')
> >
> >     app = QtWidgets.QApplication([])
> >     mw = MainWindow()
> >     mw.show()
> >     app.exec()
> >
> > On PyQt 6.0.1, this results in the following traceback:
> >
> >     Traceback (most recent call last):
> >       File "/path/to/pyqt6_test.py", line 14, in <module>
> >         mw = MainWindow()
> >       File "/path/to/pyqt6_test.py", line 7, in __init__
> >         self.myList.itemActivated.connect(self.itemActivatedHandler)
> >     TypeError: decorated slot has no signature compatible with
> > itemActivated(QListWidgetItem*)
>
> That's fixed in the current PyQt6 snapshot.
>
> > This seems to affect every slot that takes one or more pointers to Qt
> > objects. If there's a way to denote pointers in the decorator,
> > something like
> > `@QtCore.pyqtSlot(pointerTo(QtWidgets.QListWidgetItem))`,
> > it doesn't seem to be explained in the documentation
> > (https://www.riverbankcomputing.com/static/Docs/PyQt6/signals_slots.html).
> >
> > Here's a different issue, related to
> > `QtWidgets.QGraphicsItem.itemChange()`:
> >
> >     from PyQt6 import QtCore, QtGui, QtWidgets
> >
> >     class CustomGraphicsItem(QtWidgets.QGraphicsItem):
> >         def boundingRect(self):
> >             return QtCore.QRectF(0, 0, 10, 10)
> >
> >         def itemChange(self, change, value):
> >             return QtWidgets.QGraphicsItem.itemChange(self, change,
> > value)
> >
> >     class MainWindow(QtWidgets.QMainWindow):
> >         def __init__(self):
> >             super().__init__()
> >             self.scene = QtWidgets.QGraphicsScene(0, 0, 100, 100, self)
> >             self.view = QtWidgets.QGraphicsView(self.scene, self)
> >
> >             self.scene.addItem(CustomGraphicsItem())
> >
> >     app = QtWidgets.QApplication([])
> >     mw = MainWindow()
> >     mw.show()
> >     app.exec()
> >
> > On PyQt 6.0.1, this results variously in one of the following three
> > outcomes (most often the second):
> >
> >     Traceback (most recent call last):
> >       File "/path/to/pyqt6_test_2.py", line 8, in itemChange
> >         return QtWidgets.QGraphicsItem.itemChange(self, change, value)
> >     TypeError: itemChange(self, QGraphicsItem.GraphicsItemChange,
> > Any): argument 2 has unexpected type 'GraphicsItemChange'
> >
> >     Traceback (most recent call last):
> >       File "/usr/lib/python3.8/enum.py", line 309, in __call__
> >         return cls.__new__(cls, value)
> >     RecursionError: maximum recursion depth exceeded while calling a
> > Python object
> >
> >     Segmentation fault
> >
> > I notice this example *does* work fine if I replace
> > `QtWidgets.QGraphicsItem` in `itemChange()`'s body with `super()` or
> > `super(CustomGraphicsItem, self)`. Maybe that syntax is required now?
> > But even if so, it shouldn't really be segfaulting if you do it the
> > wrong way.
>
> That's a SIP code generator bug that is fixed in the next snapshot.
>
> > Here's a third issue:
> >
> >     from PyQt6 import QtCore, QtGui, QtWidgets
> >
> >     class CustomGraphicsView(QtWidgets.QGraphicsView):
> >         def mouseMoveEvent(self, event):
> >             print(event.x())
> >
> >     class MainWindow(QtWidgets.QMainWindow):
> >         def __init__(self):
> >             super().__init__()
> >             self.scene = QtWidgets.QGraphicsScene(0, 0, 100, 100, self)
> >             self.view = CustomGraphicsView(self.scene, self)
> >             self.view.setMouseTracking(True)
> >
> >             self.setCentralWidget(self.view)
> >
> >     app = QtWidgets.QApplication([])
> >     mw = MainWindow()
> >     mw.show()
> >     app.exec()
> >
> > On PyQt 6.0.1, running this and then moving your cursor over the
> > graphics view results in the following traceback:
> >
> >     Traceback (most recent call last):
> >       File "/path/to/pyqt6_test_3.py", line 6, in mouseMoveEvent
> >         print(event.x())
> >     AttributeError: 'QMouseEvent' object has no attribute 'x'
> >
> > I don't really have any idea about this one. The same thing happens if
> > you try to access `.pos()`, so that's not a workaround.
>
> PyQt6 does not support API elements that are deprecated (ie. x(), y(),
> pos() etc.). However the Qt docs are wrong in that these methods aren't
> marked as such.
>
> The exact equivalent of event.x() is event.position().toPoint().x()
>
> > PyQt is by far my favorite GUI framework in any language, so I'm
> > really looking forward to being able to use PyQt6. Thanks in advance
> > for any help you can provide!
>
> The SIP bug is quite serious so I may make new releases sooner rather
> than later.
>
> Thanks,
> Phil


More information about the PyQt mailing list