如何使选定的 qgraphicsitem 的边界矩形自动显示?
How to make the bounding rect of a selected qgraphicsitem show automatically?
我在 SO 中通过 @serge_gubenko 找到了这个例子。
Moving a QGraphicsItem around a central point in PyQt4
然后我做了一些修改以结束:
如果我运行示例 (Moving a QGraphicsItem around a central point in PyQt4) 并单击图形项,它会自动显示一个虚线框,表明它已被选中。我准备了图片来展示效果,但由于我的声誉不高,我还不允许上传这些 ;)
对我来说,虚线框旁的 "is selected indication" 似乎是自动出现的。
在我修改的示例 () 中,这并没有发生,我不明白为什么?
您使用了QtGui.QGraphicsItem,所以您定义了boundingRect 和paint 方法,其中您使用了painter drawEllipse 方法。在您找到的第一个示例中,class 直接使用 QtGui.QGraphicsEllipseItem 并且它做了所有不同的事情,因为那些方法已经定义了。顺便说一句,我没有找到为什么 boundingRect 没有在你的案例中绘制。
这是一个工作示例,它有自己的 drawFocusRect 方法。
焦点有两种表示方式:
1)通过点击Qgraphicsitem,然后绘制边界矩形。
2) 将鼠标悬停在项目上。触发时 hoverEnterEvent the pen style is changed to DotLine converting back to SolidLine when the hoverLeaveEvent 被触发。
#!d:/python27/python -u
import sys
from PyQt4 import QtGui, QtCore
class GraphicsItem(QtGui.QGraphicsItem):
"""
From the QT docs:
To write your own graphics item, you first create a subclass
of QGraphicsItem, and then start by implementing its two pure
virtual public functions: boundingRect(), which returns an estimate
of the area painted by the item, and paint(),
which implements the actual painting.
"""
# call constructor of GraphicsItem
def __init__(self, rect, pen, brush, tooltip='No tip here', parent=None):
# call constructor of QGraphicsItem
super(GraphicsItem, self).__init__()
self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
self.setFlag(QtGui.QGraphicsItem.ItemIsFocusable, True)
self.setAcceptsHoverEvents(True)
self.pen = pen
pw = self.pen.widthF()
self.brush = QtGui.QBrush(QtCore.Qt.blue)
self.brush = brush
self.setToolTip(tooltip)
self.parent = parent
self.rect = QtCore.QRectF(rect[0], rect[1], rect[2], rect[3])
self.focusrect = QtCore.QRectF(rect[0]-pw/2, rect[1]-pw/2,
rect[2]+pw, rect[3]+pw)
def mouseMoveEvent(self, event):
# move object
QtGui.QGraphicsItem.mouseMoveEvent(self, event)
def mousePressEvent(self, event):
# select object
# set item as topmost in stack
self.setZValue(self.parent.scene.items()[0].zValue() + 1)
self.setSelected(True)
QtGui.QGraphicsItem.mousePressEvent(self, event)
def boundingRect(self):
return self.rect
def paint(self, painter, option, widget):
painter.setBrush(self.brush)
painter.setPen(self.pen)
painter.drawEllipse(self.rect)
if self.isSelected():
self.drawFocusRect(painter)
def drawFocusRect(self, painter):
self.focusbrush = QtGui.QBrush()
self.focuspen = QtGui.QPen(QtCore.Qt.DotLine)
self.focuspen.setColor(QtCore.Qt.black)
self.focuspen.setWidthF(1.5)
painter.setBrush(self.focusbrush)
painter.setPen(self.focuspen)
painter.drawRect(self.focusrect)
def hoverEnterEvent(self, event):
self.pen.setStyle(QtCore.Qt.DotLine)
QtGui.QGraphicsItem.hoverEnterEvent(self, event)
def hoverLeaveEvent(self, event):
self.pen.setStyle(QtCore.Qt.SolidLine)
QtGui.QGraphicsItem.hoverLeaveEvent(self, event)
class MyMainWindow(QtGui.QMainWindow):
# call constructor of MyMainWindow
def __init__(self, parent=None):
# call constructor of QMainWindow
super(MyMainWindow, self).__init__(parent)
w = 1000
h = 800
self.scene = QtGui.QGraphicsScene(-w/2, -h/2, w, h)
self.view = QtGui.QGraphicsView()
# set QGraphicsView attributes
self.view.setRenderHints(QtGui.QPainter.Antialiasing |
QtGui.QPainter.HighQualityAntialiasing)
self.view.setViewportUpdateMode(QtGui.QGraphicsView.FullViewportUpdate)
self.view.setScene(self.scene)
# set central widget for the application
self.setCentralWidget(self.view)
# add items to the scene
self.addGraphicsItem((0, 0, 250, 250), 8.0, (255, 0, 0), (0, 0, 255), 'My first item')
self.addGraphicsItem((-250, -250, 300, 200), 4.0, (0, 0, 0), (255, 0, 100), 'My 2nd item')
self.addGraphicsItem((200, -200, 200, 200), 10.0, (0, 0, 255), (0, 255, 100), 'My 3rd item')
def addGraphicsItem(self, rect, pw, pc, bc, tooltip):
pen = QtGui.QPen(QtCore.Qt.SolidLine)
pen.setColor(QtGui.QColor(pc[0], pc[1], pc[2], 255))
pen.setWidth(pw)
brush = QtGui.QBrush(QtGui.QColor(bc[0], bc[1], bc[2], 255))
item = GraphicsItem(rect, pen, brush, tooltip, self)
self.scene.addItem(item)
def mousePressEvent(self, event):
#print 'from MainWindow'
pass
def keyPressEvent(self, event):
key = event.key()
if key == QtCore.Qt.Key_Escape:
sys.exit(QtGui.qApp.quit())
else:
super(GraphicsView, self).keyPressEvent(event)
def main():
app = QtGui.QApplication(sys.argv)
form = MyMainWindow()
form.setGeometry(700, 100, 1050, 850)
form.show()
app.exec_()
if __name__ == '__main__':
main()
针对 PyQt5 更新
import sys
from PyQt5 import QtGui, QtCore, QtWidgets
class GraphicsItem(QtWidgets.QGraphicsItem):
"""
From the QT docs:
To write your own graphics item, you first create a subclass
of QGraphicsItem, and then start by implementing its two pure
virtual public functions: boundingRect(), which returns an estimate
of the area painted by the item, and paint(),
which implements the actual painting.
"""
# call constructor of GraphicsItem
def __init__(self, rect, pen, brush, tooltip='No tip here', parent=None):
# call constructor of QGraphicsItem
super(GraphicsItem, self).__init__()
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)
self.setFlag(QtWidgets.QGraphicsItem.ItemIsSelectable, True)
self.setFlag(QtWidgets.QGraphicsItem.ItemIsFocusable, True)
self.setAcceptHoverEvents(True)
self.pen = pen
pw = self.pen.widthF()
self.brush = QtGui.QBrush(QtCore.Qt.blue)
self.brush = brush
self.setToolTip(tooltip)
self.parent = parent
self.rect = QtCore.QRectF(rect[0], rect[1], rect[2], rect[3])
self.focusrect = QtCore.QRectF(rect[0]-pw/2, rect[1]-pw/2,
rect[2]+pw, rect[3]+pw)
def mouseMoveEvent(self, event):
# move object
QtWidgets.QGraphicsItem.mouseMoveEvent(self, event)
def mousePressEvent(self, event):
# select object
# set item as topmost in stack
self.setZValue(self.parent.scene.items()[0].zValue() + 1)
self.setSelected(True)
QtWidgets.QGraphicsItem.mousePressEvent(self, event)
def boundingRect(self):
return self.rect
def paint(self, painter, option, widget=None):
painter.setBrush(self.brush)
painter.setPen(self.pen)
painter.drawEllipse(self.rect)
if self.isSelected():
self.drawFocusRect(painter)
def drawFocusRect(self, painter):
self.focusbrush = QtGui.QBrush()
self.focuspen = QtGui.QPen(QtCore.Qt.DotLine)
self.focuspen.setColor(QtCore.Qt.black)
self.focuspen.setWidthF(1.5)
painter.setBrush(self.focusbrush)
painter.setPen(self.focuspen)
painter.drawRect(self.focusrect)
def hoverEnterEvent(self, event):
self.pen.setStyle(QtCore.Qt.DotLine)
QtWidgets.QGraphicsItem.hoverEnterEvent(self, event)
def hoverLeaveEvent(self, event):
self.pen.setStyle(QtCore.Qt.SolidLine)
QtWidgets.QGraphicsItem.hoverLeaveEvent(self, event)
class MyMainWindow(QtWidgets.QMainWindow):
# call constructor of MyMainWindow
def __init__(self, parent=None):
# call constructor of QMainWindow
super(MyMainWindow, self).__init__(parent)
w = 1000
h = 800
self.scene = QtWidgets.QGraphicsScene(-w/2, -h/2, w, h)
self.view = QtWidgets.QGraphicsView()
# set QGraphicsView attributes
self.view.setRenderHints(QtGui.QPainter.Antialiasing |
QtGui.QPainter.HighQualityAntialiasing)
self.view.setViewportUpdateMode(QtWidgets.QGraphicsView.FullViewportUpdate)
self.view.setScene(self.scene)
# set central widget for the application
self.setCentralWidget(self.view)
# add items to the scene
self.addGraphicsItem((0, 0, 250, 250), 8.0, (255, 0, 0), (0, 0, 255), 'My first item')
self.addGraphicsItem((-250, -250, 300, 200), 4.0, (0, 0, 0), (255, 0, 100), 'My 2nd item')
self.addGraphicsItem((200, -200, 200, 200), 10.0, (0, 0, 255), (0, 255, 100), 'My 3rd item')
def addGraphicsItem(self, rect, pw, pc, bc, tooltip):
pen = QtGui.QPen(QtCore.Qt.SolidLine)
pen.setColor(QtGui.QColor(pc[0], pc[1], pc[2], 255))
pen.setWidth(pw)
brush = QtGui.QBrush(QtGui.QColor(bc[0], bc[1], bc[2], 255))
item = GraphicsItem(rect, pen, brush, tooltip, self)
self.scene.addItem(item)
def mousePressEvent(self, event):
#print 'from MainWindow'
pass
def main():
app = QtWidgets.QApplication(sys.argv)
form = MyMainWindow()
form.setGeometry(700, 100, 1050, 850)
form.show()
app.exec_()
if __name__ == '__main__':
main()
我在 SO 中通过 @serge_gubenko 找到了这个例子。 Moving a QGraphicsItem around a central point in PyQt4
然后我做了一些修改以结束:
如果我运行示例 (Moving a QGraphicsItem around a central point in PyQt4) 并单击图形项,它会自动显示一个虚线框,表明它已被选中。我准备了图片来展示效果,但由于我的声誉不高,我还不允许上传这些 ;)
对我来说,虚线框旁的 "is selected indication" 似乎是自动出现的。
在我修改的示例 (
您使用了QtGui.QGraphicsItem,所以您定义了boundingRect 和paint 方法,其中您使用了painter drawEllipse 方法。在您找到的第一个示例中,class 直接使用 QtGui.QGraphicsEllipseItem 并且它做了所有不同的事情,因为那些方法已经定义了。顺便说一句,我没有找到为什么 boundingRect 没有在你的案例中绘制。
这是一个工作示例,它有自己的 drawFocusRect 方法。
焦点有两种表示方式:
1)通过点击Qgraphicsitem,然后绘制边界矩形。
2) 将鼠标悬停在项目上。触发时 hoverEnterEvent the pen style is changed to DotLine converting back to SolidLine when the hoverLeaveEvent 被触发。
#!d:/python27/python -u
import sys
from PyQt4 import QtGui, QtCore
class GraphicsItem(QtGui.QGraphicsItem):
"""
From the QT docs:
To write your own graphics item, you first create a subclass
of QGraphicsItem, and then start by implementing its two pure
virtual public functions: boundingRect(), which returns an estimate
of the area painted by the item, and paint(),
which implements the actual painting.
"""
# call constructor of GraphicsItem
def __init__(self, rect, pen, brush, tooltip='No tip here', parent=None):
# call constructor of QGraphicsItem
super(GraphicsItem, self).__init__()
self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
self.setFlag(QtGui.QGraphicsItem.ItemIsFocusable, True)
self.setAcceptsHoverEvents(True)
self.pen = pen
pw = self.pen.widthF()
self.brush = QtGui.QBrush(QtCore.Qt.blue)
self.brush = brush
self.setToolTip(tooltip)
self.parent = parent
self.rect = QtCore.QRectF(rect[0], rect[1], rect[2], rect[3])
self.focusrect = QtCore.QRectF(rect[0]-pw/2, rect[1]-pw/2,
rect[2]+pw, rect[3]+pw)
def mouseMoveEvent(self, event):
# move object
QtGui.QGraphicsItem.mouseMoveEvent(self, event)
def mousePressEvent(self, event):
# select object
# set item as topmost in stack
self.setZValue(self.parent.scene.items()[0].zValue() + 1)
self.setSelected(True)
QtGui.QGraphicsItem.mousePressEvent(self, event)
def boundingRect(self):
return self.rect
def paint(self, painter, option, widget):
painter.setBrush(self.brush)
painter.setPen(self.pen)
painter.drawEllipse(self.rect)
if self.isSelected():
self.drawFocusRect(painter)
def drawFocusRect(self, painter):
self.focusbrush = QtGui.QBrush()
self.focuspen = QtGui.QPen(QtCore.Qt.DotLine)
self.focuspen.setColor(QtCore.Qt.black)
self.focuspen.setWidthF(1.5)
painter.setBrush(self.focusbrush)
painter.setPen(self.focuspen)
painter.drawRect(self.focusrect)
def hoverEnterEvent(self, event):
self.pen.setStyle(QtCore.Qt.DotLine)
QtGui.QGraphicsItem.hoverEnterEvent(self, event)
def hoverLeaveEvent(self, event):
self.pen.setStyle(QtCore.Qt.SolidLine)
QtGui.QGraphicsItem.hoverLeaveEvent(self, event)
class MyMainWindow(QtGui.QMainWindow):
# call constructor of MyMainWindow
def __init__(self, parent=None):
# call constructor of QMainWindow
super(MyMainWindow, self).__init__(parent)
w = 1000
h = 800
self.scene = QtGui.QGraphicsScene(-w/2, -h/2, w, h)
self.view = QtGui.QGraphicsView()
# set QGraphicsView attributes
self.view.setRenderHints(QtGui.QPainter.Antialiasing |
QtGui.QPainter.HighQualityAntialiasing)
self.view.setViewportUpdateMode(QtGui.QGraphicsView.FullViewportUpdate)
self.view.setScene(self.scene)
# set central widget for the application
self.setCentralWidget(self.view)
# add items to the scene
self.addGraphicsItem((0, 0, 250, 250), 8.0, (255, 0, 0), (0, 0, 255), 'My first item')
self.addGraphicsItem((-250, -250, 300, 200), 4.0, (0, 0, 0), (255, 0, 100), 'My 2nd item')
self.addGraphicsItem((200, -200, 200, 200), 10.0, (0, 0, 255), (0, 255, 100), 'My 3rd item')
def addGraphicsItem(self, rect, pw, pc, bc, tooltip):
pen = QtGui.QPen(QtCore.Qt.SolidLine)
pen.setColor(QtGui.QColor(pc[0], pc[1], pc[2], 255))
pen.setWidth(pw)
brush = QtGui.QBrush(QtGui.QColor(bc[0], bc[1], bc[2], 255))
item = GraphicsItem(rect, pen, brush, tooltip, self)
self.scene.addItem(item)
def mousePressEvent(self, event):
#print 'from MainWindow'
pass
def keyPressEvent(self, event):
key = event.key()
if key == QtCore.Qt.Key_Escape:
sys.exit(QtGui.qApp.quit())
else:
super(GraphicsView, self).keyPressEvent(event)
def main():
app = QtGui.QApplication(sys.argv)
form = MyMainWindow()
form.setGeometry(700, 100, 1050, 850)
form.show()
app.exec_()
if __name__ == '__main__':
main()
针对 PyQt5 更新
import sys
from PyQt5 import QtGui, QtCore, QtWidgets
class GraphicsItem(QtWidgets.QGraphicsItem):
"""
From the QT docs:
To write your own graphics item, you first create a subclass
of QGraphicsItem, and then start by implementing its two pure
virtual public functions: boundingRect(), which returns an estimate
of the area painted by the item, and paint(),
which implements the actual painting.
"""
# call constructor of GraphicsItem
def __init__(self, rect, pen, brush, tooltip='No tip here', parent=None):
# call constructor of QGraphicsItem
super(GraphicsItem, self).__init__()
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)
self.setFlag(QtWidgets.QGraphicsItem.ItemIsSelectable, True)
self.setFlag(QtWidgets.QGraphicsItem.ItemIsFocusable, True)
self.setAcceptHoverEvents(True)
self.pen = pen
pw = self.pen.widthF()
self.brush = QtGui.QBrush(QtCore.Qt.blue)
self.brush = brush
self.setToolTip(tooltip)
self.parent = parent
self.rect = QtCore.QRectF(rect[0], rect[1], rect[2], rect[3])
self.focusrect = QtCore.QRectF(rect[0]-pw/2, rect[1]-pw/2,
rect[2]+pw, rect[3]+pw)
def mouseMoveEvent(self, event):
# move object
QtWidgets.QGraphicsItem.mouseMoveEvent(self, event)
def mousePressEvent(self, event):
# select object
# set item as topmost in stack
self.setZValue(self.parent.scene.items()[0].zValue() + 1)
self.setSelected(True)
QtWidgets.QGraphicsItem.mousePressEvent(self, event)
def boundingRect(self):
return self.rect
def paint(self, painter, option, widget=None):
painter.setBrush(self.brush)
painter.setPen(self.pen)
painter.drawEllipse(self.rect)
if self.isSelected():
self.drawFocusRect(painter)
def drawFocusRect(self, painter):
self.focusbrush = QtGui.QBrush()
self.focuspen = QtGui.QPen(QtCore.Qt.DotLine)
self.focuspen.setColor(QtCore.Qt.black)
self.focuspen.setWidthF(1.5)
painter.setBrush(self.focusbrush)
painter.setPen(self.focuspen)
painter.drawRect(self.focusrect)
def hoverEnterEvent(self, event):
self.pen.setStyle(QtCore.Qt.DotLine)
QtWidgets.QGraphicsItem.hoverEnterEvent(self, event)
def hoverLeaveEvent(self, event):
self.pen.setStyle(QtCore.Qt.SolidLine)
QtWidgets.QGraphicsItem.hoverLeaveEvent(self, event)
class MyMainWindow(QtWidgets.QMainWindow):
# call constructor of MyMainWindow
def __init__(self, parent=None):
# call constructor of QMainWindow
super(MyMainWindow, self).__init__(parent)
w = 1000
h = 800
self.scene = QtWidgets.QGraphicsScene(-w/2, -h/2, w, h)
self.view = QtWidgets.QGraphicsView()
# set QGraphicsView attributes
self.view.setRenderHints(QtGui.QPainter.Antialiasing |
QtGui.QPainter.HighQualityAntialiasing)
self.view.setViewportUpdateMode(QtWidgets.QGraphicsView.FullViewportUpdate)
self.view.setScene(self.scene)
# set central widget for the application
self.setCentralWidget(self.view)
# add items to the scene
self.addGraphicsItem((0, 0, 250, 250), 8.0, (255, 0, 0), (0, 0, 255), 'My first item')
self.addGraphicsItem((-250, -250, 300, 200), 4.0, (0, 0, 0), (255, 0, 100), 'My 2nd item')
self.addGraphicsItem((200, -200, 200, 200), 10.0, (0, 0, 255), (0, 255, 100), 'My 3rd item')
def addGraphicsItem(self, rect, pw, pc, bc, tooltip):
pen = QtGui.QPen(QtCore.Qt.SolidLine)
pen.setColor(QtGui.QColor(pc[0], pc[1], pc[2], 255))
pen.setWidth(pw)
brush = QtGui.QBrush(QtGui.QColor(bc[0], bc[1], bc[2], 255))
item = GraphicsItem(rect, pen, brush, tooltip, self)
self.scene.addItem(item)
def mousePressEvent(self, event):
#print 'from MainWindow'
pass
def main():
app = QtWidgets.QApplication(sys.argv)
form = MyMainWindow()
form.setGeometry(700, 100, 1050, 850)
form.show()
app.exec_()
if __name__ == '__main__':
main()