Hi,
I found that replacing a widget while a drag is happening can cause a segmentation fault on Mac OS (doesn’t happen on my Windows machine). I am replacing it from the parent’s widget dragEnterEvent.
I am using PyQt4 4.9.6 with Qt 4.8.3.
Below is an example program that shows the issue; dragging something from the list to the MyWidget on the right will cause a segmentation fault on Mac OS… Even though the child widget shouldn’t be concerned by the drag and drop (only the parent accepts and handles it).
I can probably translate it to C++ if needed…
import sys
from PyQt4 import QtCore, QtGui
class Widget1(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
# If this line is left commented out (which I need it to be), this
# program will crash on Mac OS
#self.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)
self.setSizePolicy(QtGui.QSizePolicy.MinimumExpanding,
QtGui.QSizePolicy.MinimumExpanding)
def sizeHint(self):
return QtCore.QSize(100, 100)
def paintEvent(self, event):
qp = QtGui.QPainter(self)
qp.setPen(QtGui.QColor(0, 0, 191))
qp.drawText(0, 0, self.width(), self.height(),
QtCore.Qt.AlignCenter | QtCore.Qt.TextWordWrap,
"First widget, drag something here")
class Widget2(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)
self.setSizePolicy(QtGui.QSizePolicy.MinimumExpanding,
QtGui.QSizePolicy.MinimumExpanding)
def sizeHint(self):
return QtCore.QSize(100, 100)
def paintEvent(self, event):
qp = QtGui.QPainter(self)
qp.setPen(QtGui.QColor(191, 0, 0))
qp.drawText(0, 0, self.width(), self.height(),
QtCore.Qt.AlignCenter | QtCore.Qt.TextWordWrap,
"Second widget, overlay")
class MyWidget(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.setAcceptDrops(True)
self._scrollarea = QtGui.QScrollArea()
layout = QtGui.QVBoxLayout()
layout.addWidget(self._scrollarea)
self.setLayout(layout)
self._inner_widget = Widget1()
self._scrollarea.setWidget(self._inner_widget)
def _set_widget(self, widget):
self._inner_widget.setParent(None)
self._inner_widget.deleteLater()
self._inner_widget = widget
self._scrollarea.setWidget(widget)
widget.show()
def dragEnterEvent(self, event):
self._set_widget(Widget2())
event.accept()
def dragLeaveEvent(self, event):
self._set_widget(Widget1())
def dropEvent(self, event):
self._set_widget(Widget1())
event.accept()
app = QtGui.QApplication(sys.argv)
listWidget = QtGui.QListWidget()
listWidget.setDragEnabled(True)
listWidget.setDragDropMode(QtGui.QAbstractItemView.DragOnly)
listWidget.addItem("An item")
listWidget.addItem("Other item")
window = QtGui.QWidget()
layout = QtGui.QHBoxLayout()
layout.addWidget(listWidget)
layout.addWidget(MyWidget())
window.setLayout(layout)
window.show()
app.exec_()
Is this a bug in Qt? How can I get this to work? (I am thinking about making both widgets TransparentForMouseEvents and forwarding manually the mouse events from MyWidget to Widget1… can I make this work?)
Thank you for your time
↧