首頁 > 軟體

基於實現Qt秒錶設計

2022-08-04 18:03:09

基於Qt秒錶設計

這個只是虛擬機器器下的Dialog中設計的秒錶,大家感興趣的可以根據自己手機的秒錶介面來設計,亦或是有別的想法也可以在ui中新增函數,或者是在ui介面自己新增調整。本篇將給除了給出Qt秒錶設計例子之外還會為大家提供一些常用函數。

一、Qt繪圖系統簡介

Qt的繪圖系統允許使用相同的API在螢幕和其它列印裝置上進行繪製。整個繪圖系統基於 QPainter,QPainterDevice和QPaintEngine三個類。

QPainter用來執行繪製的操作;

QPaintDevice則允許QPainter在其上面進行繪製,也就是QPainter工作的空間;

QPaintEngine提供了畫筆(QPainter)在不同的裝置上進行繪製的統一的介面。

Qt 的繪圖系統實際上是,使用 QPainter在QPainterDevice上進行繪製,它們之間使用QPaintEngine進行通訊(也就是翻譯QPainter 的指令)。

二、QPainter類的繪圖函數

drawPoint 點drawLine 線
drawRect 矩形drawPath 路徑
drawArc 圓弧drawChord 弦
drawPie 扇形drawEllipse 橢圓
drawText 文字
drawRoundRect 圓角矩形
drawImage drawPixmap drawPicture 顯示影象
drawPoints,drawLines,drawRects 多個點、多條線、多個矩形

三、幾種常用函數效果圖:

四、畫刷和畫筆

QBrush定義了QPainter的填充模式,具有樣式、顏色、漸變以及紋理等屬性。畫刷的style()定義了填充的樣式,使用Qt::BrushStyle列舉,預設值是Qt::NoBrush,也就是不進行任何填充。
QPen定義了用於QPainter應該怎樣畫線或者輪廓線。畫筆具有樣式、寬度、畫刷、筆帽樣式和連線樣式等屬性。畫筆的樣式style()定義了線的樣式。畫筆寬度width()或widthF()定義了畫筆的寬。注意,不存在寬度為 0 的線,畫筆寬度通常至少是 1 畫素。
宣告畫刷或畫筆物件的時候,通常可以先指定顏色,然後再通過類中的setStyle、setWidth等成員函數設定畫刷或畫筆屬性。
QPainter物件要使用畫刷或畫筆,通常是呼叫setBrush和setPen成員函數,設定過畫刷和畫筆的狀態將會一直保持。

五、影象處理

Qt提供了4個處理影象的類:QImage、QPixmap、QBitmap,QPicture,它們有著各自的特點。
QImage優化了I/O操作,可以直接存取操作畫素資料。
QPixmap優化了再螢幕上顯示影象的效能。
QBitmap從QPixmap繼承,只能表示黑白兩種顏色。
QPicture是可以記錄和重啟QPrinter命令的類。
對最簡單的圖片顯示而言,用QImage或QPixmap類比較常見。顯示一副影象,可以在paintEvent函數中如下操作:

QPainter painter(this); // 宣告QPainter物件
… // 其他繪圖操作
// 宣告一個QPixmap物件並初始裝載影象檔案
QPixmap pm("/home/fish/HDU.png");
painter.drawPixmap((rect().width() - pm.width()) / 2,
(rect().height() - pm.height()) / 2, pm); // 居中顯示影象

六、秒錶設計例子

1、.pro檔案

#-------------------------------------------------
#
# Project created by QtCreator 2019-12-04T16:50:48
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = qt_clock
TEMPLATE = app


SOURCES += main.cpp
        dialog.cpp

HEADERS  += dialog.h

FORMS    += dialog.ui

2、標頭檔案:

dialog.h程式碼;

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QTime>
#include <QMouseEvent>

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    Ui::Dialog *ui;
    int state;
    int nMSCnt;
    QTime   sTime;
    QList<int> lstCnt;
    int idx;

    QRect   rcBottom;
    QRect   rcLeft;
    QRect   rcRight;
private   slots:
        void    mytimer ( );

    // QWidget interface
protected:
    void paintEvent(QPaintEvent *);

    // QWidget interface
protected:
    void mousePressEvent(QMouseEvent *);

    // QWidget interface
protected:
    void wheelEvent(QWheelEvent *);
};

#endif // DIALOG_H

3、原始檔

(1)dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"
#include <QPainter>
#include <QTimer>

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    state = 0;
    nMSCnt = 0;
    idx =0;
    sTime =QTime::currentTime();
    QTimer*timer =new QTimer(this);
    connect(timer,SIGNAL(timeout()),this,SLOT(mytimer()));
    timer->start(10);
}

Dialog::~Dialog()
{
    delete ui;
}

void Dialog::mytimer()
{
     if(1==state){
         update();
     }
}


