Windows 11 专业版 PyQt6(最新) Python 3.13.1
我希望这是一件容易的事。我有以下代码:
import sys
from PyQt6.QtCore import QSize, Qt
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget
# Subclass QMainWindow to customize your application's main window
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("My App")
layout = QVBoxLayout()
button1 = QPushButton("Press Me!")
button1.setFixedSize(QSize(200, 60))
button2 = QPushButton("Press Me!")
button2.setFixedSize(QSize(200, 60))
button3 = QPushButton("Press Me!")
button3.setFixedSize(QSize(200, 60))
layout.addWidget(button1)
layout.addWidget(button2)
layout.addWidget(button3)
widget = QWidget()
widget.setLayout(layout)
#self.setFixedSize(QSize(100, 100))
# Set the central widget of the Window.
self.setCentralWidget(widget)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
它运行并产生以下结果:
我想做这个:
我找到下面的代码,它生成了一行。但我不知道如何将该代码与上面的代码合并。这只是一个例子。如果我能弄清楚如何让它在小部件上绘制线条,我可以从那里获取它。到目前为止我有两个要求。 如果可能的话,我需要集成代码能够绘制可以跨越多个小部件的线条。此外,将来我希望能够有一个事件触发器(例如按钮按下)来调用一个函数,该函数会在我的主窗口中的多个小部件上画一条线。
import sys
from PyQt6 import QtCore, QtGui, QtWidgets, uic
from PyQt6.QtCore import Qt
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.label = QtWidgets.QLabel()
canvas = QtGui.QPixmap(400, 300)
canvas.fill(Qt.GlobalColor.white)
self.label.setPixmap(canvas)
self.setCentralWidget(self.label)
self.draw_something()
def draw_something(self):
canvas = self.label.pixmap()
painter = QtGui.QPainter(canvas)
painter.drawLine(10, 10, 300, 200)
painter.end()
self.label.setPixmap(canvas)
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
您不能直接在 over 小部件上绘制,因为渲染遵循堆叠顺序,从下到上:绘制父级,然后在其上方绘制其子级。
解决方案是将一个小部件覆盖在其他小部件之上。 处理布局时会出现问题,因为小部件的几何形状可能会在运行时发生变化(并且在构建小部件时您几乎永远不能依赖初始几何形状)。
只要“栏”必须显示在整个父级上方,那么您就可以使用 QGridLayout,它允许将小部件添加到多个“单元格”,即使它们已经被其他单元格占用。
class BarWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents)
def paintEvent(self, event):
qp = QPainter(self)
qp.setRenderHint(qp.RenderHint.Antialiasing)
qp.setPen(QPen(Qt.GlobalColor.black, 4))
rect = self.rect().adjusted(10, 10, -10, -10)
qp.drawLine(rect.topLeft(), rect.bottomRight())
class MainWindow(QMainWindow):
def __init__(self):
...
barWidget = BarWidget()
layout.addWidget(
barWidget,
0, 0, layout.rowCount(), layout.columnCount()
)
请注意,创建顺序对于堆叠很重要:如果您将该栏小部件添加到其他小部件之前,它将显示在它们下方;在这种情况下,您可以通过调用
barWidget.raise_()
强制堆叠。 对于可能跨越多个容器或布局的更复杂的情况,唯一的解决方案是在其父窗口(也可能是主窗口)的
resizeEvent()
内手动设置小部件的几何形状:
class MainWindow(QMainWindow):
def __init__(self):
...
self.barWidget = BarWidget(self)
self.barred = button2, button3
def resizeEvent(self, event):
super().resizeEvent(event)
# this is necessary because we're managing the resize event of the
# parent and at this moment the child layout may still not be
# activated yet
self.centralWidget().layout().activate()
self.barWidget.raise_()
rect = QRect()
for widget in self.barred:
geo = widget.rect().translated(widget.mapTo(self, QPoint()))
rect |= geo
self.barWidget.setGeometry(rect)