我在 Qt Designer 中构建了一个 PyQt 窗口,我正在编写一个自定义绘制方法。主窗口创建一个标签并将其设置为中央小部件。然后我重写paint方法来绘制一个简单的柱形图。
在调整大小之前,该小部件运行良好。小部件调用 resize 方法并按预期重新绘制,但它使用与调整大小之前相同大小的矩形。有一个很大的黑色区域——调整大小的部分——没有被涂上。
为了测试这一点,我抓住了小部件的矩形并绘制了一个带有浅蓝色填充和外部红线的大矩形。当窗口调整大小时,外部矩形的一部分也丢失了。
调试语句显示新矩形的大小正确,并且宽度和高度值已正确输入到绘制事件中。
但是当我调整大小时,这就是我所看到的。为什么油漆不在黑色区域上漆?我检查了我的代码,油漆没有硬编码限制。是否发生了一些隐藏的剪辑?
我找不到任何关于这个问题的问题,所以我似乎遗漏了一些东西。这个类似的问题说在重绘之前使窗口无效,但这是针对 C++ 的: Graphics.DrawImage 并不总是绘制整个位图?
我是否需要以某种方式使小部件无效?我找不到 PyQt 方法来做到这一点。
import sys
from PyQt5 import QtCore, QtGui, QtWidgets, uic
import PyQt5 as qt
import numpy as np
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.label = QtWidgets.QLabel()
self.max_x = 600
self.max_y = 400
canvas = QtGui.QPixmap(self.max_x, self.max_y)
self.label.setPixmap(canvas)
self.setCentralWidget(self.label)
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 = np.sin(self.x_time) + rand_data
pal = self.palette()
pal.setColor(self.backgroundRole(), QtGui.QColor('black'))
self.setPalette(pal)
self.setAutoFillBackground(True)
def resizeEvent(self, a0: QtGui.QResizeEvent):
print("resizeEvent")
max_x = self.size().width()
max_y = self.size().height()
self.draw(max_x, max_y)
def mousePressEvent(self, a0: QtGui.QMouseEvent):
print("mousePressEvent")
def paintEvent(self, a0: QtGui.QPaintEvent):
print("New window size = ", self.size())
print("canvas size = ", self.label.size())
max_x = self.label.size().width()
max_y = self.label.size().height()
self.draw(max_x, max_y)
def draw(self, max_x, max_y):
x_final = self.x_time[-1]
data = self.data/np.max(np.abs(self.data))
data = [abs(int(k*max_y)) for k in self.data]
x_pos_all = [int(self.x_time[i]*max_x / x_final) for i in range(len(data))]
# Find and use only the max y value for each x pixel location
y_pos = []
x_pos = list(range(max_x))
cnt = 0
for x_pixel in range(max_x):
mx = 0.0
v = x_pos_all[cnt]
while cnt < len(x_pos_all) and x_pos_all[cnt] == x_pixel:
if data[cnt] > mx:
mx = data[cnt]
cnt += 1
y_pos.append(mx)
print("data = ")
dat = np.array(data)
print(dat[dat > 0].shape[0])
painter = QtGui.QPainter(self.label.pixmap()) # takes care of painter.begin(self)
pen = QtGui.QPen()
rect = self.label.rect()
print("rect = {}".format(rect))
painter.fillRect(rect, QtGui.QColor('lightblue'))
pen.setWidth(2)
pen.setColor(QtGui.QColor('green'))
for i in range(len(x_pos)):
painter.setPen(pen)
painter.drawLine(x_pos[i], max_y, x_pos[i], max_y - y_pos[i])
pen.setWidth(5)
pen.setColor(QtGui.QColor('red'))
painter.setPen(pen)
painter.drawRect(rect)
painter.end()
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
我希望随着小部件的大小调整,paint 事件将在小部件的整个新大小上重新绘制,而不仅仅是原始大小。奇怪的是,图形部分(绿线)在我调整大小时看起来像是在缩放,但一切都只是在原始小部件大小处被截断。
我该如何解决?
