Qt Third party circular progress bar--and its improvement

Source: Internet
Author: User

Improvement of QT Third party circular progress bar

To implement a circular progress bar function, find a more famous third-party package class on the Internet: Qroundprogressbar, Address: SourceForge Qroundprogressbar
Functional package is still good, provides 3 modes, linear, ring, pie-like. Using the process found that the ring progress bar on the background transparency support is not perfect, the background of the inner circle is not transparent, in order to solve this problem, the following changes to this control, to achieve a complete circular progress bar.

Qroundprogressbar present deficiencies

Qroundprogressbar the inner ring background is opaque when using the Styledonut style with the background picture widget

The code is as follows:
Header file:

class DRoundProgressBar;class QTimer;namespace Ui {class Widget;}class Widget : public QWidget{ Q_OBJECTpublic: explicit Widget(QWidget *parent = 0); ~Widget();public slots: void onTimeOut();private: Ui::Widget *ui; QTimer* mTimer; DRoundProgressBar* mRoundBar; int mPresent;};

Cpp:

#include "Widget.h"#include "Ui_widget.h"#include "DRoundProgressBar.h"#include <qtimer>widget::widget (qwidget *parent): Qwidget (parent), UI (New Ui::widget) {UI-&GT;SETUPUI (this); Setautofillbackground (true); Qpixmap img (":/img/bluedialog_bk.png"); Qpalette Bkpalette; Bkpalette.setbrush (Qpalette::window,qbrush (IMG)); SetPalette (Bkpalette); Mroundbar =New Droundprogressbar (this); Mroundbar->setgeometry (150,100,500,500); Mroundbar->setbarstyle (Droundprogressbar::styledonut); Mroundbar->setrange (0,100); Qpalette Palette; Palette.setbrush (Qpalette::window,qt::nobrush); Palette.setbrush (Qpalette::alternatebase,qt::nobrush); Palette.setbrush (Qpalette::highlight,qbrush (Qcolor (0,140,255)); Palette.setcolor (Qpalette::text,qcolor (0,0, 0)); //palette.setbrush (qpalette::base,qt::white); Mroundbar->setpalette (palette); Mtimer = new qtimer (this); Mtimer->setinterval (200); Connect (mtimer,signal (), this,slot (OnTimeOut ())); mpresent = 0; Mtimer->start ();} Widget::~widget () {delete UI;} void widget::ontimeout () {++mpresent; if (mpresent >= 100) {mpresent = 0 ; } mroundbar->setvalue (mpresent);             

Here the Qpalette::window and qpalette::alternatebase are set to transparent and the ring cannot be drawn.

Reason

See the code to see how it draws the ring

void Qroundprogressbar::d rawvalue (Qpainter &p,Const QRECTF &baserect,Double value,Double arclength) {Nothing to drawif (value = = m_min)ReturnFor line Styleif (M_barstyle = styleline) {P.setpen (Qpen (Palette). Highlight (). Color (), m_ Datapenwidth)); P.setbrush (Qt::nobrush); P.drawarc (baserect.adjusted (M_outlinepenwidth/2, m_outlinepenwidth/ 2,-m_outlinepenwidth/2,-m_outlinepenwidth/2), M_nullposition * 16,-arclength * 16); return; } //for Pie and donut Styles Qpainterpath DataPath; Datapath.setfillrule (Qt::windingfill); Span class= "hljs-comment" >//Pie segment Outer Datapath.moveto (Baserect.center ()); Datapath.arcto (Baserect, m_nullposition,-arclength); Datapath.lineto (Baserect.center ()); P.setbrush (Palette (). Highlight ()); P.setpen (Qpen (Palette (). Shadow (). Color (), m_datapenwidth)); P.drawpath (DataPath);          

