QT控件大全 四十五 QSclock

来源:互联网 发布:控制网络连接管理 编辑:程序博客网 时间:2024/06/07 01:00
描述:
qsegmentwidget旨在为段的部件如进度控制、状态显示基类,钟…
一个qsegmentwidget包含气缸数与指定的宽度。
每个气缸都可以显示若干段,并具有明确的开始和停止。

角。段可以通过适当的槽进行修改。

效果如图:


核心代码:

#ifndef _QSEGMENTWIDGET_H_#define _QSEGMENTWIDGET_H_#include <Qt>#include <QWidget>#include <QList>/**  @brief QSegmentWidget class provides a rounded segment control.  QSegmentWidget is intended as base class for segment widgets like  progress controls, status displays, clocks ...  @image html SegmentClock1.png  A QSegmentWidget contains a number of cylinders with a specified width.   Every cylinder can show a number of arcs with a defined start and stop  angle. The segments can be modified by appropriate slots.  @authors Joerg Dentler  @note sclock/sclock  example shows a segment clock.*/class QSegmentWidget : public QWidget{  Q_OBJECTpublic:  /**   * Defines a segment with start and stop angle.   */  typedef QPair<qreal, qreal> Segment;  /**   * A list of segments   */  typedef QList<Segment> SegmentList;public:   /**   * Constructor   *   * @param parent Parent widget   */  QSegmentWidget(QWidget *parent = 0);  /**   * @return The number of cylinders in the widget   */  int cylinders() const { return m_cylinders.size(); }  /**   * @return The current widget color   */  QColor color() const { return m_color; }  ~QSegmentWidget();public slots:  /**   * This slot is used to set the default segment color.   */void setColor(const QColor &c);  /**   * This slot is used to add a new cylinder at the outer ring.   * @param size Relative cylinder size   */  void addCylinder(qreal size = 1.0);  /**   * This slot is used to add a new cylinder at the outer ring.   * @param c The cylinder color to be used   * @param size Relative cylinder size   */  void addCylinder(const QColor &c, qreal size = 1.0);  /**   * This slot is used to draw a new segment.   *    * A segment with a specified start and stop angle will be drawn.   * The angles should be specified in degrees and can be > 360° or < 0°.   * @param cyl The index of the cylinder for drawing.   * @param startAngle The start angle of the current segment   * @param stopAngle The stop angle of the current segment   */  void addSegment(int cyl, qreal startAngle, qreal stopAngle);  /**   * This slot is used to draw new segments.   *    * A list of segments will be drawn.   * @param cyl The index of the cylinder for drawing   * @param s The list of segments to draw   */  void addSegments(int cyl, const SegmentList &s);  /**   * This slot is used to clear a segment from a cylinder.   *   * The specified segment will be drawn with the specified background    * color. With this method highlighted segments can be erased.   * @param cyl The index of the cylinder for clearing   * @param startAngle The start angle of the segment   * @param stopAngle The stop angle of the segment   */  void clearSegment(int cyl, qreal startAngle, qreal stopAngle);  /**   * This slot is used to clear a list of segments from a cylinder.   *   * @param cyl The index of the cylinder for clearing   * @param s The list of segments to clear   */  void clearSegments(int cyl, const SegmentList &s);  /**   * This slot is used to clear all cylinders of the QSegmentWidget.   */  void clear();protected:  class Cylinder  {    public:      Cylinder():        size(0.0),        innerRadius(0.0),        outerRadius(0.0)      {  }      Cylinder(const Cylinder &c):        size(c.size),        innerRadius(c.innerRadius),        outerRadius(c.outerRadius),        color(c.color)      {  }      qreal size;      qreal innerRadius;      qreal outerRadius;      QColor color;  };  enum  {    BM_SIZE   =   400,    BM_RADIUS =  (BM_SIZE / 2),    BM_BEVEL  = ((BM_SIZE * 8) / 100),    BM_OSIZE  =  (BM_SIZE + BM_BEVEL),  };protected:  QColor m_color;  QList<Cylinder> m_cylinders;  QPixmap *m_pixmap;protected:  void paintEvent(QPaintEvent *event);  void InitPixmap();  void DrawBevel(QPainter *painter);  void DrawBackground(QPainter *painter);  void DrawCylinder(const Cylinder &cyl,     const SegmentList &s, const bool erase);  void DrawSegments(QPainter *painter,     const SegmentList &s, qreal radius);  void CalculateRadians();  qreal TrimAngle(const qreal &a);};#endif
#include <QtGui>#include "qsegmentwidget.h"QSegmentWidget::QSegmentWidget(QWidget *parent):   QWidget(parent),  m_pixmap(0){  m_color = palette().color(foregroundRole());}void QSegmentWidget::InitPixmap(){  m_pixmap = new QPixmap(BM_OSIZE, BM_OSIZE);  m_pixmap->fill(palette().color(backgroundRole()));  QPainter painter(m_pixmap);  painter.setRenderHint(QPainter::Antialiasing, true);  painter.setWindow( -(BM_OSIZE / 2), -(BM_OSIZE / 2),    BM_OSIZE, BM_OSIZE);  DrawBevel(&painter);  DrawBackground(&painter);}QSegmentWidget::~QSegmentWidget(){  delete m_pixmap;  m_pixmap = 0;}void QSegmentWidget::paintEvent(QPaintEvent *){  if (!m_pixmap)    InitPixmap();  QPainter painter(this);  int side = qMin(width(), height());  painter.setViewport((width() - side) / 2, (height() - side) / 2,    side, side);  painter.setWindow(0, 0, BM_OSIZE, BM_OSIZE);  painter.drawPixmap(0, 0, *m_pixmap); }void QSegmentWidget::DrawBevel(QPainter *painter){  painter->save();  QRadialGradient g(0, 0, BM_OSIZE / 2, 0, 0);  QPalette p = palette();  g.setColorAt(0.0, p.color(QPalette::Normal, QPalette::Midlight));  g.setColorAt(0.8, p.color(QPalette::Normal, QPalette::Dark));  g.setColorAt(0.9, p.color(QPalette::Normal, QPalette::Light));  g.setColorAt(1.0, p.color(QPalette::Normal, QPalette::Shadow));  painter->setPen(Qt::NoPen);  painter->setBrush(g);  painter->drawEllipse(    -((BM_SIZE + BM_BEVEL) / 2),    -((BM_SIZE + BM_BEVEL) / 2),    BM_SIZE + BM_BEVEL,    BM_SIZE + BM_BEVEL);  painter->restore();}void QSegmentWidget::DrawCylinder(const Cylinder &cyl,   const SegmentList &s, const bool erase){  if (!m_pixmap)    InitPixmap();  QPainter painter(m_pixmap);  painter.setRenderHint(QPainter::Antialiasing, true);  painter.setWindow( -(BM_OSIZE / 2), -(BM_OSIZE / 2),    BM_OSIZE, BM_OSIZE);  QRectF rco(-cyl.outerRadius, -cyl.outerRadius, cyl.outerRadius * 2.0,      cyl.outerRadius * 2.0);  QRectF rci(-cyl.innerRadius, -cyl.innerRadius, cyl.innerRadius * 2.0,      cyl.innerRadius * 2.0);  QRegion ro(rco.toRect(), QRegion::Rectangle);  QRegion ri(rci.toRect(), QRegion::Ellipse);  QRegion region = ro.subtracted(ri);  painter.setClipRegion(region);  if (erase) {    QBrush b(m_color.darker(2 * 200));    painter.setBrush(b);    painter.setPen(QPen(b, 1.0));  } else {    QBrush b(cyl.color);    painter.setBrush(b);    painter.setPen(Qt::NoPen);  }  DrawSegments(&painter, s, cyl.outerRadius);}void QSegmentWidget::DrawSegments(QPainter *painter,   const SegmentList &s, qreal radius){  for (SegmentList::const_iterator i = s.begin(); i != s.end(); i++) {    int startAngle = qRound(i->first * 16.0);    qreal dAngle = i->second - i->first;    if (dAngle < 0.0)      dAngle += 360.0;    int spanAngle = qRound(dAngle * 16.0);    QRectF r(-radius, -radius, radius * 2.0, radius * 2.0);    if (spanAngle >= 360 * 16)      painter->drawEllipse(r);    else      painter->drawPie(r, startAngle, spanAngle);  }}void QSegmentWidget::DrawBackground(QPainter *painter){  painter->save();  QBrush face(m_color.darker(2 * 200));  painter->setBrush(face);  painter->drawEllipse(-BM_RADIUS, -BM_RADIUS, BM_SIZE, BM_SIZE);  painter->restore();}void QSegmentWidget::setColor(const QColor &c){  m_color = c;  delete m_pixmap;  m_pixmap = 0;}void QSegmentWidget::addCylinder(qreal size){  Q_ASSERT(size > 0.0);  Cylinder cyl;  cyl.size = size;  cyl.color = m_color;  m_cylinders.push_back(cyl);  CalculateRadians();  delete m_pixmap;  m_pixmap = 0;}void QSegmentWidget::addCylinder(const QColor &c, qreal size){  Q_ASSERT(size > 0.0);  Cylinder cyl;  cyl.size = size;  cyl.color = c;  m_cylinders.push_back(cyl);  CalculateRadians();  delete m_pixmap;  m_pixmap = 0;}void QSegmentWidget::clear(){  m_cylinders.clear();  delete m_pixmap;  m_pixmap = 0;}void QSegmentWidget::CalculateRadians(){  qreal ssum = 0.0;  for (QList<Cylinder>::iterator i = m_cylinders.begin();      i != m_cylinders.end(); i++) {    ssum += i->size;  }  qreal r = 0.0;  for (QList<Cylinder>::iterator i = m_cylinders.begin();      i != m_cylinders.end(); i++) {    qreal s = (i->size / ssum) * BM_RADIUS;     i->innerRadius = r;     r += s;    i->outerRadius = r;  }}void QSegmentWidget::addSegment(int cyl, qreal startAngle, qreal stopAngle){  Segment s(startAngle, stopAngle);  SegmentList sl;  sl.push_back(s);  addSegments(cyl, sl);}void QSegmentWidget::addSegments(int cyl, const SegmentList &s){  Q_ASSERT(cyl >= 0 && cyl < m_cylinders.size());  Cylinder &cylinder = m_cylinders[cyl];  DrawCylinder(cylinder, s, false);  update();}void QSegmentWidget::clearSegment(int cyl, qreal startAngle, qreal stopAngle){  Segment s(startAngle, stopAngle);  SegmentList sl;  sl.push_back(s);  clearSegments(cyl, sl);}void QSegmentWidget::clearSegments(int cyl, const SegmentList &s){  Q_ASSERT(cyl >= 0 && cyl < m_cylinders.size());  Cylinder &cylinder = m_cylinders[cyl];  DrawCylinder(cylinder, s, true);  update();}qreal QSegmentWidget::TrimAngle(const qreal &a){  qreal r = a;  while (r > 360.0)    r -= 360.0;  while (r < 0.0)    r += 360.0;  return r;}


源码工程:QQ:609162385