Qt绘制带边框的填充圆角矩形

时间:2015-03-22 16:05:47

标签: c++ qt rectangles rounded-corners qpainter

我想画一个圆角的矩形(所有4个角的边框半径相同),特定的颜色填充整个矩形,还有一个单独的边框颜色(比如边框宽1 px)。

根据我的观察,Qt提供了三种方法 - fillRectdrawRect以及drawRoundedRect。我试过了,他们不像我想的那样工作。没有类似fillRoundedRect的方法。这意味着我可以绘制一个圆角矩形,但它不会填充我想要的颜色。

我该怎么办?而且,我读到由于一些混叠问题,角落经常被渲染为不相等。如何将它设置为全部四个相等? painter.setRenderHint(QPainter::Antialiasing)会满足吗?或者我还需要做其他事情吗?

2 个答案:

答案 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移动设备上,它几乎不可见。

enter image description here

如果您将矩形创建为QRectF(9.5, 9.5, 100, 50),使用1 px抗锯齿边框会更好看,因为它会" snap"在右边的像素上:

enter image description here

答案 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())