我想画一个圆角的矩形(所有4个角的边框半径相同),特定的颜色填充整个矩形,还有一个单独的边框颜色(比如边框宽1 px)。
根据我的观察,Qt提供了三种方法 - fillRect
和drawRect
以及drawRoundedRect
。我试过了,他们不像我想的那样工作。没有类似fillRoundedRect
的方法。这意味着我可以绘制一个圆角矩形,但它不会填充我想要的颜色。
我该怎么办?而且,我读到由于一些混叠问题,角落经常被渲染为不相等。如何将它设置为全部四个相等? painter.setRenderHint(QPainter::Antialiasing)
会满足吗?或者我还需要做其他事情吗?
答案 0 :(得分:46)
您可以创建QPainterPath
,为其添加圆角矩形,然后填充并描边:
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
QPainterPath path;
path.addRoundedRect(QRectF(10, 10, 100, 50), 10, 10);
QPen pen(Qt::black, 10);
p.setPen(pen);
p.fillPath(path, Qt::red);
p.drawPath(path);
请注意,即使使用抗锯齿功能,1 px边框也可能永远不会看起来很好,特别是在低DPI桌面显示器上,在高DPI移动设备上,它几乎不可见。
如果您将矩形创建为QRectF(9.5, 9.5, 100, 50)
,使用1 px抗锯齿边框会更好看,因为它会" snap"在右边的像素上:
答案 1 :(得分:1)
上面的答案(来自@dtech)效果很好,但有时最终会在 roundedRect 周围出现不均匀的边框。使用 QPainter.strokePath()
而不是 QPainter.drawPath()
可以解决此问题。
这是QPushButton
的python实现,重新实现了paintEvent
:
# I use PySide6, but whatever library should work.
from PySide6.QtWidgets import QPushButton
from PySide6.QtGui import QPainter, QPainterPath, QBrush, QPen
from PySide6.QtCore import Qt, QRectF
class RoundedButton(QPushButton):
def __init__(self, text, bordersize, outlineColor, fillColor):
super(RoundedButton, self).__init__()
self.bordersize = bordersize
self.outlineColor = outlineColor
self.fillColor = fillColor
self.setText(text)
def paintEvent(self, event):
# Create the painter
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
# Create the path
path = QPainterPath()
# Set painter colors to given values.
pen = QPen(self.outlineColor, self.bordersize)
painter.setPen(pen)
brush = QBrush(self.fillColor)
painter.setBrush(brush)
rect = QRectF(event.rect())
# Slighly shrink dimensions to account for bordersize.
rect.adjust(self.bordersize/2, self.bordersize/2, -self.bordersize/2, -self.bordersize/2)
# Add the rect to path.
path.addRoundedRect(rect, 10, 10)
painter.setClipPath(path)
# Fill shape, draw the border and center the text.
painter.fillPath(path, painter.brush())
painter.strokePath(path, painter.pen())
painter.drawText(rect, Qt.AlignCenter, self.text())