DrawArc рисуются неправильно (qt/c++)

Я новичок в QT и не могу понять, почему мои дуги так плохо рисуются. У меня 2 проблемы.

Первый, который я считаю нормальным для такого рисования: если я рисую с помощью QPainterPath, прямая линия будет нарисована на каждой дуге от конца дуги до направления точки 0,0, но не полностью до 0 ,0 вместо этого это просто, я думаю, половина пути к этому моменту...

Второй: если я использую QPainterPath или painter.drawArc, «кольца» не являются симметричными, если я изменяю ширину пера.

У меня есть этот код, который инициирует мою дугу.

//Редактировать// Извините, забыл указать, где создаются w и h. this->getMainWidget() возвращает только QWidget, в котором нарисованы мои элементы. геометрия и положение виджета верхнего уровня и виджета из this->getMainWidget() одинаковы.

QRect mainWidgetGeo = geometry();
int w = mainWidgetGeo.width();
int h = mainWidgetGeo.height();

QPen secondPen(Qt::yellow);
secondPen.setWidth(50);

circleSeconds = new Circle(this->getMainWidget());
circleSeconds->setMaxValue(60);
circleSeconds->setValue(55);
circleSeconds->setSteps(60);
circleSeconds->setMouseTracking(true);
circleSeconds->setPen(secondPen);
circleSeconds->setGeometry(QRect(0, 0, w, h));

QPen minutePen(Qt::red);
minutePen.setWidth(100);

circleMinutes = new Circle(this->getMainWidget());
circleMinutes->setMaxValue(60);
circleMinutes->setValue(50);
circleMinutes->setSteps(60);
circleMinutes->setMouseTracking(true);
circleMinutes->setPen(minutePen);
circleMinutes->setGeometry(QRect(50, 50, w-100, h-100));

QPen hourPen(Qt::green);
hourPen.setWidth(50);

circleHours = new Circle(this->getMainWidget());
circleHours->setMaxValue(12);
circleHours->setValue(45);
circleHours->setSteps(12);
circleHours->setMouseTracking(true);
circleHours->setPen(hourPen);
circleHours->setGeometry(QRect(150, 150, w-300, h-300));

Это установит 3 дуги. У первого и третьего одинаковая ширина пера 50, у второго 100.

Для завершения вот класс Circle:

#include <QtGui>
#include "Circle.h"
#include <QDebug>

Circle::Circle(QWidget *parent): QWidget(parent)
{
}

void Circle::setSteps(int i)
{
    this->steps = i;
}

void Circle::setValue(int i)
{
    this->value = i;
    repaint();
}

void Circle::setMaxValue(int i)
{
    this->maxValue = i;
}

void Circle::paintEvent(QPaintEvent *)
{
    QPainter painter(this);

painter.setRenderHint(QPainter::Antialiasing, true);
painter.setPen(this->pen);

int stepSize = 360/this->steps;
float devideValue = ((100.0/this->maxValue)*this->value)/100.0;
int roundedSize = this->steps*devideValue;
int angel = -1.0*16.0*(stepSize*roundedSize);

qDebug() << "steps: " << steps;
qDebug() << "stepSize: " << stepSize;
qDebug() << "devideValue: " << devideValue;
qDebug() << "roundedSize: " << roundedSize;
qDebug() << "stepSize*roundedSize: " << (stepSize*roundedSize);
qDebug() << "angel: " << angel;
qDebug() << "angel: " << angel;


painter.drawArc(this->pen.width()/2, this->pen.width()/2, this->geometry().width()-(this->pen.width()), this->geometry().height()-(this->pen.width()), 0, angel);

/*QPainterPath circle_path;
circle_path.arcTo(this->pen.width()/2, this->pen.width()/2, this->geometry().width()-(this->pen.width()), this->geometry().height()-(this->pen.width()), 0, angel);
painter.drawPath(circle_path);*/
}

void Circle::setPen(QPen pen)
{
this->pen = pen;
}

Также я заметил, что если ширина пера отличается от другой дуги, «начальная точка 0» отличается для каждой ширины пера...

