PDA

View Full Version : how can i draw rectanglar percentage?



icapathos
21st August 2013, 10:04
9434
I'd like to create a widget that present a percentage like above.
So, I use QPainterPath, and try to do that with "addRect" and "arcTo". But I can't get the willing result.
9435
Maybe I'm not good at order of drawing, so I hope to someone tell me the way.

Santosh Reddy
21st August 2013, 11:09
Hope this helps.
9436


#include <QtGlobal>
#include <QApplication>

#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
#include <QtWidgets>
#else
#include <QtGui>
#endif

#include "windows.h"

class ProgressRect : public QProgressBar
{
Q_OBJECT
public:
explicit ProgressRect(QWidget * parent = 0) : QProgressBar(parent) { }

protected:
void paintEvent(QPaintEvent * event)
{
QPainter painter(this);
int w = 0;
int h = 0;

QPen pen = painter.pen();
pen.setWidth(1);
pen.setColor(QColor(Qt::red));

QBrush brush = painter.brush();
brush.setColor(QColor(Qt::red));
brush.setStyle(Qt::SolidPattern);

// Paint red background rectangle
painter.setPen(pen);
painter.setBrush(brush);
w = pen.width() / 2;
painter.drawRect(event->rect().adjusted(w, w, -w, -w));

// Paint green pie based on current value
pen.setColor(Qt::green);
brush.setColor(Qt::green);
painter.setPen(pen);
painter.setBrush(brush);
h = event->rect().size().height();
w = event->rect().size().width();
w = qSqrt(h * h + w * w);
QRect rect(0, 0, w, w);
rect.moveCenter(event->rect().center());
if(invertedAppearance())
painter.drawPie(rect, 90 * 16, value() * 360 * 16 / 100);
else
painter.drawPie(rect, 90 * 16, -value() * 360 * 16 / 100);

// Paint white rectangle to partially hide the pie
pen.setColor(Qt::white);
brush.setColor(Qt::white);
painter.setPen(pen);
painter.setBrush(brush);
w = 20;
if((event->rect().size().height() > w * 2) and (event->rect().size().width() > w * 2))
painter.drawRect(event->rect().adjusted(w, w, -w, -w));

// Paint the value in text in the centre
pen.setColor(QColor(Qt::black));
painter.setPen(pen);
painter.drawText(event->rect(), QString::number(value()), QTextOption(Qt::AlignCenter));
}
};

int main(int argc, char *argv[])
{
QApplication app(argc, argv);

ProgressRect rect;
rect.setMaximum(100);
rect.setFixedSize(200, 200);
rect.show();

for(int i = 1; i <= 100; i++)
{
rect.setValue(i);
qApp->processEvents();
Sleep(100);
}

return 0;
}

#include "main.moc"

wysota
21st August 2013, 11:10
Use clipping on the painter to obtain the result you want.

icapathos
22nd August 2013, 02:58
Thank you for your comment. But I hope that the white region to be transparent. :)

ChrisW67
22nd August 2013, 03:36
... and incomplete requirements are why software projects are notorious for being late ;)

What are you expecting to see in the transparent region?

icapathos
22nd August 2013, 05:16
I try to show splashscreen widget on my listView (icon based). So, I want to let the WIDGET shown up on item in listView.
I just want to see the item trough the transparent region. :o

wysota
22nd August 2013, 07:12
Again -- use clipping to filter out what regions of the widget the draw operations modify.Then you can just draw a red rectangle and a green pie segment over it and you'll obtain the effect you want.

Santosh Reddy
22nd August 2013, 13:36
Thank you for your comment. But I hope that the white region to be transparent.

I try to show splashscreen widget on my listView (icon based). So, I want to let the WIDGET shown up on item in listView.
I just want to see the item trough the transparent region.
Ok then here it is again with transparent background.


#include <QtGlobal>
#include <QApplication>

#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
#include <QtWidgets>
#else
#include <QtGui>
#endif

class ProgressRect : public QProgressBar
{
Q_OBJECT
public:
explicit ProgressRect(QWidget * parent = 0)
: QProgressBar(parent)
, mPenWidth(1)
{
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
}

protected:
void resizeEvent(QResizeEvent * event)
{
QProgressBar::resizeEvent(event);

int t = 20;
int w = mPenWidth / 2;

QRect outRect;
QRect inRect;

outRect.setSize(event->size());
outRect.adjust(w, w, -w, -w);

if((event->size().height() > (t * 2)) and (event->size().width() > (t * 2)))
inRect = outRect.adjusted(t, t, -t, -t);

// Set the clipping mask
QRegion outRegion(outRect);
QRegion inRegion(inRect);
outRegion = outRegion.subtracted(inRegion);
setMask(outRegion);
}

void paintEvent(QPaintEvent * event)
{
QPainter painter(this);
int w = 0;
int h = 0;

QPen pen = painter.pen();
pen.setWidth(mPenWidth);
pen.setColor(QColor(Qt::red));

QBrush brush = painter.brush();
brush.setColor(QColor(Qt::red));
brush.setStyle(Qt::SolidPattern);

// Paint red background rectangle
painter.setPen(pen);
painter.setBrush(brush);
w = pen.width() / 2;
QRect outRect = event->rect().adjusted(w, w, -w, -w);
painter.drawRect(outRect);

// Paint green pie based on current value
pen.setColor(Qt::green);
brush.setColor(Qt::green);
painter.setPen(pen);
painter.setBrush(brush);
h = event->rect().size().height();
w = event->rect().size().width();
w = qSqrt(h * h + w * w);
QRect rect(0, 0, w, w);
rect.moveCenter(event->rect().center());
if(invertedAppearance())
painter.drawPie(rect, 90 * 16, value() * 360 * 16 / 100);
else
painter.drawPie(rect, 90 * 16, -value() * 360 * 16 / 100);
}

private:
const int mPenWidth;
};

class Timer : public QObject
{
public:
explicit Timer(QProgressBar * progress, QObject * parent = 0)
: QObject(parent)
, mProgress(progress)
, mCount(0)
{
mProgress->setMaximum(100);
mProgress->setValue(0);
startTimer(100);
}

protected:
void timerEvent(QTimerEvent * event)
{
mCount++;
mProgress->setValue(mCount);

if(mCount == 100)
{
killTimer(event->timerId());
deleteLater();
}
}

private:
QProgressBar * const mProgress;
int mCount;
};

int main(int argc, char *argv[])
{
QApplication app(argc, argv);

QWidget widget;
QHBoxLayout * layout = new QHBoxLayout(&widget);
ProgressRect * rect = new ProgressRect;
new Timer(rect, rect);
layout->addWidget(rect);
widget.showMaximized();
return app.exec();
}

#include "main.moc"