我正在尝试创建一个可调整大小的QGraphicsRectItem,可以选择不同的绘制样式。
如果我只创建一个带有调整大小功能的简单矩形,那么它按预期工作:
class Rectangle(QtWidgets.QGraphicsRectItem):
def __init__(self, x, y, w, h):
super(Rectangle, self).__init__(0, 0, w, h)
self.setPen(QtGui.QPen(QtCore.Qt.red, 2))
self.setFlags(QtWidgets.QGraphicsItem.ItemIsSelectable
| QtWidgets.QGraphicsItem.ItemIsMovable
| QtWidgets.QGraphicsItem.ItemIsFocusable
| QtWidgets.QGraphicsItem.ItemSendsGeometryChanges
| QtWidgets.QGraphicsItem.ItemSendsScenePositionChanges)
self.setPos(QtCore.QPointF(x, y))
self.rect = rect = QtCore.QRectF(0, 0, 200, 200)
def boundingRect(self):
return self.rect.adjusted(-10, -10, 10, 10)
def mouseMoveEvent(self, event):
if event.buttons() & QtCore.Qt.LeftButton:
super(Rectangle, self).mouseMoveEvent(event)
if event.buttons() & QtCore.Qt.RightButton:
self.rect = QtCore.QRectF(QtCore.QPoint(), event.pos()).normalized()
self.prepareGeometryChange()
self.setRect(self.rect)
当我尝试修改它以更改笔样式和颜色(如果处于活动状态)时,它变得无法选择且无法对焦。更重要的是,边界矩形意外消失。这是一个修改版本:
class Rectangle(QtWidgets.QGraphicsRectItem):
def __init__(self, position, scene, style=QtCore.Qt.SolidLine,
rect=None, matrix=QtGui.QMatrix()):
super(Rectangle, self).__init__()
# self.setPen(QtGui.QPen(QtCore.Qt.red, 2))
self.setFlags(QtWidgets.QGraphicsItem.ItemIsSelectable
| QtWidgets.QGraphicsItem.ItemIsMovable
| QtWidgets.QGraphicsItem.ItemIsFocusable
| QtWidgets.QGraphicsItem.ItemSendsGeometryChanges
| QtWidgets.QGraphicsItem.ItemSendsScenePositionChanges)
if rect is None:
rect = QtCore.QRectF(0, 0, 200, 200)
self.size = QtCore.QPointF(200, 200)
self.rect = rect
self.style = style
self.setPos(position)
self.setMatrix(matrix)
scene.clearSelection()
scene.addItem(self)
self.setSelected(True)
self.setFocus()
global RAW
RAW = True
self.pen = QtGui.QPen(self.style)
self.pen.setColor(QtCore.Qt.black)
self.pen.setWidth(1)
def parentWidget(self):
return self.scene().views()[0]
def boundingRect(self):
return self.rect.adjusted(-10, -10, 10, 10)
def paint(self, painter, option, widget):
if option.state & QtWidgets.QStyle.State_Selected:
self.pen.setColor(QtCore.Qt.blue)
painter.setPen(self.pen)
painter.drawRect(self.rect)
def itemChange(self, change, variant):
if change != QtWidgets.QGraphicsItem.ItemSelectedChange:
global RAW
RAW = True
return QtWidgets.QGraphicsItem.itemChange(self, change, variant)
def contextMenuEvent(self, event):
wrapped = []
menu = QtWidgets.QMenu(self.parentWidget())
for text, param in (("&Solid", QtCore.Qt.SolidLine),
("&Dashed", QtCore.Qt.DashLine),
("D&otted", QtCore.Qt.DotLine),
("D&ashDotted", QtCore.Qt.DashDotLine),
("DashDo&tDotten", QtCore.Qt.DashDotDotLine)):
wrapper = functools.partial(self.setStyle, param)
wrapped.append(wrapper)
menu.addAction(text, wrapper)
menu.exec_(event.screenPos())
def setStyle(self, style):
#self.prepareGeometryChange()
self.style = style
self.update()
global RAW
RAW = True
def mousePressEvent(self, event):
if event.buttons() & QtCore.Qt.LeftButton:
super(Rectangle, self).mouseMoveEvent(event)
if event.buttons() & QtCore.Qt.MiddleButton:
if self.isSelected():
self.rect = QtCore.QRectF(QtCore.QPoint(), event.pos()).normalized()
self.prepareGeometryChange()
self.setRect(self.rect)
global RAW
RAW = True
我想主要的问题在于重新实现的paint()函数,但是我仍然没有想出任何确切的...
谁能解释我做错了什么?错误在哪里以及如何使这个东西正常工作?
我的触摸板上没有中间按钮所以我用右按钮实现了逻辑,但是我给了10px的小边缘,你可以改变矩形的大小。
要更改样式,您只需更改QGraphicsItem的QPen。
import functools
from PyQt5 import QtCore, QtGui, QtWidgets
class Rectangle(QtWidgets.QGraphicsRectItem):
def __init__(self, x, y, w, h):
super(Rectangle, self).__init__(0, 0, w, h)
self.setPen(QtGui.QPen(QtCore.Qt.red, 2))
self.setFlags(QtWidgets.QGraphicsItem.ItemIsSelectable
| QtWidgets.QGraphicsItem.ItemIsMovable
| QtWidgets.QGraphicsItem.ItemIsFocusable
| QtWidgets.QGraphicsItem.ItemSendsGeometryChanges
| QtWidgets.QGraphicsItem.ItemSendsScenePositionChanges)
self.setPos(QtCore.QPointF(x, y))
def mouseMoveEvent(self, event):
if event.buttons() & QtCore.Qt.LeftButton:
super(Rectangle, self).mouseMoveEvent(event)
if event.buttons() & QtCore.Qt.RightButton:
rect = QtCore.QRectF(QtCore.QPoint(), event.pos()).normalized()
self.prepareGeometryChange()
self.setRect(rect)
def contextMenuEvent(self, event):
super(Rectangle, self).contextMenuEvent(event)
delta = 10
r = self.boundingRect()
r.adjust(delta, delta, -delta, -delta)
if not r.contains(event.pos()):
return
self.setSelected(True)
wrapped = []
menu = QtWidgets.QMenu(self.parentWidget())
for text, param in (("&Solid", QtCore.Qt.SolidLine),
("&Dashed", QtCore.Qt.DashLine),
("D&otted", QtCore.Qt.DotLine),
("D&ashDotted", QtCore.Qt.DashDotLine),
("DashDo&tDotten", QtCore.Qt.DashDotDotLine)):
wrapper = functools.partial(self.setStyle, param)
wrapped.append(wrapper)
menu.addAction(text, wrapper)
menu.exec_(event.screenPos())
def paint(self, painter, option, widget):
painter.setPen(self.pen())
painter.setBrush(self.brush())
if option.state & QtWidgets.QStyle.State_Selected:
pen = self.pen()
pen.setColor(QtCore.Qt.blue)
painter.setPen(pen)
painter.setBrush(QtCore.Qt.NoBrush)
painter.drawRect(self.boundingRect())
def setStyle(self, style):
pen = self.pen()
pen.setStyle(style)
self.setPen(pen)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
scene = QtWidgets.QGraphicsScene(-400, -400, 800, 800)
w = QtWidgets.QGraphicsView(scene)
scene.addItem(Rectangle(100, 100, 100, 100))
w.show()
sys.exit(app.exec_())