Вот результаты, чтобы лучше понять, что идет не так.

На этом изображении также присутствует первая проблема с линией. (QPainterPath) На этом изображении также присутствует первая проблема с линией. (QPainterPath)

Это вывод с помощью painter.drawArc Это вывод с помощью painter.drawArc

//Редактировать// Ожидаемый результат должен быть примерно таким. Обратите внимание, что spanAngle зеленого круга отличается от двух изображений выше, потому что я сделал результат с фотошопом, и с этими spanAngles было проще :) введите здесь описание изображения

Это должно дать понять, в чем моя проблема. После тестирования с помощью drawEllipse я узнаю, что ширина пера меньше на 45 часах, чем на 90 часах.

Может ли кто-нибудь помочь мне избавиться от этих проблем? Я также доволен различными решениями для получения таких открытых колец.

С уважением, ПрДатур


person prdatur    schedule 15.06.2013    source источник
comment
Каков желаемый результат? Выложите фото если можно. Что значит несимметричный?   -  person Pavel Strakhov    schedule 15.06.2013
comment
Разве вы не видите 2 большие картинки с результатами (3 кольца), если вы их видите, то должны видеть, что на 90,180,270,360 градусов подходит, но ширина кольца меньше на 45, 135, 215, 295 градусов. Если вы не видите 2 изображения, сообщите мне   -  person prdatur    schedule 15.06.2013
comment
Извините, только что проснулся и неправильно прочитал ваш вопрос, добавил недостающую информацию   -  person prdatur    schedule 15.06.2013
comment
В сторону: я думаю, что несимметричный - это неправильное написание несимметричного   -  person rivimey    schedule 16.06.2013


Ответы (1)


Есть 2 проблемы. Во-первых, начальная точка дуги зависит от ширины пера. Это легко исправить настройками pen.setCapStyle(Qt::FlatCap); для каждого используемого пера.

Вторая проблема — незаполненное пространство между дугами. Я не могу понять, почему это происходит. Это каким-то образом связано с системой QPen/QPainter Qt, но я не могу найти способ это исправить.

Однако я нашел обходной путь. Создайте соответствующие QPainterPath, содержащие границы вашей фигуры, а затем используйте QPainter::fillPath вместо обводки ручкой.

Побочная задача — использовать QPainterPath::moveArcTo для перемещения и обводки линии. Насколько я вижу, он не поддерживается. Нам понадобится следующая вспомогательная функция, которая будет использоваться с методом QPainterPath::lineTo:

QPointF my_find_ellipse_coords(const QRectF &r, qreal angle) {
  QPainterPath path;
  path.arcMoveTo(r, angle);
  return path.currentPosition();
}

В функции paintEvent:

double angle = -1.0*(stepSize*roundedSize); // removed '*16' here
QPainterPath path;
QRectF outer_rect(0, 0, width(), height());
QRectF inner_rect(pen.width(), pen.width(),   
                  width() - pen.width() * 2, height() - pen.width() * 2);
path.arcMoveTo(outer_rect, 0);
path.arcTo(outer_rect, 0, angle);
path.lineTo(my_find_ellipse_coords(inner_rect, angle));
path.arcTo(inner_rect, angle, -angle);
path.lineTo(my_find_ellipse_coords(outer_rect, 0));
path.closeSubpath();
painter.fillPath(path, QBrush(pen.color()));

В вашем коде есть некоторые другие незначительные проблемы. Для circleHours вы установили value больше, чем maxValue. Также вы должны опустить this-> при доступе к членам класса.

В случае каких-либо проблем с моим кодом проверьте полный файл, который я использовал для его тестирования.

person Pavel Strakhov    schedule 15.06.2013
comment
Вы спасли мне жизнь :) Большое спасибо за это идеальное решение. - person prdatur; 15.06.2013
comment
Хотя моя проблема была другой, ваше предложение Кэпа исправило мои дуги (угол 1º был слишком большим) - person Frederic Yesid Peña Sánchez; 17.11.2014