void Dialog::paintEvent(QPaintEvent *)
{
      QRect  rc = rect();
      int size = rc.width() > rc.height() ?  rc.height() : rc.width();

      QPainter qp(this);
      qp.setFont(QFont("Arial",size/6));
      qp.setPen(Qt::black);

      QString str;
      int nms;
      if(state>0){
          if(1==state)
              nms = (sTime.msecsTo(QTime::currentTime()) + nMSCnt) / 10;
          else
              nms = nMSCnt / 10;
          str.sprintf("%02d:%02d.%02d",nms / 6000 , (nms / 100) % 60 , nms % 100);
      }
      else {
           str="00:00.00";
      }

      if (lstCnt.empty())
          qp.drawText(rect(),Qt::AlignCenter,str);
      else{
          qp.drawText(rect(),Qt::AlignTop | Qt::AlignHCenter,str);
          qp.setPen(Qt::gray);
          qp.setFont(QFont("Arial",size / 10));
          QRect t = rect();
          t.translate(0, size / 6 + size / 20);
          nms -= lstCnt.last() / 10;
          str.sprintf("%02d:%02d.%02d",nms/6000 , (nms/100)%60 , nms%100);
         qp.drawText(t,Qt::AlignTop | Qt::AlignHCenter,str);

         qp.setFont(QFont("Arial",size / 15));
         qp.setPen(Qt::darkBlue);
         t.translate(0, size / 6);
         int i =idx,j;
         if(i>= lstCnt.size())
             i = lstCnt.size() - 1;
         j =i - 4;

         for(;i>=0 &&i>j;--i){
             nms = lstCnt[i] / 10;
             int nnms;
             if(i>0)
                 nnms = (lstCnt[i] - lstCnt[i-1]) / 10;
             str.sprintf("%02d      %02d:%02d.%02d      %02d:%02d.%02d",
                         i + 1, nms / 6000,(nms /100) % 60,nms % 100, nnms /6000 ,(nnms /100)%60,nnms % 100);
             qp.drawText(t,Qt::AlignTop | Qt::AlignHCenter,str);
             t.translate(0, size /10);
         }
      }

      qp.setFont(QFont("Arial",size/15));
      qp.setPen(Qt::red);
      int hh = size / 10;
      rcLeft  = QRect(rc.left(), rc.bottom()-hh*2, rc.width()/2, hh);
      rcRight = QRect(rc.width()/2, rc.bottom()-hh*2,rc.width()/2,hh);
      rcBottom = QRect(rc.left(),rc.bottom()-hh*2,rc.width(),hh);

      switch(state){
      default:
          qp.drawText(rcBottom,Qt::AlignCenter,"開始");
          break;
      case 1:
          qp.drawText(rcLeft,Qt::AlignCenter,"暫停");
          qp.setPen(Qt::blue);
          qp.drawText(rcRight, Qt::AlignCenter,"計次");
          break;
      case 2:
          qp.drawText(rcLeft,Qt::AlignCenter,"繼續");
          qp.setPen(Qt::blue);
          qp.drawText(rcRight,Qt::AlignCenter,"重置");
          break;
      }
}

void Dialog::mousePressEvent(QMouseEvent *e)
{
    if(Qt::LeftButton == e->button()){
        switch(state){
        default:
            if(rcBottom.contains(e->pos())){
                nMSCnt = 0;
                sTime = QTime::currentTime();
                state = 1;
            }
        break;
        case 1:
            if(rcLeft.contains(e->pos())){
                state = 2;
                nMSCnt +=sTime.msecsTo(QTime::currentTime());
                update();
            }
            else if(rcRight.contains(e->pos())){
                  lstCnt.append(nMSCnt + sTime.msecsTo(QTime::currentTime()));
                  idx = lstCnt.size() - 1;
                  update();
            }
            break;
        case 2:
            if(rcLeft.contains(e->pos())){
                state = 1;
                sTime = QTime::currentTime();
            }
            else if(rcRight.contains(e->pos())){
                state = 0;
                nMSCnt = 0;
                lstCnt.clear();
                update();
            }
            break;
        }
    }
}


void Dialog::wheelEvent(QWheelEvent *e)
{
     if(e->delta() >0){
         if(idx < lstCnt.size() -1){
             ++idx;
             update();
         }
     }
      else {
         if(idx>0){
             --idx;
             update();
         }
    }
}

(2)main.cpp

#include "dialog.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.show();

    return a.exec();
}

(3)規定介面,在ui介面設定裡面(這裡我只是簡單的設計成正方形,節省時間,需要別的設計,或者探討,可以加我QQ或者vx)

七、編譯演示。

(1)如果你工程很多,需要將你要演示的調變成活動專案,如下圖所示;

(2)編譯 -> 執行 -> 結果顯示

剛才就說過了,介面設定你除了手動畫,還可以在這個函數裡面進行新增,如下圖所示;

廢話不多說,看演示結果;

點選開始,開始計數;

點選計次,開始加次數;

暫停 -> 重置 重置之後回到清零狀態;

另:看完了這個大家也可以試著設計自己手機中秒錶的介面,亦或是下圖的計時器,原理異曲同工,大家可以試著呼叫video相關函數,通過滑鼠點選函數去實現聲音大小的控制。

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


IT145.com E-mail:sddin#qq.com