我有一个问题,当我调整其中一个“Test_Boxes”时,所有其他现有的Text_Box都会调整大小,之后创建的任何内容都会以调整大小的大小创建。
似乎他们都共享相同的QRect但他们不应该。
请帮忙。
import sys, sip, random
from PyQt4.QtCore import *
from PyQt4.QtGui import *
PAGESIZE_LST = [612, 792]
POINT_SIZE = 10
CURSOR_SIZE = 2 * POINT_SIZE
BORDER_WIDTH = 0.5 * POINT_SIZE
def Cursor_Pos(item):
# Get mouse position relative to this item
cursor_pos = item.scene().parent().mapFromGlobal(QCursor.pos())
cursor_pos = item.scene().views()[0].mapToScene(cursor_pos)
cursor_pos = item.mapFromScene(cursor_pos)
return cursor_pos
class Test_Box(QGraphicsItem):
""" Group box that groups the various stages """
# Constants
WIDTH = 70 * POINT_SIZE
HEIGHT = 100 * POINT_SIZE
RECT = QRectF(0, 0, WIDTH, HEIGHT)
CORNER_RADIUS = 1.5 * POINT_SIZE
FONT_SIZE = 4 * POINT_SIZE
BORDERRECT_PAD = 4 * POINT_SIZE
def __init__(self, position, parent=None):
super(Test_Box, self).__init__(parent)
# Vars
self.resize_sections= None
self.resize_pos = None
self.rect = Test_Box.RECT
# Settings
self.setFlags( self.flags() |
QGraphicsItem.ItemIsSelectable |
QGraphicsItem.ItemIsMovable |
QGraphicsItem.ItemIsFocusable )
def boundingRect(self):
return self.rect.adjusted(-BORDER_WIDTH/2,-BORDER_WIDTH/2,BORDER_WIDTH/2,BORDER_WIDTH/2)
def paint(self, painter, option, widget):
# Draw Box
# Inner and outer rect to display drag-expand's clickable area
outer_rect = self.boundingRect().adjusted(-Test_Box.BORDERRECT_PAD,-Test_Box.BORDERRECT_PAD,CURSOR_SIZE+Test_Box.BORDERRECT_PAD,CURSOR_SIZE+Test_Box.BORDERRECT_PAD)
inner_bound = (BORDER_WIDTH/2 + (Test_Box.CORNER_RADIUS/2)) # Get corner offset due to rounded corners
inner_rect = self.boundingRect().adjusted((CURSOR_SIZE+inner_bound)+Test_Box.BORDERRECT_PAD, (CURSOR_SIZE+inner_bound)+Test_Box.BORDERRECT_PAD, -inner_bound-Test_Box.BORDERRECT_PAD, -inner_bound-Test_Box.BORDERRECT_PAD)
painter.drawRect(outer_rect)
painter.drawRect(inner_rect)
brush = QBrush(QColor(100, 100, 100, 100))
painter.setBrush(brush)
painter.drawRoundedRect(self.rect, Test_Box.CORNER_RADIUS, Test_Box.CORNER_RADIUS)
def Cursor_OnEdge(self):
outer_rect = self.boundingRect().adjusted(-Test_Box.BORDERRECT_PAD,-Test_Box.BORDERRECT_PAD,CURSOR_SIZE+Test_Box.BORDERRECT_PAD,CURSOR_SIZE+Test_Box.BORDERRECT_PAD)
inner_bound = (BORDER_WIDTH/2 + (Test_Box.CORNER_RADIUS/2)) # Get corner offset due to rounded corners
inner_rect = self.boundingRect().adjusted((CURSOR_SIZE+inner_bound)+Test_Box.BORDERRECT_PAD, (CURSOR_SIZE+inner_bound)+Test_Box.BORDERRECT_PAD, -inner_bound-Test_Box.BORDERRECT_PAD, -inner_bound-Test_Box.BORDERRECT_PAD)
cursor_pos = Cursor_Pos(self)
on_edge = False
if outer_rect.contains(cursor_pos) and not inner_rect.contains(cursor_pos):
on_edge = True
return on_edge
def mousePressEvent(self, event):
# check if user has clicked this object's border
if self.Cursor_OnEdge():
self.Setup_Resize()
super(Test_Box, self).mousePressEvent(event)
def mouseMoveEvent(self, event):
if self.resize_pos != None:
self.Resize()
else:
super(Test_Box, self).mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
if self.resize_pos != None:
self.Done_Resize()
super(Test_Box, self).mouseReleaseEvent(event)
def Setup_Resize(self):
self.resize_sections= []
self.setCursor(Qt.ClosedHandCursor)
cursor_pos = Cursor_Pos(self)
self.resize_pos = cursor_pos
# Determine drag from sections
if cursor_pos.y() > self.boundingRect().height()/2:
# If on bottom half
self.resize_sections.append('BOTTOM')
else:
self.resize_sections.append('TOP')
if cursor_pos.x() < self.boundingRect().width()/2:
# If on left half
self.resize_sections.append('LEFT')
else:
self.resize_sections.append('RIGHT')
def Resize(self):
updated = False
# From cursor_pos to resize_pos
cursor_pos = Cursor_Pos(self)
move_x = cursor_pos.x() - self.resize_pos.x()
move_y = cursor_pos.y() - self.resize_pos.y()
child_rect = self.childrenBoundingRect()
# If y not within child items rect
if not child_rect.contains(child_rect.left()+1, cursor_pos.y()):
if self.resize_sections[0] == 'TOP':
self.rect.setTop(self.rect.top() + move_y)
else:
self.rect.setBottom(self.rect.bottom() + move_y)
updated = True
# If x not within child items rect
if not child_rect.contains(cursor_pos.x(), child_rect.top()+1):
if self.resize_sections[1] == 'LEFT':
self.rect.setLeft(self.rect.left() + move_x)
else:
self.rect.setRight(self.rect.right() + move_x)
updated = True
# Check if updated
if updated:
self.scene().update()
self.resize_pos = cursor_pos
def Done_Resize(self):
self.resize_pos = None
self.setCursor(Qt.ArrowCursor)
class GraphicsView(QGraphicsView):
def __init__(self, parent=None):
super(GraphicsView, self).__init__(parent)
self.setDragMode(QGraphicsView.RubberBandDrag)
self.setRenderHint(QPainter.Antialiasing)
self.setRenderHint(QPainter.TextAntialiasing)
def wheelEvent(self, event):
factor = 1.41 ** (event.delta() / 240.0)
self.scale(factor, factor)
class Main_Dlg(QDialog):
OFFSET = 5
def __init__(self, parent=None):
super(Main_Dlg, self).__init__(parent)
self.from_linkPnt= None
self.prev_pnt = QPoint()
self.add_offset = Main_Dlg.OFFSET
self.prntr = QPrinter(QPrinter.HighResolution)
self.prntr.setPageSize(QPrinter.Letter)
self.view = GraphicsView()
self.scene = QGraphicsScene(self)
self.scene.setSceneRect(0, 0, PAGESIZE_LST[0], PAGESIZE_LST[1])
self.view.setScene(self.scene)
linkPnt_btn = QPushButton("Add Stage Box")
linkPnt_btn.clicked.connect(self.Add_Item)
layout = QVBoxLayout()
layout.addWidget(self.view)
layout.addWidget(linkPnt_btn)
self.setLayout(layout)
self.Add_Item()
def position(self):
point = self.mapFromGlobal(QCursor.pos())
if not self.view.geometry().contains(point):
coord_x = random.randint(int(PAGESIZE_LST[0]*0.25), int(PAGESIZE_LST[0]*0.75))
coord_y = random.randint(int(PAGESIZE_LST[1]*0.25), int(PAGESIZE_LST[1]*0.75))
point = QPoint(coord_x, coord_y)
else:
if point == self.prev_pnt:
point += QPoint(self.add_offset, self.add_offset)
self.add_offset += 5
else:
self.add_offset = Main_Dlg.OFFSET
self.prev_pnt = point
return self.view.mapToScene(point)
def Add_Item(self):
item = Test_Box(self.position())
self.scene.addItem(item)
app = QApplication(sys.argv)
form = Main_Dlg()
rect = QApplication.desktop().availableGeometry()
form.resize(int(rect.width() * 0.6), int(rect.height() * 0.9))
form.show()
app.exec_()
答案 0 :(得分:2)
是的,他们 共享相同的QRect
,因为您在分配到self.rect
时没有创建它的副本:
class Test_Box(QGraphicsItem):
""" Group box that groups the various stages """
# Constants
WIDTH = 70 * POINT_SIZE
HEIGHT = 100 * POINT_SIZE
RECT = QRectF(0, 0, WIDTH, HEIGHT)
CORNER_RADIUS = 1.5 * POINT_SIZE
FONT_SIZE = 4 * POINT_SIZE
BORDERRECT_PAD = 4 * POINT_SIZE
def __init__(self, position, parent=None):
super(Test_Box, self).__init__(parent)
# Vars
self.resize_sections= None
self.resize_pos = None
self.rect = QRectF(Test_Box.RECT) #use a copy!
# Settings
self.setFlags( self.flags() |
QGraphicsItem.ItemIsSelectable |
QGraphicsItem.ItemIsMovable |
QGraphicsItem.ItemIsFocusable )
此外,您正确地在boundingRect()
中返回一个新矩形,但在调整大小时修改共享矩形,这就是为什么所有实例都会相应调整大小。
我认为从一开始就使用self.rect
的副本就可以解决这个问题。