用基础图形做一个钟表

用基础图形做一个钟表

简述

利用Qpainter可以画出一些简单的图形,再将这些简单的图形组合,配合一些其他的函数和事件,就能实现一个基础的钟表。

效果图

在这里插入图片描述

代码实现

  1. 设置背景图片(此步骤可以省略,根据需要添加)
//设置背景图片
    QPixmap map(":/rec/1_13.png");
    QRect q(0,0,1892,990);
    QRect q2(0,0,width(),height());
    painter.drawPixmap(q2,map,q);
  1. 设置窗口名称和图标
    setWindowTitle("clock");//窗口名称
    setWindowIcon(QIcon((":/rec/zhong.png")));//窗口图标
  1. 设置定时器,时间间隔为1000毫秒,并且将定时器时间与update函数关联为信号和槽,定时器每隔1秒发送一个信号,update接到信号后自动调用paintEvent事件。
    QTimer *timer1 = new QTimer(this);
    connect(timer1, SIGNAL(timeout()), this, SLOT(update()));
    timer1->start(1000);

4.绘制时针分针秒针的形状

    // 时针、分针、秒针 - 多边形
    static const QPoint hourHand[3] = {
        QPoint(3, 8),
        QPoint(-3, 8),
        QPoint(0, -40)
    };


    static const QPoint minuteHand[3] = {
        QPoint(3, 8),
        QPoint(-3, 8),
        QPoint(0, -65)
    };


    static const QPoint secondHand[3] = {
        QPoint(3, 8),
        QPoint(-3, 8),
        QPoint(0, -80)
    };

5.设置颜色(此步骤可以省略,根据需要添加)

 	QColor hourColor(130,57,53, 200);
   	QColor minuteColor(0, 127, 127, 150);
        QColor secondColor(0, 160, 230, 150);

6.获取系统时间,平移坐标系

 	QTime time = QTime::currentTime();//获取系统时间
        painter.setRenderHint(QPainter::Antialiasing);
        painter.translate(width() / 2, height() / 2);// 平移坐标系原点至中心点
        painter.scale(qMin(width(), height())/ 200.0, qMin(width(), height())/ 200.0); // 缩放
        painter.drawEllipse(-96,-96,192,192);//画制边框圆

7.绘制时针和时刻度线

     // 绘制时针
        painter.setPen(Qt::NoPen);
        painter.setBrush(hourColor);
        painter.save();
        painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0)));
        painter.drawConvexPolygon(hourHand, 3);
        painter.restore();
        painter.setPen(hourColor);
            // 绘制时刻度线
        for (int i = 0; i < 12; ++i)
        {
            painter.drawLine(88, 0, 96, 0);
            painter.rotate(30.0);
        }
        QFont font = painter.font();
        font.setBold(true);
        painter.setFont(font);

8.绘制小时文本
预先设置的接口:

QRectF Widget::textRectF(double radius, int pointSize, double angle)
{
    QRectF rectF;
    rectF.setX(radius*cos(angle*M_PI/180.0) - pointSize*2);
    rectF.setY(radius*sin(angle*M_PI/180.0) - pointSize/2.0);
    rectF.setWidth(pointSize*4);
    rectF.setHeight(pointSize*1.2);
    return rectF;
}
 // 绘制小时文本
        int radius = 100;
        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));
         }

9.绘制分针和分针刻度线

  // 绘制分针
        painter.setPen(Qt::NoPen);
        painter.setBrush(minuteColor);
        painter.save();
        painter.rotate(6.0 * (time.minute() + time.second() / 60.0));
        painter.drawConvexPolygon(minuteHand, 3);
        painter.restore();
        painter.setPen(minuteColor);
            // 绘制分钟刻度线 
        for (int j = 0; j < 60; ++j)
        {
            if ((j % 5) != 0)
                painter.drawLine(92, 0, 96, 0);
            painter.rotate(6.0);
        }

10.绘制秒针

// 绘制秒针
        painter.setPen(Qt::NoPen);
        painter.setBrush(secondColor);
        painter.save();
        painter.rotate(6.0 * time.second());
        painter.drawConvexPolygon(secondHand, 3);
        painter.restore();

源代码

头文件

#ifndef CLOCK_H
#define CLOCK_H
#include <QWidget>


QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE


