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 часов.

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

с уважением,
PrDatur

0

Решение

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

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

Тем не менее, я нашел обходной путь. Создать соответствующий 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-> при доступе к ученикам.

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

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]