Python 如何在Qt中在小部件上绘制形状
我试图在一个小部件上绘制一个形状,据我所知,您可以通过重写Python 如何在Qt中在小部件上绘制形状,python,qt,pyqt,pyqt5,Python,Qt,Pyqt,Pyqt5,我试图在一个小部件上绘制一个形状,据我所知,您可以通过重写paintEvent()方法来实现这一点。但是,当我这样做时,形状是在后面渲染的。如何渲染前面的形状? 我正在使用pyqt5,我的测试代码是: from PyQt5 import Qt from PyQt5.QtGui import QPainter, QPen,QBrush,QColor from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QApplication, QMain
paintEvent()
方法来实现这一点。但是,当我这样做时,形状是在后面渲染的。如何渲染前面的形状?
我正在使用pyqt5,我的测试代码是:
from PyQt5 import Qt
from PyQt5.QtGui import QPainter, QPen,QBrush,QColor
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QHBoxLayout,QPushButton
import sys
class MyWidget(QWidget):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.btn = QPushButton('Hello World')
self.layout = QHBoxLayout()
self.layout.addWidget(self.btn)
self.setLayout(self.layout)
def paintEvent(self, event):
painter = QPainter(self)
painter.setPen(QPen(Qt.green))
brush = QBrush(QColor(0,0,255,255))
painter.setBrush(brush)
painter.drawRect(0,0,50,50)
if __name__ == "__main__":
app = QApplication(sys.argv)
mainscreen = MyWidget()
mainscreen.show()
app.exec_()
Qt小部件从父级绘制到子级。 这意味着
MyWidget
在QPushButton
绘制自身之前绘制自身(通过调用paintEvent()
)
一种可能的解决方案是创建一个小部件来绘制矩形,并使其成为
QPushButton
的同级(即MyWidget
的子级)。然后,您可以通过使用QWidget::stackUnder()
,QWidget::raise()
或QWidget::lower()
,QWidget::lower()将Qt小部件从父对象绘制到子对象,来决定QPushButton
和RectangleWidget
的呈现顺序。
这意味着MyWidget
在QPushButton
绘制自身之前绘制自身(通过调用paintEvent()
)
一种可能的解决方案是创建一个小部件来绘制矩形,并使其成为QPushButton
的同级(即MyWidget
的子级)。然后,您可以通过使用QWidget::stackUnder()
,QWidget::raise()
或QWidget::lower()
,QWidget::lower()
这本质上是一个常见问题的Python版本:如何在小部件上覆盖内容。我有一系列相关的答案:
第三个答案,用Python重铸:
# https://github.com/KubaO/stackoverflown/tree/master/questions/python-overlay-49920532
from PyQt5 import Qt
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
class Overlay(QWidget):
def __init__(self, parent = None):
QWidget.__init__(self, parent)
self.setAttribute(Qt.WA_NoSystemBackground)
self.setAttribute(Qt.WA_TransparentForMouseEvents)
def paintEvent(self, event) {
QPainter(self).fillrect(self.rect(), QColor(80, 80, 255, 128))
class Filter(QObject):
def __init__(self, parent = None):
QObject.__init__(self, parent)
self.m_overlay = None
self.m_overlayOn = None
def eventFilter(self, w, event):
if w.isWidgetType():
if event.type() == QEvent.MouseButtonPress:
if not m_overlay:
m_overlay = Overlay(w.parentWidget());
m_overlay.setGeometry(w.geometry());
m_overlayOn = w;
m_overlay.show();
elif event.type() == QEvent.Resize:
if m_overlay and m_overlayOn is w:
m_overlay.setGeometry(w.geometry());
return False
if __name__ == "__main__":
app = QApplication(sys.argv)
filter = Filter()
window = QWidget()
layout = QHBoxLayout(window);
for text in ["Foo", "Bar", "Baz"]:
label = QLabel(text)
label.installEventFilter(filter)
layout.addWidget(label)
window.setMinimumSize(300, 250)
window.show()
app.exec_()
这本质上是一个常见问题的Python版本:如何在小部件上覆盖内容。我有一系列相关的答案:
第三个答案,用Python重铸:
# https://github.com/KubaO/stackoverflown/tree/master/questions/python-overlay-49920532
from PyQt5 import Qt
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
class Overlay(QWidget):
def __init__(self, parent = None):
QWidget.__init__(self, parent)
self.setAttribute(Qt.WA_NoSystemBackground)
self.setAttribute(Qt.WA_TransparentForMouseEvents)
def paintEvent(self, event) {
QPainter(self).fillrect(self.rect(), QColor(80, 80, 255, 128))
class Filter(QObject):
def __init__(self, parent = None):
QObject.__init__(self, parent)
self.m_overlay = None
self.m_overlayOn = None
def eventFilter(self, w, event):
if w.isWidgetType():
if event.type() == QEvent.MouseButtonPress:
if not m_overlay:
m_overlay = Overlay(w.parentWidget());
m_overlay.setGeometry(w.geometry());
m_overlayOn = w;
m_overlay.show();
elif event.type() == QEvent.Resize:
if m_overlay and m_overlayOn is w:
m_overlay.setGeometry(w.geometry());
return False
if __name__ == "__main__":
app = QApplication(sys.argv)
filter = Filter()
window = QWidget()
layout = QHBoxLayout(window);
for text in ["Foo", "Bar", "Baz"]:
label = QLabel(text)
label.installEventFilter(filter)
layout.addWidget(label)
window.setMinimumSize(300, 250)
window.show()
app.exec_()
对不起,“在前面”是什么意思?你能添加一张显示所需结果的模型图片吗?@S.monteleon谢谢你的回复,我已经上传了一张样本图片谢谢,现在一切都清楚了。您希望在所有小部件的顶部绘制红方块。那么@BenjaminT的答案是正确的,很抱歉,你说的“在前面”是什么意思?你能添加一张显示所需结果的模型图片吗?@S.monteleon谢谢你的回复,我已经上传了一张样本图片谢谢,现在一切都清楚了。您希望在所有小部件的顶部绘制红方块。那么@BenjaminT的答案是正确的,可能是重复的谢谢,我尝试了两种解决方案,它们都对我有效。@恢复Monica此答案中提到的python解决方案非常有缺陷。@Raj我不太知道这样简单的代码怎么会有“缺陷”-要么有效,要么无效。如果您有任何特殊的问题,请分享一个指向复制机的主要链接,我来看看。考虑到这是C++代码的直接翻译,我希望两者都是“Bug”。谢谢,我尝试了这两种解决方案,它们都为我工作。“恢复莫尼卡,Python解决方案中提到的答案非常多。”我不知道这些简单的代码是如何“Bugy”的——它可以工作,也不会。如果您有任何特殊的问题,请分享一个指向复制机的主要链接,我来看看。考虑到它是C++代码的直接翻译,那么我希望两者都是“Bug”。你能举个例子吗?QWidget::lower()
似乎不起作用(或者更可能是我把继承人制度搞砸了)。你能举个例子吗。QWidget::lower()
似乎不起作用(或者更可能是我把继承人的档案搞砸了)。