将带有光标的小部件移动到另一个布局
Move widget with cursor to another layout
我想模拟自定义小部件的 QDockWidget/QToolBar 行为,使用 mousePressEvent
从一个位置取消固定小部件并将其固定到另一个位置。喜欢把上框放到'sub'位置:
我可以使用以下代码将其取消固定:
class DraggableSpectralFrame(SpectralFrame):
def __init__(self, parent=None):
super().__init__(parent)
self.setMouseTracking(True)
self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint)
self.oldPos = QPointF(self.pos())
self.local= QPointF(self.pos())
self.floating = False
def mousePressEvent(self, event):
self.oldPos = event.globalPos()
if self.hoverRect.contains(event.localPos()) and \
event.button() == Qt.LeftButton:
self.floating = True
self.local = event.localPos()
self.setParent(None)
self.show()
self.move((self.oldPos - self.local).toPoint())
def mouseMoveEvent(self, event):
self.oldPos = event.globalPos()
if self.floating:
self.move((self.oldPos - self.local).toPoint())
在将 DraggableSpectralFrame
变形为 window 并以正确的方式移动 window 后,我失去了按下的功能,我必须再次 click/press 。没有额外的点击 window 仍然对光标移动做出反应(由于 self.floating
是 True
)但是很容易失去对急剧移动的关注。
可能有更简单的方法来实现这个想法,如果是的话 - 请告诉我!
实现拖放的一种方法是使用 QDrag
对象在拖动时显示小部件。对于应该接受拖动的小部件的小部件,您需要将 acceptDrops
设置为 True 并至少重新实现 dragEnterEvent
和 dropEvent
。这是一个非常简单的示例,说明如何完成此操作。在此示例中,“移动我”标签可以在两个 windows.
之间来回拖动
from PyQt5 import QtWidgets, QtCore, QtGui
class DropFrame(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.vlayout = QtWidgets.QVBoxLayout(self)
self.setAcceptDrops(True)
def dragEnterEvent(self, event):
if isinstance(event.source(), DraggableLabel):
event.accept()
def dropEvent(self, event):
event.accept()
widget = event.source()
if widget:
self.vlayout.addWidget(widget)
class DraggableLabel(QtWidgets.QLabel):
def __init__(self, text, parent=None):
super().__init__(text, parent)
self.setFrameShape(self.Box)
def mousePressEvent(self, event):
self.drag = QtGui.QDrag(self)
self.mime_data = QtCore.QMimeData()
self.drag.setMimeData(self.mime_data)
# capture image of self to use as pixmap while dragging
self.pixmap = self.grab()
self.drag.setPixmap(self.pixmap)
self.hide()
self.drag.exec(QtCore.Qt.MoveAction)
self.show()
if __name__ == "__main__":
app = QtWidgets.QApplication([])
widget1 = DropFrame()
label = DraggableLabel('Move me')
widget1.layout().addWidget(label)
widget1.show()
widget2 = DropFrame()
widget2.show()
widget2.move(widget1.pos().x(),widget1.pos().y()+150)
app.exec()
我想模拟自定义小部件的 QDockWidget/QToolBar 行为,使用 mousePressEvent
从一个位置取消固定小部件并将其固定到另一个位置。喜欢把上框放到'sub'位置:
我可以使用以下代码将其取消固定:
class DraggableSpectralFrame(SpectralFrame):
def __init__(self, parent=None):
super().__init__(parent)
self.setMouseTracking(True)
self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint)
self.oldPos = QPointF(self.pos())
self.local= QPointF(self.pos())
self.floating = False
def mousePressEvent(self, event):
self.oldPos = event.globalPos()
if self.hoverRect.contains(event.localPos()) and \
event.button() == Qt.LeftButton:
self.floating = True
self.local = event.localPos()
self.setParent(None)
self.show()
self.move((self.oldPos - self.local).toPoint())
def mouseMoveEvent(self, event):
self.oldPos = event.globalPos()
if self.floating:
self.move((self.oldPos - self.local).toPoint())
在将 DraggableSpectralFrame
变形为 window 并以正确的方式移动 window 后,我失去了按下的功能,我必须再次 click/press 。没有额外的点击 window 仍然对光标移动做出反应(由于 self.floating
是 True
)但是很容易失去对急剧移动的关注。
可能有更简单的方法来实现这个想法,如果是的话 - 请告诉我!
实现拖放的一种方法是使用 QDrag
对象在拖动时显示小部件。对于应该接受拖动的小部件的小部件,您需要将 acceptDrops
设置为 True 并至少重新实现 dragEnterEvent
和 dropEvent
。这是一个非常简单的示例,说明如何完成此操作。在此示例中,“移动我”标签可以在两个 windows.
from PyQt5 import QtWidgets, QtCore, QtGui
class DropFrame(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.vlayout = QtWidgets.QVBoxLayout(self)
self.setAcceptDrops(True)
def dragEnterEvent(self, event):
if isinstance(event.source(), DraggableLabel):
event.accept()
def dropEvent(self, event):
event.accept()
widget = event.source()
if widget:
self.vlayout.addWidget(widget)
class DraggableLabel(QtWidgets.QLabel):
def __init__(self, text, parent=None):
super().__init__(text, parent)
self.setFrameShape(self.Box)
def mousePressEvent(self, event):
self.drag = QtGui.QDrag(self)
self.mime_data = QtCore.QMimeData()
self.drag.setMimeData(self.mime_data)
# capture image of self to use as pixmap while dragging
self.pixmap = self.grab()
self.drag.setPixmap(self.pixmap)
self.hide()
self.drag.exec(QtCore.Qt.MoveAction)
self.show()
if __name__ == "__main__":
app = QtWidgets.QApplication([])
widget1 = DropFrame()
label = DraggableLabel('Move me')
widget1.layout().addWidget(label)
widget1.show()
widget2 = DropFrame()
widget2.show()
widget2.move(widget1.pos().x(),widget1.pos().y()+150)
app.exec()