Qt圆角矩形,为什么角落不同?

时间:2011-06-28 13:51:04

标签: c++ qt qt4 rasterizing

我尝试直接在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)......
  • 我改变笔宽,刷颜色......

但它始终以4个不同角落的直线结束!像那样:

Radius = 3.0 in x and y

我将pixmap直接输出到一个文件,以确保我在显示过程中没有刮掉它...相同的形状。

任何人都知道Qt小圆角矩形吗?很久以前我看到了它的一些东西,但我不记得如何处理它!

6 个答案:

答案 0 :(得分:14)

看起来你没有使用抗锯齿(即QPainter::Antialiasing渲染提示)。这是一个没有它的Qt怪癖。从我所看到/听到的情况来看,Qt开发人员并不十分关心修复这个问题(大多数人都想要抗锯齿)。

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

如果你感觉有点雄心勃勃,你可以尝试解决这个问题并向Qt提交补丁。

更新:在Qt 5中,圆弧绘制结果发生了变化。根据我的经验,这是一个很大的进步。

答案 1 :(得分: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 :(得分:2)

我知道这是一个老问题,但Qt5用户setRenderHint(QPainter::Qt4CompatiblePainting);上的QPainter似乎可以解决问题。

修改

我找到了一个解决方案,用于生成一个完美的圆角矩形和边框颜色,它看起来与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 :(得分:1)

最好的方法是绘制RoundRect是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);     
}

答案 4 :(得分:0)

尝试使用渲染提示 1)禁用antiAliasing; 2)启用SmoothPixmapTransform

但仍无法保证会有所帮助。

答案 5 :(得分:0)

我已经尝试了答案的所有提示,但对我没什么用。但基于这些代码片段,我找到了以下解决方案:

默认设置为m_pPainter->setRenderHint(QPainter::Qt4CompatiblePainting, true),仅适用于宽度为%2 == 0的圆角矩形,请将其禁用。

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);