【发布时间】:2020-01-21 00:10:29
【问题描述】:
我已经创建了一个小应用程序,我正在尝试制作它,以便在调整主窗口的大小(以及 GraphicsView 和场景)时,整个场景(像素图和矩形)垂直缩放以完全适合里面图形视图。我不想要垂直滚动条,也不希望它水平缩放。
我不知道如何正确缩放场景。我使用 GraphicsScene 来包含一个图形和几个垂直矩形“标记”。当我可以通过重绘像素图然后重新附加它来缩放图形以适应它时,z 顺序是错误的,并且矩形小部件不会随之缩放。
我需要跟踪矩形小部件,所以我不能一直删除和重新添加它们,因为每个小部件都有元数据。
我知道适用于包含 GraphicsView 的 fitInView(来自这里:Issue with fitInView of QGraphicsView when ItemIgnoresTransformations is on),但我不明白为什么它需要一个参数。我只希望场景适合 GraphicsView(垂直但不是水平)那么为什么 GraphicsView 不只是缩放场景中的所有内容以适应其当前大小?使场景垂直适合的参数应该是什么样的?
在 resizeEvent 中,我可以重绘像素图并重新添加,但由于 z 顺序混乱,它会覆盖矩形。此外,它不会在场景中保持垂直居中,我需要复制元数据。
import sys
import os
from PyQt5 import QtCore, QtGui, QtWidgets
import PyQt5 as qt
from PyQt5.QtGui import QColor
from PyQt5.QtCore import Qt, QPoint
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout, QGroupBox, QDialog, QVBoxLayout
from PyQt5.QtWidgets import QVBoxLayout, QGridLayout, QStackedWidget, QTabWidget
import numpy as np
class GraphicsScene(QtWidgets.QGraphicsScene):
def __init__(self, parent=None):
super(GraphicsScene, self).__init__(parent)
def minimumSizeHint(self):
return QtCore.QSize(300, 200)
def dragMoveEvent(self, event):
print("dragMoveEvent", event)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
#super(MainWindow).__init__()
layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
max_x, max_y = 2400, 700
max_x_view = 1200
self.max_x = max_x
self.max_y = max_y
self.first = True
self.setGeometry(200, 200, max_x_view, self.max_y)
self.gv = QtWidgets.QGraphicsView(self)
self.gv.setGeometry(0, 0, max_x_view, self.max_y)
self.gv2 = QtWidgets.QGraphicsView(self)
layout.addWidget(self.gv)
layout.addWidget(self.gv2)
scene = GraphicsScene()
self.scene = scene
self.gv.setScene(scene)
tab_widget = QTabWidget()
tab_widget.setTabPosition(QTabWidget.West)
widget = QWidget()
widget.setLayout(layout)
tab_widget.addTab(widget, "main")
self.setCentralWidget(tab_widget)
np.random.seed(777)
self.x_time = np.linspace(0, 12.56, 3000)
rand_data = np.random.uniform(0.0, 1.0, 3000)
self.data = .45*(np.sin(2*self.x_time) + rand_data) - .25*(np.sin(3*self.x_time))
self.first = True
pixmap_height = max_y//2 - 2*22 # 22 to take care of scrollbar height
pixmap = self.draw_graph()
pen = QtGui.QPen()
pen.setWidth(2)
pen.setColor(QtGui.QColor("red"))
self.gv1_pixmap = scene.addPixmap(pixmap)
rect = scene.sceneRect()
print("scene rect = {}".format(rect))
scene.setSceneRect(rect)
side, offset = 50, 200
for i in range(2):
r = QtCore.QRectF(QtCore.QPointF((i + 1)*offset + i * 2 * side, 2), QtCore.QSizeF(side, pixmap_height - 4))
rect_ref = scene.addRect(r, pen, QColor(255, 0, 0, 127))
rect_ref.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable)
all_items = scene.items()
print(all_items)
def draw_graph(self):
print("draw_graph: main Window size {}:".format(self.size()))
pixmap_height = self.height()//2 - 2*22 # 22 to take care of scrollbar height
x_final = self.x_time[-1]
data = self.data / np.max(np.abs(self.data))
data = [abs(int(k * pixmap_height)) for k in self.data]
x_pos = [int(self.x_time[i] * self.max_x / x_final) for i in range(len(data))]
pixmap = QtGui.QPixmap(self.max_x, pixmap_height)
painter = QtGui.QPainter(pixmap)
pen = QtGui.QPen()
pen.setWidth(2)
rect = pixmap.rect()
pen.setColor(QtGui.QColor("red"))
painter.drawRect(rect)
print("pixmap rect = {}".format(rect))
painter.fillRect(rect, QtGui.QColor('lightblue'))
pen.setWidth(2)
pen.setColor(QtGui.QColor("green"))
painter.setPen(pen)
for x, y in zip(x_pos, data):
painter.drawLine(x, pixmap_height, x, pixmap_height - y)
painter.end()
return pixmap
def resizeEvent(self, a0: QtGui.QResizeEvent):
#print("main Window resizeEvent")
print("main Window size {}:".format(a0.size()))
redraw = False
if redraw:
pixmap = self.draw_graph()
self.scene.removeItem(self.gv1_pixmap)
self.gv1_pixmap = self.scene.addPixmap(pixmap)
self.gv1_pixmap.moveBy(0, 30)
else:
#rect = QtCore.QRect(self.gv.startPos, self.gv.endPos)
#sceneRect = self.gv.mapToScene(rect).boundingRect()
#print 'Selected area: viewport coordinate:', rect,', scene coordinate:', sceneRect
#self.gv.fitInView(sceneRect)
pass
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
【问题讨论】:
-
这些矩形有特殊要求吗?我怀疑您希望这些矩形占据 QGraphicsView 视口的高度,并且不能垂直移动,只能水平移动,对吗?
-
没错。矩形需要与像素图具有相同的高度。像素图比视口短一点,因为水平滚动条使像素图无法完全拟合。
-
矩形应该能够垂直移动还是只能水平移动?
-
不,矩形只能水平移动。将它们视为图表中突出显示的部分。
标签: python pyqt pyqt5 qgraphicsview qgraphicsscene