Qt круглый прямоугольник, почему углы разные? - PullRequest
6 голосов
/ 28 июня 2011

Я пытаюсь нарисовать круглый прямоугольник с помощью метода drawRoundedRect непосредственно в QPixmap (здесь не задействован механизм рендеринга, кроме чистого Qt one ...), я дважды проверяю размер прямоугольника по сравнению с размером моего растрового изображения:

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

Я напрямую вывожу растровое изображение в файл, чтобы убедиться, что я не очищал его во время отображения ... такой же формы.

Кто-нибудь знает про Qt круглый прямоугольник с небольшим радиусом?Я видел что-то об этом давным-давно, но я не помню, как с этим бороться!

Ответы [ 6 ]

14 голосов
/ 28 июня 2011

Похоже, вы не используете сглаживание (то есть подсказка QPainter::Antialiasing).Это причуды Qt, которые происходят без него.Из того, что я видел / слышал, разработчики Qt не очень заботятся об исправлении этого (большинство людей все равно хотят сглаживать).

Обходной путь (помимо простого использования сглаживания) заключается вНарисуйте прямоугольник с помощью QPainter::drawLine() и QPainter::drawArc().Возможно, вам придется поиграть с числами, пока они не будут выглядеть правильно - прямые вычисления имеют тенденцию выходить из положения на один или два пикселя.Кроме того, вы можете обнаружить, что даже при использовании этого метода нижний правый угол никогда не будет точно таким же, как другие углы.

Если вы чувствуете себя немного честолюбивым, вы можете попробовать исправить это иотправка патча в Qt.

Обновление: Изменены результаты рисования дуг в Qt 5. По моему опыту, это большое улучшение.

3 голосов
/ 08 августа 2013

Попробуйте добавить половину смещения пикселя (например: 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 голосов
/ 22 сентября 2014

Я знаю, что это старая проблема, но для 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

1 голос
/ 26 сентября 2014

Лучший способ рисовать 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);     
}
0 голосов
/ 03 декабря 2014

Я перепробовал все подсказки из ответов здесь, но у меня ничего не работает.Но, основываясь на этих фрагментах кода, я нашел следующее решение:

По умолчанию установлено 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);
0 голосов
/ 28 июня 2011

попробуйте поиграть с подсказками рендера 1) отключить антиалиасинг;2) включить SmoothPixmapTransform

, но по-прежнему нет гарантии, что это поможет.

...