Qt圆角矩形,为什么四个角不一样?

7

我尝试使用drawRoundedRect方法直接在QPixmap中绘制一个圆角矩形(这里没有涉及任何渲染引擎,只有纯Qt ...),我仔细检查了矩形的大小与我的像素图的大小:

Pixmap : QSize(50, 73) 
Rectangle: QRect(0,0 48x11) 

看到了很多空间...

编辑:一些代码

pixmap = QPixmap(50,73); //example size that match my case
QRectF rect(0,0,48,11);

QPainter painter(&pixmap);
painter.setRenderHint(QPainter::TextAntialiasing);
painter.setWorldMatrixEnabled(false);
painter.setPen(QPen()); //no pen
painter.setBrush(QBrush(color));
painter.drawRoundedRect(rect, 2.0, 2.0);
  • 我禁用了世界变换...
  • 我将转换设置为统一...
  • 我尝试了几个半径 (1.0、2.0、3.0、4.0)...
  • 我改变了笔宽、画刷颜色...

但它总是以一个有四个不同角落的矩形结束!就像这样:

X和Y方向上的半径=3.0

我直接将像素图输出到文件中,以确保在显示过程中没有对其进行修改...但形状仍然相同。

有人知道如何使用Qt创建小半径的圆角矩形吗?我很久以前看到过一些关于它的东西,但我不记得该如何处理它了!

6个回答

15

看起来你没有使用抗锯齿(即QPainter::Antialiasing渲染提示)。这是Qt的一个小问题。从我所见/所闻,Qt开发者并不是特别关心修复这个问题(大多数人都希望启用抗锯齿)。

解决方法(除了使用抗锯齿之外)是使用QPainter::drawLine()QPainter::drawArc()自己绘制矩形。您可能要调整数字,直到它看起来正确--直接计算往往会相差一两个像素。此外,您可能会发现,即使使用此方法,右下角永远不会与其他角落完全相同。

如果您有些雄心壮志,可以尝试修复此问题并向Qt提交补丁。

更新: Qt 5中弧线绘制的结果已经改变。根据我的经验,这是一个很大的改进。


2
我尝试了抗锯齿和其他绘图方式(如绘制路径、弧线等)。即使是在这些小的细节上使用抗锯齿也是值得的!而我的最佳尝试是在每个地方加上 ~0.5,猜测四舍五入可能会产生奇怪的行为...所以我将接受“玩数字”的方法! - Thomas Vincent
3
我也遇到了同样的问题。使用 QPainter p(this); p.setRenderHint(QPainter::Antialiasing); p.setRenderHint(QPainter::HighQualityAntialiasing); 为我解决了这个问题。 - S B

5
我知道这是一个老问题,但对于Qt5用户,在QPainter上调用setRenderHint(QPainter::Qt4CompatiblePainting);似乎可以解决这个问题。 编辑: 我找到了一个解决方案,可以生成一个完美的带边框颜色的圆角矩形,并且它看起来与QPushButton的边框使用的圆角矩形相同。这是我实现paintEvent的方式:
void MyButtonGroup::paintEvent(QPaintEvent * e)
{
    int borderSize = 5;
    QColor borderColor = Qt::red;
    QColor backgroundColor = Qt::blue;
    int borderRadius = 3;

    QPen pen;
    pen.setWidth(borderSize);
    pen.setColor(borderColor);

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(pen);

    QRectF rect(rect().x() + borderSize / 2,
                rect().y() + borderSize / 2,
                rect().width() - borderSize,
                rect().height() - borderSize);


    if(borderSize % 2 == 0)
    {
        painter.drawRoundedRect(rect,
                                borderSize,
                                borderSize);
    }
    else
    {
        painter.drawRoundedRect(rect.translated(0.5, 0.5),
                                borderRadius,
                                borderRadius);
    }

    QBrush brush(backgroundColor);
    pen.setBrush(brush);
    painter.setBrush(brush);

    if(borderSize % 2 == 0)
    {
        painter.drawRoundedRect(rect,
                                borderRadius,
                                borderRadius);
    }
    else
    {
        painter.drawRoundedRect(rect.translated(0.5, 0.5),
                                borderRadius,
                                borderRadius);
    }

    QWidget::paintEvent(e);
}

我发布这篇文章是因为我发现实现这个结果有点困难: enter image description here

3
尝试添加半像素的偏移量(例如:rect.translated(0.5,0.5)):
QRectF rect(0,0,48,11);
painter.setRenderHint(QPainter::Antialiasing,false);
painter.drawRoundedRect( rect.translated(0.5,0.5), 2.0, 2.0 );

我想这与坐标系统将整数值放置在两个像素之间有关。

如果您使用抗锯齿绘制并使用1像素宽的笔,则在精确整数坐标处绘制会导致2像素宽的线条。 只有通过这个0.5像素的偏移,您才能获得精确为1像素宽的线条。

QRectF rect(0,0,48,11);
painter.setRenderHint(QPainter::Antialiasing,true);
painter.setBrush(Qt::NoBrush);
painter.setPen( Qt::white );
painter.drawRoundedRect( rect.translated(0.5,0.5), 2.0,2.0 );

2

绘制圆角矩形的最佳方式是使用路径(Path)。 http://developer.nokia.com/community/wiki/Qt_rounded_rect_widget

void fillRoundRect(QPainter& painter, QRect r, int radius)
{
    painter.setRenderHint(QPainter::Antialiasing,true);

    QPainterPath rounded_rect;
    rounded_rect.addRoundRect(r, radius, radius);
    painter.setClipPath(rounded_rect);

    painter.fillPath(rounded_rect,painter.brush());     
    painter.drawPath(rounded_rect);     
}

0

我尝试了这里所有答案的提示,但对我来说都没有用。但是根据这些代码片段,我找到了以下解决方案:

默认设置m_pPainter->setRenderHint(QPainter::Qt4CompatiblePainting, true),仅对宽度为偶数的圆角矩形禁用它。

QRect rect = ConvertRectangle(rectangle);

int nPenWidth = m_pPainter->pen().width();
if ( nPenWidth % 2 == 0 )
    m_pPainter->setRenderHint(QPainter::Qt4CompatiblePainting, false);

m_pPainter->drawRoundedRect(rect, dbRadiusX, dbRadiusY);

if ( nPenWidth % 2 == 0 )
    m_pPainter->setRenderHint(QPainter::Qt4CompatiblePainting, true);

0
尝试使用渲染提示进行操作: 1)禁用抗锯齿; 2)启用SmoothPixmapTransform。
但仍不能保证它会有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接