问题描述
目前添加了2个布局,在标签的顶部和下方使用FlowLayout添加按钮。 在 Qrubberband 上
当鼠标不动时,没有任何问题。当我拖动时,选择有问题。 问题从何而来?
# -*- coding: utf-8 -*-
from pyside2.QtCore import *
from pyside2.QtGui import *
from pyside2.QtWidgets import *
class QToolButton(QToolButton):
def __init__(self,label='',icon='',icon_size=100):
super(QToolButton,self).__init__()
self.label = label
self.icon = icon
self.icon_size = icon_size
self.create()
def create(self):
self.setText(self.label)
self.setIcon(QIcon(self.icon))
self.setIconSize(QSize(self.icon_size,self.icon_size))
self.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
self.setCheckable(True)
self.setFocusPolicy(Qt.NoFocus)
class Window(QMainWindow):
def __init__(self):
super(Window,self).__init__()
self.rubberBand = QRubberBand(QRubberBand.Rectangle,self)
self.ui()
self.add_thumbnail()
def ui(self):
self.setContentsMargins(2,2,2)
self.resize(1000,800)
self.centralwidget = QWidget(self)
self.gridLayout = qgridLayout(self.centralwidget)
self.label = QLabel(self.centralwidget)
self.label.setText('LABEL IMAGE')
self.label.setMinimumSize(QSize(0,100))
self.label.setMaximumSize(QSize(16777215,100))
self.label.setAlignment(Qt.AlignCenter)
self.gridLayout.addWidget(self.label,1,1)
self.frame = qframe(self.centralwidget)
self.frame.setFrameShape(qframe.StyledPanel)
self.frame.setFrameShadow(qframe.Raised)
self.gridLayout.addWidget(self.frame,1)
self.setCentralWidget(self.centralwidget)
self.flow_layout = FlowLayout()
self.frame.setLayout(self.flow_layout)
def add_thumbnail(self):
for i in range(10):
button = QToolButton(label='test',icon='test')
self.flow_layout.addWidget(button)
button.installEventFilter(self)
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 > QApplication.startDragdistance():
if isinstance(source,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(Window,self).eventFilter(source,event)
def startRubberBand(self,pos):
self.origin = pos
self.rubberBand.setGeometry(
QRect(self.origin,QSize()))
self.rubberBand.show()
def resizeRubberBand(self,pos):
if self.rubberBand.isVisible():
self.rubberBand.setGeometry(
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(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())
QMainWindow.mousepressEvent(self,event)
def mouseMoveEvent(self,event):
self.resizeRubberBand(event.pos())
QMainWindow.mouseMoveEvent(self,event)
def mouseReleaseEvent(self,event):
self.closeRubberBand()
QMainWindow.mouseReleaseEvent(self,event)
class FlowLayout(QLayout):
def __init__(self,parent=None,margin=0,spacing=-1):
super(FlowLayout,self).__init__(parent)
if parent is not None:
self.setContentsMargins(margin,margin,margin)
self.setSpacing(spacing)
self.margin = margin
# spaces between each item
self.spaceX = 2
self.spaceY = 2
self.itemList = []
def __del__(self):
item = self.takeAt(0)
while item:
item = self.takeAt(0)
def addItem(self,item):
self.itemList.append(item)
def count(self):
return len(self.itemList)
def itemAt(self,index):
if index >= 0 and index < len(self.itemList):
return self.itemList[index]
return None
def takeAt(self,index):
if index >= 0 and index < len(self.itemList):
return self.itemList.pop(index)
return None
def expandingDirections(self):
return Qt.Orientations(Qt.Orientation(0))
def hasHeightForWidth(self):
return True
def heightForWidth(self,width):
height = self.doLayout(QRect(0,width,0),True)
return height
def setGeometry(self,rect):
super(FlowLayout,self).setGeometry(rect)
self.doLayout(rect,False)
def sizeHint(self):
return self.minimumSize()
def minimumSize(self):
size = QSize()
for item in self.itemList:
size = size.expandedTo(item.minimumSize())
size += QSize(2 * self.margin,2 * self.margin)
return size
def doLayout(self,rect,testOnly):
x = rect.x()
y = rect.y()
lineHeight = 0
for item in self.itemList:
wid = item.widget()
nextX = x + item.sizeHint().width() + self.spaceX
if nextX - self.spaceX > rect.right() and lineHeight > 0:
x = rect.x()
y = y + lineHeight + self.spaceY
nextX = x + item.sizeHint().width() + self.spaceX
lineHeight = 0
if not testOnly:
item.setGeometry(QRect(QPoint(x,y),item.sizeHint()))
x = nextX
lineHeight = max(lineHeight,item.sizeHint().height())
return y + lineHeight - rect.y()
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
问题从何而来?
解决方法
鼠标左键时,当是mousePressEvent时,正常工作,当是mouseReleaseEvent时,widget选择有问题。 我现在已经解决了 代码是
def closeRubberBand(self):
if self.rubberBand.isVisible():
self.rubberBand.hide()
selected = []
rect = self.rubberBand.geometry()
for child in self.findChildren(QToolButton):
if self.flow_layout_widget:
layout_x = self.flow_layout_widget.pos().toTuple()[0]
layout_y = self.flow_layout_widget.pos().toTuple()[1]
child_w = child.geometry().size().toTuple()[0]
child_h = child.geometry().size().toTuple()[1]
cx,cy,cw,ch = (child.geometry().x() + layout_x,child.geometry().y() + layout_y,child_w,child_h)
child_rect = QRect(cx,ch)
else:
child_rect = child.geometry()
if rect.intersects(child_rect):
selected.append(child)
if selected:
for i in selected:
if i.isChecked():
i.setChecked(False)
else:
i.setChecked(True)
有没有更简单的方法?