python - 如何拖动按钮
问题描述
我正在使用 qToolButton 和 QRubberBand 制作图像和标签小部件,但拖动在窗口中效果很好,但拖动在按钮上不起作用。有解决办法吗?
# coding:utf-8
from PySide2 import QtCore,QtGui,QtWidgets
class QToolButton(QtWidgets.QToolButton):
def __init__(self, label='', icon=''):
super(QToolButton, self).__init__()
self.label = label
self.icon = icon
self.create()
def create(self):
self.setText(self.label)
self.setIcon(QtGui.QIcon(self.icon))
self.setIconSize(QtCore.QSize(200, 200))
self.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
self.setCheckable(True)
self.setFocusPolicy(QtCore.Qt.NoFocus)
class Window(QtWidgets.QWidget):
def __init__(self):
super(Window, self).__init__()
self.rubberBand = QtWidgets.QRubberBand(QtWidgets.QRubberBand.Rectangle, self)
self.resize(500, 300)
layout = QtWidgets.QHBoxLayout(self)
for i in range(5):
layout.addWidget(QToolButton(label='test', icon='test.jpg'))
self.setLayout(layout)
self.setWindowTitle("Flow Layout")
def mousePressEvent(self, event):
self.origin = event.pos()
self.rubberBand.setGeometry(
QtCore.QRect(self.origin, QtCore.QSize()))
self.rubberBand.show()
QtWidgets.QWidget.mousePressEvent(self, event)
def mouseMoveEvent(self, event):
if self.rubberBand.isVisible():
self.rubberBand.setGeometry(
QtCore.QRect(self.origin, event.pos()).normalized())
QtWidgets.QWidget.mouseMoveEvent(self, event)
def mouseReleaseEvent(self, event):
if self.rubberBand.isVisible():
self.rubberBand.hide()
selected = []
rect = self.rubberBand.geometry()
for child in self.findChildren(QtWidgets.QToolButton):
if rect.intersects(child.geometry()):
selected.append(child)
if selected:
for i in selected:
if i.isChecked():
i.setChecked(False)
else:
i.setChecked(True)
QtWidgets.QWidget.mouseReleaseEvent(self, event)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
我正在使用 qToolButton 和 QRubberBand 制作图像和标签小部件,但拖动在窗口中效果很好,但拖动在按钮上不起作用。有解决办法吗?
解决方案
您必须在要提供该功能的所有小部件上安装事件过滤器,并且可能使用橡皮筋的常用功能以避免重复代码。
class Window(QtWidgets.QWidget):
def __init__(self):
super(Window, self).__init__()
self.rubberBand = QtWidgets.QRubberBand(QtWidgets.QRubberBand.Rectangle, self)
self.resize(500, 300)
layout = QtWidgets.QHBoxLayout(self)
for i in range(5):
button = QToolButton(label='test', icon='test.jpg')
layout.addWidget(button)
button.installEventFilter(self)
self.setLayout(layout)
self.setWindowTitle("Flow Layout")
def eventFilter(self, source, event):
if event.type() == event.MouseButtonPress:
self.origin = source.mapTo(self, event.pos())
elif event.type() == event.MouseMove and event.buttons():
if not self.rubberBand.isVisible():
distance = (source.mapTo(self, event.pos()) - self.origin).manhattanLength()
if distance > QtWidgets.QApplication.startDragDistance():
if isinstance(source, QtWidgets.QAbstractButton) and source.isDown():
source.setDown(False)
self.rubberBand.show()
if self.rubberBand.isVisible():
self.resizeRubberBand(source.mapTo(self, event.pos()))
event.accept()
return True
elif event.type() == event.MouseButtonRelease and self.rubberBand.isVisible():
self.closeRubberBand()
event.accept()
return True
return super().eventFilter(source, event)
def startRubberBand(self, pos):
self.origin = pos
self.rubberBand.setGeometry(
QtCore.QRect(self.origin, QtCore.QSize()))
self.rubberBand.show()
def resizeRubberBand(self, pos):
if self.rubberBand.isVisible():
self.rubberBand.setGeometry(
QtCore.QRect(self.origin, pos).normalized())
def closeRubberBand(self):
if self.rubberBand.isVisible():
self.rubberBand.hide()
selected = []
rect = self.rubberBand.geometry()
for child in self.findChildren(QtWidgets.QToolButton):
if rect.intersects(child.geometry()):
selected.append(child)
if selected:
for i in selected:
if i.isChecked():
i.setChecked(False)
else:
i.setChecked(True)
def mousePressEvent(self, event):
self.startRubberBand(event.pos())
QtWidgets.QWidget.mousePressEvent(self, event)
def mouseMoveEvent(self, event):
self.resizeRubberBand(event.pos())
QtWidgets.QWidget.mouseMoveEvent(self, event)
def mouseReleaseEvent(self, event):
self.closeRubberBand()
QtWidgets.QWidget.mouseReleaseEvent(self, event)
请注意,您可能应该通过检查所有三个鼠标事件是否由左键生成来创建、调整大小和关闭橡皮筋;在这种情况下,请记住对于 mouseMoveEvent 您应该使用buttons()
,而不是button()
。
推荐阅读
- php - 如何在在线 Web 服务器中将 php/html 页面相互链接?加上mysqli的问题
- excel - 如何在列中查找所有重复项,然后实现重复项中所有信息的“历史列”?
- node.js - 无法将访问令牌存储在角度构造函数中
- python - 改变 SIR 模型的回收率
- sql - UNION ALL 返回类似于 UNION 的结果
- jsf - 如何格式化 primefaces 进度条的值以始终显示 2 个十进制数字?
- ionic-framework - 如何在 Ionic 4 中更改 ion-item-sliding 中按钮的颜色
- laravel - 图像未显示在编辑刀片中
- excel - 如何从多选列表框数组(VBA)中正确检索每个选定的值
- spring - 什么是 Maven pom 标签?