1. 程式人生 > 程式設計 >Qt繪製時鐘效果

Qt繪製時鐘效果

簡述

QPainter 提供了 2D 繪圖的常用操作,QTimer 提供了定時器功能,將兩者相結合,可以做出很多的自定義特效繪製。

下面,來實現一個每天都要接觸的東西 - 時鐘。包含了常見的所有功能:時針、分針、秒針。

實現方式

由於時鐘是妙級更新的,所以我們需要定時重新整理,時鐘本身則使用之前講過的 QPainter 來進行繪製。

使用 QTimer 定時重新整理,設定超時時間為 1000 毫秒(1 秒)。
繪製時鐘,通過 paintEvent() 實現,包括:時針、分針、秒針、及面板、錶盤等。
繪製小時對應的文字,文字區域通過 textRectF() 計算。

示例

效果

Qt繪製時鐘效果

原始碼

首先,我們構造一個定時器 QTimer,連線其超時訊號 timeout() 到槽函式 update(),當呼叫 update() 時,系統會自動通知當前介面進行重繪(paintEvent())。

ClockWidget::ClockWidget(QWidget *parent)
  : QWidget(parent)
{
  ...
 
  // 構造定時器,設定超時為 1 秒
  QTimer *timer = new QTimer(this);
  connect(timer,SIGNAL(timeout()),this,SLOT(update()));
  timer->start(1000);
  ...
}

實現一個用於獲取文字區域的介面:

QRectF ClockWidget::textRectF(double radius,int pointSize,double angle)
{
  QRectF rectF;
  rectF.setX(radius*qCos(angle*M_PI/180.0) - pointSize*2);
  rectF.setY(radius*qSin(angle*M_PI/180.0) - pointSize/2.0);
  rectF.setWidth(pointSize*4);
  rectF.setHeight(pointSize);
  return rectF;
}

注意:這裡,textRectF() 主要用於獲取小時對應的文字區域。

重寫 paintEvent(),用於繪製時鐘。

void ClockWidget::paintEvent(QPaintEvent *event)
{
  Q_UNUSED(event);
 
  // 時針、分針、秒針位置 - 多邊形
  static const QPoint hourHand[3] = {
    QPoint(7,8),QPoint(-7,QPoint(0,-30)
  };
  static const QPoint minuteHand[3] = {
    QPoint(7,-65)
  };
 
  static const QPoint secondHand[3] = {
    QPoint(7,-80)
  };
 
  // 時針、分針、秒針顏色
  QColor hourColor(200,100,200);
  QColor minuteColor(0,127,150);
  QColor secondColor(0,160,230,150);
 
  int side = qMin(width(),height());
  QTime time = QTime::currentTime();
 
  QPainter painter(this);
  painter.setRenderHint(QPainter::Antialiasing);
  // 平移座標系原點至中心點
  painter.translate(width() / 2,height() / 2);
  // 縮放
  painter.scale(side / 200.0,side / 200.0);
 
  // 繪製時針
  painter.setPen(Qt::NoPen);
  painter.setBrush(hourColor);
 
  painter.save();
  // 每圈360° = 12h 即:旋轉角度 = 小時數 * 30°
  painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0)));
  painter.drawConvexPolygon(hourHand,3);
  painter.restore();
 
  painter.setPen(hourColor);
 
  // 繪製小時線 (360度 / 12 = 30度)
  for (int i = 0; i < 12; ++i) {
    painter.drawLine(88,96,0);
    painter.rotate(30.0);
  }
 
  int radius = 100;
  QFont font = painter.font();
  font.setBold(true);
  painter.setFont(font);
  int pointSize = font.pointSize();
 
  // 繪製小時文字
  int nHour = 0;
  for (int i = 0; i < 12; ++i) {
    nHour = i + 3;
    if (nHour > 12)
      nHour -= 12;
    painter.drawText(textRectF(radius*0.8,pointSize,i * 30),Qt::AlignCenter,QString::number(nHour));
  }
 
  // 繪製分針
  painter.setPen(Qt::NoPen);
  painter.setBrush(minuteColor);
 
  painter.save();
  // 每圈360° = 60m 即:旋轉角度 = 分鐘數 * 6°
  painter.rotate(6.0 * (time.minute() + time.second() / 60.0));
  painter.drawConvexPolygon(minuteHand,3);
  painter.restore();
 
  painter.setPen(minuteColor);
 
  // 繪製分鐘線 (360度 / 60 = 6度)
  for (int j = 0; j < 60; ++j) {
    if ((j % 5) != 0)
      painter.drawLine(92,0);
    painter.rotate(6.0);
  }
 
  // 繪製秒針
  painter.setPen(Qt::NoPen);
  painter.setBrush(secondColor);
 
  painter.save();
  // 每圈360° = 60s 即:旋轉角度 = 秒數 * 6°
  painter.rotate(6.0 * time.second());
  painter.drawConvexPolygon(secondHand,3);
  painter.restore();
}

好了,註釋寫的很清楚了,就不多做講解了,如果要做一個應用,可以自己實現一些設定指標、錶盤樣式外觀的一些介面。

注意:網上很多文字都是在旋轉之後繪製上去的,效果並不好(6 顯示的是 9),所以請避免這一點!

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。