我正在试图覆盖paintEvent() of QMenu,使其具有圆角。
上下文菜单应该如下所示。

下面是我尝试过的代码,但是什么也没有出现:
from PyQt5 import QtWidgets, QtGui, QtCore
import sys
class Example(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 300, 200)
self.setWindowTitle('Context menu')
self.show()
def contextMenuEvent(self, event):
cmenu = AddContextMenu(self)
newAct = cmenu.addAction("New")
openAct = cmenu.addAction("Open")
quitAct = cmenu.addAction("Quit")
action = cmenu.exec_(self.mapToGlobal(event.pos()))
class AddContextMenu(QtWidgets.QMenu):
def __init__(self, *args, **kwargs):
super(AddContextMenu, self).__init__()
self.painter = QtGui.QPainter(self)
self.setMinimumSize(150, 200)
self.pen = QtGui.QPen(QtCore.Qt.red)
#self.setStyleSheet('color:white; background:gray; border-radius:4px; border:2px solid white;')
def paintEvent(self, event) -> None:
self.pen.setWidth(2)
self.painter.setPen(self.pen)
self.painter.setBrush(QtGui.QBrush(QtCore.Qt.blue))
self.painter.drawRoundedRect(10, 10, 100, 100, 4.0, 4.0)
self.update()
#self.repaint()
#super(AddContextMenu, self).paintEvent(event)
def main():
app = QtWidgets.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()注意:设置样式表对我不起作用:
这就是我在使用样式表时得到的结果,它不是完全四舍五入的。

这是@musicamante建议后的paintEvent (这是给他/她检查的)
def paintEvent(self, event) -> None:
painter = QtGui.QPainter(self)
#self.pen.setColor(QtCore.Qt.white)
#painter.setFont(QtGui.QFont("times", 22))
#painter.setPen(self.pen)
#painter.drawText(QtCore.QPointF(0, 0), 'Hello')
self.pen.setColor(QtCore.Qt.red)
painter.setPen(self.pen)
painter.setBrush(QtCore.Qt.gray)
painter.drawRoundedRect(self.rect(), 20.0, 20.0)和init()
self.pen = QtGui.QPen(QtCore.Qt.red)
self.pen.setWidth(2)发布于 2021-01-05 11:40:36
仅在样式表中为顶级小部件(具有自己的“窗口”的小部件)设置边框半径是不够的。
虽然克里斯蒂安·卡切尔( Christian Karcher )提议的solution很好,但需要考虑两个重要问题:
WA_TranslucentBackground属性将无法工作。在Linux上设置FramelessWindowHint FramelessWindowHint不应该,因为它可能会导致窗口管理器的问题,所以只有在确保操作系统需要它之后才能设置它。g 210
有鉴于此,当不支持组合时,使用setMask()是正确的修复,这必须发生在resizeEvent()中。请注意,掩蔽是基于位图的,并且不支持反混叠,因此圆形边框有时会因边框半径的不同而有点难看。
另外,由于您希望使用自定义颜色,所以必须使用样式表,因为QMenu的自定义绘图实际上是很难实现的。
class AddContextMenu(QtWidgets.QMenu):
def __init__(self, *args, **kwargs):
super(AddContextMenu, self).__init__()
self.setMinimumSize(150, 200)
self.radius = 4
self.setStyleSheet('''
QMenu {{
background: blue;
border: 2px solid red;
border-radius: {radius}px;
}}
QMenu::item {{
color: white;
}}
QMenu::item:selected {{
color: red;
}}
'''.format(radius=self.radius))
def resizeEvent(self, event):
path = QtGui.QPainterPath()
# the rectangle must be translated and adjusted by 1 pixel in order to
# correctly map the rounded shape
rect = QtCore.QRectF(self.rect()).adjusted(.5, .5, -1.5, -1.5)
path.addRoundedRect(rect, self.radius, self.radius)
# QRegion is bitmap based, so the returned QPolygonF (which uses float
# values must be transformed to an integer based QPolygon
region = QtGui.QRegion(path.toFillPolygon(QtGui.QTransform()).toPolygon())
self.setMask(region)一些方面提到了您的paintEvent实现,由于上述原因,在这种特殊情况下没有必要,但仍然很重要(有些要点与已注释的部分代码有关,但您尝试它们的事实使这些方面值得一提):
用于小部件的
paintEvent()之外实例化:像在__init__中创建实例一样,这是一个严重的错误,甚至可能导致崩溃。只有在接收到paintEvent时才能创建画家,而且绝不能重复使用。这显然使设置它为一个实例属性(self.painter)毫无用处,因为没有实际的理由在画图事件之后访问它。如果画笔宽度总是相同的,那么只需在构造函数(self.pen = QtGui.QPen(QtCore.Qt.red, 2))中设置它,在paintEvent中连续设置它是self.painter,QBrush可以直接接受Qt全局颜色,因此,不需要创建一个self.painter.setBrush(QtCore.Qt.blue).self.update()实例,因为画家将自动(内部和快速地)设置它:如果永远不会在paintEvent中调用(甚至self.repaint()也不应该)。在未定义(也可能是dangerous.发布于 2021-01-05 09:21:25
我不能评论paintEvent的功能,但是可以使用样式表实现圆角。为了禁用背景中的默认矩形,必须修改一些q菜单属性,这会给出不想要的结果。
下面是使用样式表+自定义标志(没有框架+透明背景)的示例的修改版本:

from PyQt5 import QtWidgets, QtCore
import sys
class Example(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 300, 200)
self.setWindowTitle('Context menu')
self.show()
def contextMenuEvent(self, event):
cmenu = QtWidgets.QMenu()
# disable default frame and background
cmenu.setWindowFlags(QtCore.Qt.FramelessWindowHint)
cmenu.setAttribute(QtCore.Qt.WA_TranslucentBackground)
# set stylesheet, add some padding to avoid overlap of selection with rounded corner
cmenu.setStyleSheet("""
QMenu{
background-color: rgb(255, 255, 255);
border-radius: 20px;
}
QMenu::item {
background-color: transparent;
padding:3px 20px;
margin:5px 10px;
}
QMenu::item:selected { background-color: gray; }
""")
newAct = cmenu.addAction("New")
openAct = cmenu.addAction("Open")
quitAct = cmenu.addAction("Quit")
action = cmenu.exec_(self.mapToGlobal(event.pos()))
def main():
app = QtWidgets.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()https://stackoverflow.com/questions/65574567
复制相似问题