class Widget : public QWidget
{
    Q_OBJECT


public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    QRectF textRectF(double radius, int pointSize, double angle);
    void paintEvent(QPaintEvent *event);
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

cpp文件

#include "widget.h"
#include "ui_widget.h"
#include <QTimer>
#include <QTime>
#include <QPainter>
#include <QFont>
#include <QPixmap>
#include <QIcon>
#define M_PI 3.1415926535898
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    setWindowTitle("clock");
    setWindowIcon(QIcon((":/rec/zhong.png")));//窗口图标
    QTimer *timer1 = new QTimer(this);
    connect(timer1, SIGNAL(timeout()), this, SLOT(update()));
    timer1->start(1000);
}
Widget::~Widget()
{
    delete ui;
}
QRectF Widget::textRectF(double radius, int pointSize, double angle)
{
    QRectF rectF;
    rectF.setX(radius*cos(angle*M_PI/180.0) - pointSize*2);
    rectF.setY(radius*sin(angle*M_PI/180.0) - pointSize/2.0);
    rectF.setWidth(pointSize*4);
    rectF.setHeight(pointSize*1.2);
    return rectF;
}
void Widget::paintEvent(QPaintEvent *event)
{
 // 时针、分针、秒针 - 多边形
    static const QPoint hourHand[3] = {
        QPoint(3, 8),
        QPoint(-3, 8),
        QPoint(0, -40)
    };


    static const QPoint minuteHand[3] = {
        QPoint(3, 8),
        QPoint(-3, 8),
        QPoint(0, -65)
    };


    static const QPoint secondHand[3] = {
        QPoint(3, 8),
        QPoint(-3, 8),
        QPoint(0, -80)
    };
    QColor hourColor(130,57,53, 200);
    QColor minuteColor(0, 127, 127, 150);
    QColor secondColor(0, 160, 230, 150);
    QTime time = QTime::currentTime();//获取系统时间
    painter.setRenderHint(QPainter::Antialiasing);
    painter.translate(width() / 2, height() / 2);// 平移坐标系原点至中心点
    painter.scale(qMin(width(), height())/ 200.0, qMin(width(), height())/ 200.0); // 缩放
    painter.drawEllipse(-96,-96,192,192);//画制边框圆
     // 绘制时针
    painter.setPen(Qt::NoPen);
    painter.setBrush(hourColor);
    painter.save();
    painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0)));
    painter.drawConvexPolygon(hourHand, 3);
    painter.restore();
    painter.setPen(hourColor);
            // 绘制时刻度线
    for (int i = 0; i < 12; ++i)
    {
        painter.drawLine(88, 0, 96, 0);
        painter.rotate(30.0);
     }
     QFont font = painter.font();
     font.setBold(true);
     painter.setFont(font);
     // 绘制小时文本
     int radius = 100;
     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();
     painter.rotate(6.0 * (time.minute() + time.second() / 60.0));
     painter.drawConvexPolygon(minuteHand, 3);
     painter.restore();
     painter.setPen(minuteColor);
            // 绘制分钟刻度线
     for (int j = 0; j < 60; ++j)
     {
     	if ((j % 5) != 0)
        	painter.drawLine(92, 0, 96, 0);
        painter.rotate(6.0);
     }
            // 绘制秒针
     painter.setPen(Qt::NoPen);
     painter.setBrush(secondColor);
     painter.save();
     painter.rotate(6.0 * time.second());
     painter.drawConvexPolygon(secondHand, 3);
     painter.restore();
}
用MFC VC++实现的时钟源代码 // MFCFrame1View.cpp : implementation of the CMFCFrame1View class // #include "stdafx.h" #include "MFCFrame1.h" #include "MFCFrame1Doc.h" #include "MFCFrame1View.h" #include "PointDialog.h" #include "math.h" GLUquadricObj *objCylinder = gluNewQuadric(); #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CMFCFrame1View IMPLEMENT_DYNCREATE(CMFCFrame1View, CView) BEGIN_MESSAGE_MAP(CMFCFrame1View, CView) //{{AFX_MSG_MAP(CMFCFrame1View) ON_WM_CREATE() ON_WM_DESTROY() ON_WM_SIZE() ON_COMMAND(IDM_ZIXUAN, OnZixuan) ON_WM_TIMER() ON_COMMAND(IDM_ChangDirect, OnChangDirect) //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMFCFrame1View construction/destruction CMFCFrame1View::CMFCFrame1View() { // TODO: add construction code here this->m_GLPixelIndex = 0; this->m_hGLContext = NULL; Angle1=0.0; Angle2=30.0; Timer=0; x=0.0; z=0.0; juli=40.0; } CMFCFrame1View::~CMFCFrame1View() { } BOOL CMFCFrame1View::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs cs.style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS); return CView::PreCreateWindow(cs); } ///////////////////////////////////////////////////////////////////////////// // CMFCFrame1View drawing ///////////////////////////////////////////////////////////////////////////// // CMFCFrame1View printing BOOL CMFCFrame1View::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); } void CMFCFrame1View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add extra initialization before printing } void CMFCFrame1View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add cleanup after printing } ///////////////////////////////////////////////////////////////////////////// // CMFCFrame1View diagnostics #ifdef _DEBUG void CMFCFrame1View::AssertValid() const { CView::AssertValid(); } void CMFCFrame1View::Dump(CDumpContext& dc) const { CView::Dump(dc); } CMFCFrame1Doc* CMFCFrame1View::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFCFrame1Doc))); return (CMFCFrame1Doc*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CMFCFrame1View message handlers BOOL CMFCFrame1View::SetWindowPixelFormat(HDC hDC) { PIXELFORMATDESCRIPTOR pixelDesc= { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| PFD_DOUBLEBUFFER|PFD_SUPPORT_GDI, PFD_TYPE_RGBA, 24, 0,0,0,0,0,0, 0, 0, 0, 0,0,0,0, 32, 0, 0, PFD_MAIN_PLANE, 0, 0,0,0 }; this->m_GLPixelIndex = ChoosePixelFormat(hDC,&pixelDesc); if(this->m_GLPixelIndex==0) { this->m_GLPixelIndex = 1; if(DescribePixelFormat(hDC,this->m_GLPixelIndex,sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc)==0) { return FALSE; } } if(SetPixelFormat(hDC,this->m_GLPixelIndex,&pixelDesc)==FALSE) { return FALSE; } return TRUE; } int CMFCFrame1View::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; // TODO: Add your specialized creation code here HWND hWnd = this->GetSafeHwnd(); HDC hDC = ::GetDC(hWnd); if(this->SetWindowPixelFormat(hDC)==FALSE) { return 0; } if(this->CreateViewGLContext(hDC)==FALSE) { return 0; } return 0; } BOOL CMFCFrame1View::CreateViewGLContext(HDC hDC) { this->m_hGLContext = wglCreateContext(hDC); if(this->m_hGLContext==NULL) {//创建失败 return FALSE; } if(wglMakeCurrent(hDC,this->m_hGLContext)==FALSE) {//选为当前RC失败 return FALSE; } return TRUE; } void CMFCFrame1View::OnDestroy() { CView::OnDestroy(); // TODO: Add your message handler code here if(wglGetCurrentContext()!=NULL) { wglMakeCurrent(NULL,NULL); } if(this->m_hGLContext!=NULL) { wglDeleteContext(this->m_hGLContext); this->m_hGLContext = NULL; } } void CMFCFrame1View::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); // TODO: Add your message handler code here GLsizei width,height; GLdouble aspect; width = cx; height = cy; if(cy==0) { aspect = (GLdouble)width; } else { aspect = (GLdouble)width/(GLdouble)height; } glViewport(0,0,width,height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(40.0,aspect,5.0,1000.0); } void CMFCFrame1View::OnDraw(CDC* pDC) { CMFCFrame1Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here CPaintDC dc(this); glClearColor(1.0,1.0,1.0,1.0); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0.0,0.0,10.0,0.0,0.0,0.0,0.0,1.0,0.0); glRotatef(-90.0,1.0,0.0,0.0);/*返回原坐标*/ glTranslatef(-3.0,0.0,0.0); SwapBuffers(dc.m_ps.hdc); glDrawBuffer (GL_BACK); glFlush(); } void CMFCFrame1View::OnZixuan() { // TODO: Add your command handler code here Timer=1; SetTimer(1,100,NULL); } void CMFCFrame1View::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default CPaintDC dc(this); if (Timer==1) { Angle1=Angle1-1; Angle2=Angle2-1; glClearColor(1.0,1.0,1.0,1.0); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW);/**/ glLoadIdentity(); gluLookAt(0.0,20.0,0.000000001,0.0,0.0,0.0,0.0,1.0,0.0); glPushMatrix(); glColor3f(0.7,0.7,0.7); glTranslatef(0.0,0.0,1.1); glRotatef(-90.0,1.0,0.0,0.0); glutSolidCone(5.0,0.0,60.0,60.0); /*底盘*/ glPopMatrix(); glPushMatrix(); glColor3f(0.0,0.0,0.0); glTranslatef(3.9,0.99,1.0); /*刻度*/ glRotatef(90.0,0.0,1.0,0.0); gluCylinder(objCylinder, 0.05, 0.05, 0.8, 9999, 9); glPopMatrix(); glPushMatrix(); glColor3f(0.0,0.0,0.0); glTranslatef(-4.7,0.99,1.0); /*刻度*/ glRotatef(90.0,0.0,1.0,0.0); gluCylinder(objCylinder,0.05, 0.05, 0.8, 9999, 9); glPopMatrix(); glPushMatrix(); glColor3f(0.0,0.0,0.0); glTranslatef(0.0,0.99,-2.9); /*刻度*/ glRotatef(180.0,0.0,1.0,0.0); gluCylinder(objCylinder,0.05, 0.05, 0.8, 9999, 9); glPopMatrix(); glPushMatrix(); glColor3f(0.0,0.0,0.0); glTranslatef(0.0,0.99,5.8); /*刻度*/ glRotatef(180.0,0.0,1.0,0.0); gluCylinder(objCylinder,0.05, 0.05,0.8, 9999, 9); glPopMatrix(); glPushMatrix(); glColor3f(0.0,1.0,0.0); glRotatef(45.0,0.0,1.0,0.0); glTranslatef(-0.67,0.99,0.7); /*时针*/ glRotatef(Angle1/129600,0.0,1.0,0.0); gluCylinder(objCylinder, 0.07, 0.02, 2.5, 9999, 9); glPopMatrix(); glPushMatrix(); glColor3f(1.0,0.0,0.0); glTranslatef(0.0,0.99,1.0); /*分针*/ glRotatef(Angle2/360,0.0,1.0,0.0); gluCylinder(objCylinder, 0.05, 0.02, 3.5, 9999, 9); glPopMatrix(); glPushMatrix(); glColor3f(0.0,0.0,0.5); glTranslatef(0.0,0.99,1.0); /*秒针*/ glRotatef(Angle1,0.0,1.0,0.0); gluCylinder(objCylinder, 0.07, 0.02, 4.5, 9999, 9); glPopMatrix(); SwapBuffers(dc.m_ps.hdc); glDrawBuffer (GL_BACK); glFlush(); } else if(Timer==2) { glClearColor(1.0,1.0,1.0,1.0); glClear(GL_COLOR_BUFFER_BIT); if (juli>12.0) { glMatrixMode(GL_MODELVIEW);/*建立了从世界坐标系到观察坐标系的转换矩阵*/ glLoadIdentity(); gluLookAt(0.0,8.0,juli,0.0,0.0,0.0,0.0,1.0,0.0); juli=juli-0.1; glPushMatrix(); glColor3f(0.0,0.0,0.0); glRotatef(-90.0,1.0,0.0,0.0); glutWireCone(40.0,0.0,30.0,30.0); /*画高度为0的圆锥*/ glPopMatrix(); glPushMatrix(); glColor3f(1.0,0.0,1.0); glLineWidth(4.0); glTranslatef(4.0,1.0,0.0); glutWireOctahedron(); /*画八面体*/ glLineWidth(1.0); glPopMatrix(); glPushMatrix(); glColor3f(1.0,0.0,1.0); glTranslatef(0.0,1.1,0.0); glRotatef(Angle2,0.0,1.0,0.0); gluCylinder(objCylinder, 1.0, 1.0, 10.0, 9999, 9); /*画壶*/ glPopMatrix(); } else if(juli<=12.0) { Angle2=Angle2+0.01; if (Angle2==360.0) Angle2=0.0; glMatrixMode(GL_MODELVIEW);/*建立了从世界坐标系到观察坐标系的转换矩阵*/ glLoadIdentity(); x=12.0*sin(Angle2); z=12.0*cos(Angle2); gluLookAt(x,5.0,z,0.0,0.0,0.0,0.0,1.0,0.0); glPushMatrix(); glColor3f(0.0,0.0,0.0); glRotatef(-90.0,1.0,0.0,0.0); glutWireCone(40.0,0.0,30.0,30.0); /*画高度为0的圆锥*/ glPopMatrix(); glPushMatrix(); glColor3f(1.0,0.0,1.0); glLineWidth(4.0); glTranslatef(4.0,1.0,0.0); glutWireOctahedron(); /*画八面体*/ glLineWidth(1.0); glPopMatrix(); glPushMatrix(); glColor3f(1.0,0.0,1.0); glTranslatef(0.0,1.1,0.0); gluCylinder(objCylinder, 1.0, 1.0, 10.0, 9999, 9); /*画壶*/ glPopMatrix(); } SwapBuffers(dc.m_ps.hdc); glDrawBuffer (GL_BACK); glFlush(); } CView::OnTimer(nIDEvent); } void CMFCFrame1View::OnChangDirect() { // TODO: Add your command handler code here Timer=2; SetTimer(1,100 ,NULL); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值