QT控件大全 三十三 QRoundProgressBar
来源:互联网 发布:php时间戳转换年月日 编辑:程序博客网 时间:2024/06/09 23:50
效果如图:
核心代码:
#ifndef QROUNDPROGRESSBAR_H#define QROUNDPROGRESSBAR_H#include <QWidget>/** * @brief The QRoundProgressBar class represents a circular progress bar and maintains its API * similar to the *QProgressBar*. * * ### Styles * QRoundProgressBar currently supports Donut, Pie, Expand and Line styles. See setBarStyle() for more details. * * ### Colors * Generally QRoundProgressBar uses its palette and font attributes to define how it will look. * * The following \a QPalette members are considered: * - *QPalette::Window* background of the whole widget (normally should be set to Qt::NoBrush) * - *QPalette::Base* background of the non-filled progress bar area (should be set to Qt::NoBrush to make it transparent) * - *QPalette::AlternateBase* background of the central circle where the text is shown (for \a Donut style) * - *QPalette::Shadow* foreground of the non-filled progress bar area (i.e. border color) * - *QPalette::Highlight* background of the filled progress bar area * - *QPalette::Text* color of the text shown in the center * * Create a \a QPalette with given attributes and apply it via `setPalette()`. * * ### Color gradient * \a Donut, \a Expand and \a Pie styles allow to use color gradient for currernt value area instead of plain brush fill. * See setDataColors() for more details. * * ### Value text * Value text is generally drawn inside the QRoundProgressBar using its `font()` and \a QPalette::Text role from its `palette()`. * * To define pattern of the text, use setFormat() function (see Qt's \a QProgressBar for more details). * * To define number of decimals to be shown, use setDecimals() function. * * ### Font * To use own font for value text, apply it via `setFont()`. * * By default, font size will be adjusted automatically to fit the inner circle of the widget. */class QRoundProgressBar : public QWidget{ Q_OBJECTpublic: explicit QRoundProgressBar(QWidget *parent = 0); static const int PositionLeft = 180; static const int PositionTop = 90; static const int PositionRight = 0; static const int PositionBottom = -90; /** * @brief Return position (in degrees) of minimum value. * \sa setNullPosition */ double nullPosition() const { return m_nullPosition; } /** * @brief Defines position of minimum value. * @param position position on the circle (in degrees) of minimum value * \sa nullPosition */ void setNullPosition(double position); /** * @brief The BarStyle enum defines general look of the progress bar. */ enum BarStyle { /// Donut style (filled torus around the text) StyleDonut, /// Pie style (filled pie segment with the text in center) StylePie, /// Line style (thin round line around the text) StyleLine, /// Expand style (circle filled from inside to outline) StyleExpand }; /** * @brief Sets visual style of the widget. * \sa barStyle */ void setBarStyle(BarStyle style); /** * @brief Returns current progree bar style. * \sa setBarStyle */ BarStyle barStyle() const { return m_barStyle; } /** * @brief Sets width of the outline circle pen. * @param penWidth width of the outline circle pen (in pixels) */ void setOutlinePenWidth(double penWidth); /** * @brief Returns width of the outline circle pen. */ double outlinePenWidth() const { return m_outlinePenWidth; } /** * @brief Sets width of the data circle pen. * @param penWidth width of the data circle pen (in pixels) */ void setDataPenWidth(double penWidth); /** * @brief Returns width of the data circle pen. */ double dataPenWidth() const { return m_dataPenWidth; } /** * @brief Sets colors of the visible data and makes gradient brush from them. * Gradient colors can be set for \a Donut and \a Pie styles (see setBarStyle() function). * * *Warning*: this function will override widget's `palette()` to set dynamically created gradient brush. * * @param stopPoints List of colors (should have at least 2 values, see Qt's \a QGradientStops for more details). * Color value at point 0 corresponds to the minimum() value, while color value at point 1 * corresponds to the maximum(). Other colors will be distributed accordingly to the defined ranges (see setRange()). */ void setDataColors(const QGradientStops& stopPoints); /** * @brief Defines the string used to generate the current text. * If no format is set, no text will be shown. * @param format see \a QProgressBar's format description * \sa setDecimals */ void setFormat(const QString& format); /** * @brief Sets format string to empty string. No text will be shown therefore. * See setFormat() for more information. */ void resetFormat(); /** * @brief Returns the string used to generate the current text. */ QStringformat() const { return m_format; } /** * @brief Sets number of decimals to show after the comma (default is 1). * \sa setFormat */ void setDecimals(int count); /** * @brief Returns number of decimals to show after the comma (default is 1). * \sa setFormat, setDecimals */ int decimals() const { return m_decimals; } /** * @brief Returns current value shown on the widget. * \sa setValue() */ double value() const { return m_value; } /** * @brief Returns minimum of the allowed value range. * \sa setMinimum, setRange */ double minimum() const { return m_min; } /** * @brief Returns maximum of the allowed value range. * \sa setMaximum, setRange */ double maximum() const { return m_max; }public Q_SLOTS: /** * @brief Defines minimum und maximum of the allowed value range. * If the current value does not fit into the range, it will be automatically adjusted. * @param min minimum of the allowed value range * @param max maximum of the allowed value range */ void setRange(double min, double max); /** * @brief Defines minimum of the allowed value range. * If the current value does not fit into the range, it will be automatically adjusted. * @param min minimum of the allowed value range * \sa setRange */ void setMinimum(double min); /** * @brief Defines maximum of the allowed value range. * If the current value does not fit into the range, it will be automatically adjusted. * @param max maximum of the allowed value range * \sa setRange */ void setMaximum(double max); /** * @brief Sets a value which will be shown on the widget. * @param val must be between minimum() and maximum() */ void setValue(double val); /** * @brief Integer version of the previous slot. * @param val must be between minimum() and maximum() */ void setValue(int val);protected: virtual void paintEvent(QPaintEvent *event); virtual void drawBackground(QPainter& p, const QRectF& baseRect); virtual void drawBase(QPainter& p, const QRectF& baseRect); virtual void drawValue(QPainter& p, const QRectF& baseRect, double value, double delta); virtual void calculateInnerRect(const QRectF& baseRect, double outerRadius, QRectF& innerRect, double& innerRadius); virtual void drawInnerBackground(QPainter& p, const QRectF& innerRect); virtual void drawText(QPainter& p, const QRectF& innerRect, double innerRadius, double value); virtual QString valueToText(double value) const; virtual void valueFormatChanged(); virtual QSize minimumSizeHint() const { return QSize(32,32); } virtual bool hasHeightForWidth() const { return true; } virtual int heightForWidth(int w) const { return w; } void rebuildDataBrushIfNeeded(); double m_min, m_max; double m_value; double m_nullPosition; BarStyle m_barStyle; double m_outlinePenWidth, m_dataPenWidth; QGradientStops m_gradientData; bool m_rebuildBrush; QString m_format; int m_decimals; static const int UF_VALUE = 1; static const int UF_PERCENT = 2; static const int UF_MAX = 4; int m_updateFlags;};#endif // QROUNDPROGRESSBAR_H
#include "QRoundProgressBar.h"#include <QtGui/QPainter>QRoundProgressBar::QRoundProgressBar(QWidget *parent) : QWidget(parent), m_min(0), m_max(100), m_value(25), m_nullPosition(PositionTop), m_barStyle(StyleDonut), m_outlinePenWidth(1), m_dataPenWidth(1), m_rebuildBrush(false), m_format("%p%"), m_decimals(1), m_updateFlags(UF_PERCENT){}void QRoundProgressBar::setRange(double min, double max){ m_min = min; m_max = max; if (m_max < m_min) qSwap(m_max, m_min); if (m_value < m_min) m_value = m_min; else if (m_value > m_max) m_value = m_max; m_rebuildBrush = true; update();}void QRoundProgressBar::setMinimum(double min){ setRange(min, m_max);}void QRoundProgressBar::setMaximum(double max){ setRange(m_min, max);}void QRoundProgressBar::setValue(double val){ if (m_value != val) { if (val < m_min) m_value = m_min; else if (val > m_max) m_value = m_max; else m_value = val; update(); }}void QRoundProgressBar::setValue(int val){ setValue(double(val));}void QRoundProgressBar::setNullPosition(double position){ if (position != m_nullPosition) { m_nullPosition = position; m_rebuildBrush = true; update(); }}void QRoundProgressBar::setBarStyle(QRoundProgressBar::BarStyle style){ if (style != m_barStyle) { m_barStyle = style; m_rebuildBrush = true; update(); }}void QRoundProgressBar::setOutlinePenWidth(double penWidth){ if (penWidth != m_outlinePenWidth) { m_outlinePenWidth = penWidth; update(); }}void QRoundProgressBar::setDataPenWidth(double penWidth){ if (penWidth != m_dataPenWidth) { m_dataPenWidth = penWidth; update(); }}void QRoundProgressBar::setDataColors(const QGradientStops &stopPoints){ if (stopPoints != m_gradientData) { m_gradientData = stopPoints; m_rebuildBrush = true; update(); }}void QRoundProgressBar::setFormat(const QString &format){ if (format != m_format) { m_format = format; valueFormatChanged(); }}void QRoundProgressBar::resetFormat(){ m_format = QString::null; valueFormatChanged();}void QRoundProgressBar::setDecimals(int count){ if (count >= 0 && count != m_decimals) { m_decimals = count; valueFormatChanged(); }}void QRoundProgressBar::paintEvent(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 delta = (m_max - m_min) / (m_value - m_min); drawValue(p, baseRect, m_value, delta); // 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);}void QRoundProgressBar::drawBackground(QPainter &p, const QRectF &baseRect){ p.fillRect(baseRect, palette().background());}void QRoundProgressBar::drawBase(QPainter &p, const QRectF &baseRect){ switch (m_barStyle) { case StyleDonut: p.setPen(QPen(palette().shadow().color(), m_outlinePenWidth)); p.setBrush(palette().base()); p.drawEllipse(baseRect); break; case StylePie: case StyleExpand: 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:; }}void QRoundProgressBar::drawValue(QPainter &p, const QRectF &baseRect, double value, double delta){ // nothing to draw if (value == m_min) return; // for Expand style if (m_barStyle == StyleExpand) { p.setBrush(palette().highlight()); p.setPen(QPen(palette().shadow().color(), m_dataPenWidth)); double radius = (baseRect.height() / 2) / delta; p.drawEllipse(baseRect.center(), radius, radius); return; } // for Line style if (m_barStyle == StyleLine) { p.setPen(QPen(palette().highlight().color(), m_dataPenWidth)); p.setBrush(Qt::NoBrush); if (value == m_max) { p.drawEllipse( baseRect.adjusted(m_outlinePenWidth/2, m_outlinePenWidth/2, -m_outlinePenWidth/2, -m_outlinePenWidth/2)); } else { double arcLength = 360.0 / delta; 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); // pie segment outer if (value == m_max) { dataPath.addEllipse(baseRect); } else { double arcLength = 360.0 / delta; 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);}void QRoundProgressBar::calculateInnerRect(const QRectF &/*baseRect*/, double outerRadius, QRectF &innerRect, double &innerRadius){ // for Line and Expand styles if (m_barStyle == StyleLine || m_barStyle == StyleExpand) { innerRadius = outerRadius - m_outlinePenWidth; } else // for Pie and Donut styles { innerRadius = outerRadius * 0.75; } double delta = (outerRadius - innerRadius) / 2; innerRect = QRectF(delta, delta, innerRadius, innerRadius);}void QRoundProgressBar::drawInnerBackground(QPainter &p, const QRectF &innerRect){ if (m_barStyle == StyleDonut) { p.setBrush(palette().alternateBase()); p.drawEllipse(innerRect); }}void QRoundProgressBar::drawText(QPainter &p, const QRectF &innerRect, double innerRadius, double value){ if (m_format.isEmpty()) return; // !!! to revise QFont f(font()); f.setPixelSize(10); QFontMetricsF fm(f); double maxWidth = fm.width(valueToText(m_max)); double delta = innerRadius / maxWidth; double fontSize = f.pixelSize() * delta * 0.75; f.setPixelSize(fontSize); //f.setPixelSize(innerRadius * qMax(0.05, (0.5 - (double)m_decimals * 0.2))); p.setFont(f); QRectF textRect(innerRect); p.setPen(palette().text().color()); p.drawText(textRect, Qt::AlignCenter, valueToText(value));}QString QRoundProgressBar::valueToText(double value) const{ QString textToDraw(m_format); if (m_updateFlags & UF_VALUE) textToDraw.replace("%v", QString::number(value, 'f', m_decimals)); if (m_updateFlags & UF_PERCENT) { double procent = (value - m_min) / (m_max - m_min) * 100.0; textToDraw.replace("%p", QString::number(procent, 'f', m_decimals)); } if (m_updateFlags & UF_MAX) textToDraw.replace("%m", QString::number(m_max - m_min + 1, 'f', m_decimals)); return textToDraw;}void QRoundProgressBar::valueFormatChanged(){ m_updateFlags = 0; if (m_format.contains("%v")) m_updateFlags |= UF_VALUE; if (m_format.contains("%p")) m_updateFlags |= UF_PERCENT; if (m_format.contains("%m")) m_updateFlags |= UF_MAX; update();}void QRoundProgressBar::rebuildDataBrushIfNeeded(){ if (!m_rebuildBrush) return; if (m_gradientData.isEmpty()) return; if (m_barStyle == StyleLine) return; m_rebuildBrush = false; QPalette p(palette()); if (m_barStyle == StyleExpand) { QRadialGradient dataBrush(0.5,0.5, 0.5, 0.5,0.5); dataBrush.setCoordinateMode(QGradient::StretchToDeviceMode); // set colors for (int i = 0; i < m_gradientData.count(); i++) dataBrush.setColorAt(m_gradientData.at(i).first, m_gradientData.at(i).second); p.setBrush(QPalette::Highlight, dataBrush); } else { QConicalGradient dataBrush(QPointF(0.5,0.5), m_nullPosition); dataBrush.setCoordinateMode(QGradient::StretchToDeviceMode); // invert colors for (int i = 0; i < m_gradientData.count(); i++) dataBrush.setColorAt(1.0 - m_gradientData.at(i).first, m_gradientData.at(i).second); p.setBrush(QPalette::Highlight, dataBrush); } setPalette(p);}
源码工程:qq:609162385
阅读全文
0 0
- QT控件大全 三十三 QRoundProgressBar
- Qt之QRoundProgressBar(圆形进度条)
- Qt之QRoundProgressBar(圆形进度条)
- Qt编写自定义控件大全
- QT控件大全一AnalogWidgets
- QT控件大全二VirtualKeyboard
- QT控件大全三QLed
- QT控件大全四QMeter
- QT控件大全五QProgressIndicator
- QT控件大全 六 QVUMeter
- QT控件大全 七 QProg
- QT控件大全 八 QNeedleIndicator
- QT控件大全 九 Qnightcharts
- QT控件大全 十 QPower
- QT控件大全 十一 QLock
- QT控件大全 十二 QScale
- QT控件大全 十三 WidgetMarqueeLabel
- QT控件大全 十四 QProgressmeter
- Problem5:Longest Palindromic Substring
- linux CRONTAB定时任务
- Maven下载及配置本地仓库
- AppBarLayout 禁止滑动
- 关于枚举类型的学习(enum)
- QT控件大全 三十三 QRoundProgressBar
- 魏杰教授《解读十九大:迎接新时代,抓住新机遇》-转
- System.err: android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file (c
- Linux系统下安装rz/sz命令及使用说明
- oracle,分区表归档
- C语言学习的第七天(续)
- salt_state
- String用法
- bean xml 属性详解