【发布时间】:2020-02-03 01:52:53
【问题描述】:
我目前在理解 QGraphicsScene 中 QGraphicsAnchorLayout 的行为时遇到问题。我创建了 4 个框并锚定了每个框的角,但似乎没有正确应用锚点,或者至少没有像我认为的那样。
黄色框应始终位于 QGraphicsScene 的左上角,即使在 GraphicsView 展开时也是如此。蓝色框被锚定在右侧的黄色框旁边,其顶部与 QGraphicsScene/viewport 的顶部重合。
绿色框的左上角固定在蓝色框的右下角,红色框也固定在绿色框的右下角。但这就是我得到的:
我希望黄色框始终位于图形场景/视口的顶部。而且我希望它即使在向右滚动时也始终保持可见,但我相信这可能是一个单独的问题。但是,当我垂直展开窗口时,所有框都居中,包括我希望保留在顶部的黄色框。
蓝色、绿色和红色框似乎与我应用的锚点没有相似之处。
以下是我用来生成它的代码。这些锚是如何工作的,我可以做些什么来纠正这个问题?
import numpy as np
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
from debug_utils import *
from PyQt5.QtWidgets import QGraphicsAnchorLayout, QGraphicsWidget, QGraphicsLayoutItem
def qp(p):
return "({}, {})".format(p.x(), p.y())
class box(QtWidgets.QGraphicsWidget):
pressed = QtCore.pyqtSignal()
def __init__(self, rect, color, parent=None):
super(box, self).__init__(parent)
self.raw_rect = rect
self.rect = QtCore.QRectF(rect[0], rect[1], rect[2], rect[3])
self.color = color
def boundingRect(self):
pen_adj = 0
return self.rect.normalized().adjusted(-pen_adj, -pen_adj, pen_adj, pen_adj)
def paint(self, painter, option, widget):
r = self.boundingRect()
brush = QtGui.QBrush()
brush.setColor(QtGui.QColor(self.color))
brush.setStyle(Qt.SolidPattern)
#rect = QtCore.QRect(0, 0, painter.device().width(), painter.device().height())
painter.fillRect(self.boundingRect(), brush)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(Qt.darkGray)
painter.drawRect(self.boundingRect())
#painter.drawRect(0, 0, max_time*char_spacing, self.bar_height)
def mousePressEvent(self, ev):
self.pressed.emit()
self.update()
def mouseReleaseEvent(self, ev):
self.update()
class GraphicsView(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(GraphicsView, self).__init__(parent)
scene = QtWidgets.QGraphicsScene(self)
self.setScene(scene)
self.numbers = []
self.setMouseTracking(True)
l = QGraphicsAnchorLayout()
l.setSpacing(0)
w = QGraphicsWidget()
#painter = QtGui.QPainter(self)
w.setPos(0, 0)
w.setLayout(l)
scene.addItem(w)
self.main_widget = w
self.main_layout = l
self.makeBoxs()
def makeBoxs(self):
rect = [0, 0, 600, 250]
blue_box = box(rect, QtGui.QColor(0, 0, 255, 128))
green_box = box(rect, QtGui.QColor(0, 255, 0, 128))
red_box = box([0, 0, 200, 50], QtGui.QColor(255, 0, 0, 128))
yellow_box_left = box([0, 0, 75, 600], QtGui.QColor(255, 255, 0, 128))
#self.scene().setSceneRect(blue_box.rect)
#self.scene().setSceneRect(bar_green.rect)
# Adding anchors adds the item to the layout which is part of the scene
self.main_layout.addCornerAnchors(yellow_box_left, Qt.TopLeftCorner, self.main_layout, Qt.TopLeftCorner)
self.main_layout.addCornerAnchors(blue_box, Qt.TopLeftCorner, yellow_box_left, Qt.TopRightCorner)
self.main_layout.addCornerAnchors(green_box, Qt.TopLeftCorner, blue_box, Qt.BottomRightCorner)
self.main_layout.addCornerAnchors(red_box, Qt.TopLeftCorner, green_box, Qt.BottomRightCorner)
#self.main_layout.addAnchor(bar_green, Qt.AnchorTop, blue_box, Qt.AnchorBottom)
#self.main_layout.addAnchor(bar_green, Qt.AnchorLeft, blue_box, Qt.AnchorRight)
def printStatus(self, pos):
msg = "Viewport Position: " + str(qp(pos))
v = self.mapToScene(pos)
v = QtCore.QPoint(v.x(), v.y())
msg = msg + ", Mapped to Scene: " + str(qp(v))
v = self.mapToScene(self.viewport().rect()).boundingRect()
msg = msg + ", viewport Mapped to Scene: " + str(qp(v))
v2 = self.mapToScene(QtCore.QPoint(0, 0))
msg = msg + ", (0, 0) to scene: " + qp(v2)
self.parent().statusBar().showMessage(msg)
def mouseMoveEvent(self, event):
pos = event.pos()
self.printStatus(pos)
super(GraphicsView, self).mouseMoveEvent(event)
def resizeEvent(self, event):
self.printStatus(QtGui.QCursor().pos())
h = self.mapToScene(self.viewport().rect()).boundingRect().height()
r = self.sceneRect()
r.setHeight(h)
height = self.viewport().height()
for item in self.items():
item_height = item.boundingRect().height()
super(GraphicsView, self).resizeEvent(event)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
gv = GraphicsView()
self.setCentralWidget(gv)
self.setGeometry(475, 250, 600, 480)
scene = self.scene = gv.scene()
sb = self.statusBar()
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
编辑:添加预期输出 根据锚点的定义方式,我希望输出如下所示。因为我还不能真正创建我需要的东西,所以我在 PowerPoint 中创建了这个。但是,当然,除了让它工作之外,我还希望了解如何在更一般的意义上使用锚点。
编辑 2: 再次感谢您的更新。这与我所期望的不太一样,滚动时出现了一个奇怪的神器。澄清一下,
- 我希望黄色小部件始终可见,位于视口左上角,z 顺序最高。我想你已经提供了。
- 所有其他小部件都应该滚动,保持它们的相对锚点。我将蓝色框的锚点移至黄色框,但所有框都向左对齐。
- 在您当前的实现中,非黄色框不会滚动,但是当我调整滚动条的大小或左右移动滚动条时,我看到了这个工件:
【问题讨论】:
标签: python pyqt pyqt5 qgraphicsview qgraphicsscene