Frage

I'm pretty new to QT and I can not understand why my arc's are drawed so bad. I have 2 problems.

First one, which I think is just normal for such drawing, is: If I draw with a QPainterPath a straight line will be drawed on every arc, from the end of the arc to the direction of point 0,0 but not completely to 0,0 instead it is just, i think, the half way to that point...

Second one: If I use QPainterPath or painter.drawArc the "rings" are unsemetric if i change the pen width.

I have this code which will init my Arc's.

//Edit// Sorry forgot to provide where w and h is created. this->getMainWidget() returns just a QWidget where my elements are drawed. the geometry and position of the toplevel widget and one from this->getMainWidget() are the same.

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

This will setup 3 Arc's. First and third one have the same pen width of 50, the second one has 100.

For completion here is the Circle class:

#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;
}

Also I have noticed that, if the pen width differs from other arc's the "starting point 0" is different for each pen width...

Here are the output's to get a better understanding what goes wrong.

At this image the first problem with the line issue also present. (QPainterPath) At this image the first problem with the line issue also present. (QPainterPath)

This is the output with painter.drawArc This is the output with painter.drawArc

//Edit// The expected result should be something like this. Please note that the green circle spanAngle is different from the 2 images above because i did the result with photoshop and it was easier with those spanAngles :) enter image description here

It should make it know clear what my problem is. After testing with drawEllipse i recognize the same behaviour that the pen width is smaller at 45 clock as at 90 clock.

Can anybody help me to get rid of those issues? I'm also happy with different solutions to get such opened rings.

best regards, PrDatur

War es hilfreich?

Lösung

There are 2 issues. The first is that starting point of arc depends on pen's width. It can be easily fixed by settings pen.setCapStyle(Qt::FlatCap); for each used pen.

The second issue is unfilled space between arcs. I can't understand why is it happening. It's somehow connected with Qt's QPen/QPainter system, but I can't find any way to fix it.

However, I found a workaround. Create appropriate QPainterPath containing borders of your figure, and then use QPainter::fillPath instead of stroking with a pen.

A side task is to use QPainterPath::moveArcTo to move and stroke a line. As far as I see, It's not supported. We'll need the following helper function that will be used with QPainterPath::lineTo method:

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

In paintEvent function:

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

There are some other minor issues in your code. For circleHours you have set the value bigger than maxValue. Also you should omit this-> when accessing class members.

In case of any issues with my code, examine complete file I was using to test it.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top