Discovering that drawing the ring and drawing the pie is a code, and the implementation ring is simply covered with a background, so that if the middle area is transparent it will show the part of the fan that is drawn (the original author is much lazy-_-#).
So. Special treatment is required when drawing a circle, and the ring is filled when the circle is drawn QPainterPath .

Improved

The original function needs to be drawValue modified, the original drawValue function to draw pie and draw donut styles is the same treatment, here fix for pie to draw pie, draw donut styles to draw the ring:
In order to draw a circle, the drawValue function needs to add two variables, which are the corresponding rectangles and radii of the inner ring.

virtual void drawValue(QPainter& p, const QRectF& baseRect, double value, double arcLength, const QRectF & innerRect, double innerRadius);

Modified CPP

void Qroundprogressbar::d rawvalue (Qpainter &p,Const QRECTF &baserect,Double value,Double arclength,Const QRECTF & Innerrect,Double Innerradius) {Nothing to drawif (value = = m_min)ReturnFor line Styleif (M_barstyle = = Styleline) {P.setpen (Qpen (Palette (). Highlight (). Color (), m_datapenwidth)); P.setbrush (Qt::nobrush) ; P.drawarc (baserect.adjusted (m_outlinepenwidth/2, m_outlinepenwidth/2,-m_outlinepenwidth/2,-m_outlinepenwidth/2), M_nullposition *-arclength *16);Return }For Pie and donut Styles Qpainterpath DataPath; Datapath.setfillrule (Qt::windingfill); Datapath.moveto (Baserect.center ()); Datapath.arcto (Baserect, m_nullposition,-arclength);We all draw the arc length of the outer circle first.if (M_barstyle = = Stylepie) {Pie segment Outer Datapath.lineto (Baserect.center ()); P.setpen (Qpen (Palette (). Shadow (). Color (), m_datapenwidth)); }if (M_barstyle = = Styledonut) {Draw Dount outer qpointf currentpoint = datapath.currentposition ();After drawing the outer arc long, get the drawn position to draw a straight line to reach the inner circle currentpoint = Baserect.center () + ((Currentpoint-baserect.center ()) * M_innerouterrate ;//Calculate the coordinate point of the inner circle, m_innerouterrate replace the original author 0.75, representing the inner circle is 0.75 times times the outer Circle Datapath.lineto (currentpoint); //Draw a straight line Datapath.moveto (Baserect.center ()) from the outer circle to the inner circle; //Coordinate point back to center ready to draw inside circular arc datapath.arcto (Innerrect, M_nullposition-arclength, arclength); //Draw the inner circle of the arc currentpoint = Datapath.currentposition (); //Prepare to draw the inner circle to the outer circle of the line, forming the enclosing area currentpoint = Baserect.center () + ((Currentpoint-baserect.center ()) * (2-m_ Innerouterrate)); //Draw the inner circle to the outer circle of the line, here 2-m_innerouterrate is actually corresponding (1 + (1-m_innerouterrate)) Datapath.lineto (currentpoint); P.setpen (Qt:: Nopen); //This is heavy or there will be some outline of the drawing process} P.setbrush (Palette (). Highlight ()); P.drawpath (DataPath);}       

See the code for a detailed procedure.

Here the author of the Inner circle to death to the outer circle of 0.75 times times, I think this loss of flexibility, so added a float variable, m_innerouterrate, the default is 0.75, replace the original 0.75 constant, and add methods float innerOuterRate() const and void setInnerOuterRate(float r) settings

The paintEvent function Order of the original function also needs to be changed:

The following is the original PaintEvent function:

void Qroundprogressbar::p aintevent (qpaintevent*/*event*/) {Double Outerradius = qmin (width (), height ()); QRECTF Baserect (1,1, outerradius-2, outerradius-2); Qimage buffer (Outerradius, Outerradius, qimage::format_argb32_premultiplied); Qpainter p (&buffer); P.setrenderhint (qpainter::antialiasing);Data brush rebuilddatabrushifneeded ();//background drawbackground (p, Buffer.rect ()); //base Circle Drawbase (P, baserect); //data circle double arcstep =  360.0/(m_max-m_min) * m_value; Drawvalue (P, Baserect, M_value, arcstep); //Center circle double Innerradius ( 0); QRECTF Innerrect; Calculateinnerrect (Baserect, Outerradius, Innerrect, Innerradius); Drawinnerbackground (P, innerrect); //text DrawText (p, Innerrect, Innerradius, m_value); //finally draw the bar p.end (); qpainter painter (this); Painter.fillrect (Baserect, Palette (). background ()); Painter.drawimage (0,0, buffer);}      

Originally the author used qimage as a cache, but Qt comes with double buffering, this step is not necessary (with qimage when there are small problems in Ubuntu, in the control compared to the hour (200*200) will appear the flower screen phenomenon, the reason unknown), modified to:

void Qroundprogressbar::p aintevent (qpaintevent*/*event*/) {Double Outerradius = qmin (width (), height ()); QRECTF Baserect (1,1, outerradius-2, outerradius-2); Qpainter P (this); P.setrenderhint (qpainter::antialiasing); //data Brush rebuilddatabrushifneeded (); //background drawbackground (P, rect ()); double Innerradius (0); QRECTF Innerrect; Calculateinnerrect (Baserect, Outerradius, Innerrect, Innerradius); double arcstep = 360.0/(m_max-m_min) * m_value; //base Circle Drawbase (P, baserect,innerrect); //Data Circle Drawvalue (p, Baserect, M_value, Arcstep,innerrect, Innerradius); //Center circle Drawinnerbackground (P, innerrect); //text DrawText (p, Innerrect, Innerradius, m_value); //finally draw the bar p.end ();         

The main function is to calculateInnerRect(baseRect, outerRadius, innerRect, innerRadius); calculate the corresponding parameters of the inner circle in advance. and passed to the newly modified drawValue function. Remove the redundant double-buffering mechanism.

At this point the effect has not yet reached the effect of demand, found that drawBase the function also needs to be modified, the original drawBase function is as follows:

void Qroundprogressbar::d rawbase (Qpainter &p,Const QRECTF &baserect) {switch (m_barstyle) {case Styledonut:p.setpen (QPen (PA Lette (). Shadow (). Color (), m_outlinepenwidth)); P.setbrush (Palette (). Base ()); P.drawellipse (Baserect); break; case Stylepie:p.setpen (Qpen (Palette (). Base (). Color (), m_outlinepenwidth)); P.setbrush ( Palette (). Base ()); P.drawellipse (Baserect); break; case Styleline:p.setpen (Qpen (Palette (). Base (). Color (), m_outlinepenwidth)); P.setbrush (Qt::nobrush); P.drawellipse (baserect.adjusted (M_outlinepenwidth/2, M_outlinepenwidth/2,-m_outlinepenwidth/2,-m_outlinepenwidth/2)) ; break; default:;}}            

The above drawBase function is visible, because the original author is lazy, for the donut style model directly draw an outer circle, not a hollow ring, improved as follows:

void Qroundprogressbar::d rawbase (Qpainter &p,Const QRECTF &baserect,Const QRECTF &innerrect) {Switch (M_barstyle) {Case Styledonut: {Qpainterpath dataPath; Datapath.setfillrule (Qt::oddevenfill); Datapath.moveto (Baserect.center ()); Datapath.addellipse (Baserect); Datapath.addellipse (Innerrect); P.setpen (Qpen (Palette (). Shadow (). Color (), m_outlinepenwidth)); P.setbrush (Palette (). Base ()); P.drawpath (DataPath);Break ;} Case Stylepie:p.setpen (Qpen (Palette (). Base (). Color (), m_outlinepenwidth)); P.setbrush (Palette (). Base ()); P.drawellipse (Baserect); Break ; Case Styleline:p.setpen (Qpen (Palette (). Base (). Color (), m_outlinepenwidth)); P.setbrush (Qt::nobrush); P.drawellipse (baserect.adjusted (m_outlinepenwidth/2, m_outlinepenwidth/2,-m_outlinepenwidth/2,-m_ outlinepenwidth/2)); Break ; default:;}}         

Last Run Effect:

Code See: czyt1988 's GitHub

http://blog.csdn.net/czyt1988/article/details/53422274

Qt Third party circular progress bar--and its improvement

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.