Qt绘制带边框的填充圆角矩形
Qt drawing a filled rounded rectangle with border
我想绘制一个圆角矩形(所有 4 个角的边框半径相同),用特定颜色填充整个矩形,并使用单独的边框颜色(比如边框宽 1 像素)。
根据我的观察,Qt 提供了三种方法——fillRect
、drawRect
和drawRoundedRect
。我已经试过了,它们不能像我想要的那样工作。没有fillRoundedRect
这样的方法。这意味着我可以绘制一个圆角矩形,但它不会填充我想要的颜色。
我该怎么做?而且,我读到由于一些混叠问题,角落经常呈现为不平等。我如何将它设置为所有四个都相等? painter.setRenderHint(QPainter::Antialiasing)
够吗?或者我还需要做其他事情吗?
您可以创建一个 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 像素的边框也可能永远不会很好看,尤其是在低 DPI 桌面显示器上,在高 DPI 移动设备上几乎看不见。
如果将矩形创建为 QRectF(9.5, 9.5, 100, 50)
,使用 1 px 抗锯齿边框看起来会更好,因为它会 "snap" 在右边的像素上:
上面的答案(来自@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())
我想绘制一个圆角矩形(所有 4 个角的边框半径相同),用特定颜色填充整个矩形,并使用单独的边框颜色(比如边框宽 1 像素)。
根据我的观察,Qt 提供了三种方法——fillRect
、drawRect
和drawRoundedRect
。我已经试过了,它们不能像我想要的那样工作。没有fillRoundedRect
这样的方法。这意味着我可以绘制一个圆角矩形,但它不会填充我想要的颜色。
我该怎么做?而且,我读到由于一些混叠问题,角落经常呈现为不平等。我如何将它设置为所有四个都相等? painter.setRenderHint(QPainter::Antialiasing)
够吗?或者我还需要做其他事情吗?
您可以创建一个 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 像素的边框也可能永远不会很好看,尤其是在低 DPI 桌面显示器上,在高 DPI 移动设备上几乎看不见。
如果将矩形创建为 QRectF(9.5, 9.5, 100, 50)
,使用 1 px 抗锯齿边框看起来会更好,因为它会 "snap" 在右边的像素上:
上面的答案(来自@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())