文章目录

  • 1 效果预览
  • 2 加载背景图片
  • 3 尺子可拉动头部的实现
  • 4 整个尺子部分的实现
  • 5 表盘的实现
  • 6 主界面代码实现

1 效果预览

我们首先来看下实现的效果:

右边的表带拉动会使左边的表盘跟随转动,停止后会开启倒计时。


2 加载背景图片

先来看下工程目录:

直接绘制背景即可,比较简单,实现代码如下:

ccwindowwidget.h:

#ifndef CCWINDOWWIDGET_H
#define CCWINDOWWIDGET_H#include <QWidget>class CCWindowWidget : public QWidget
{public:explicit CCWindowWidget(QWidget* parent = 0);~CCWindowWidget();void paintEvent(QPaintEvent *event);
};#endif // CCWINDOWWIDGET_H

ccwindowwidget.cpp:

#include "ccwindowwidget.h"
#include <QPainter>
#include <QDebug>
#include <QDesktopWidget>
#include <QApplication>#define LANUNCHER_WIDTH 436
#define LANUCHER_HEIGHT 775CCWindowWidget::CCWindowWidget(QWidget* parent) : QWidget(parent)
{setAutoFillBackground(true);setMaximumSize(LANUNCHER_WIDTH, LANUCHER_HEIGHT);setMinimumSize(LANUNCHER_WIDTH, LANUCHER_HEIGHT);setWindowFlags(windowFlags() & ~Qt::WindowMinMaxButtonsHint);QDesktopWidget* desktop = QApplication::desktop();int startX = (desktop->width() - LANUNCHER_WIDTH) / 2;int startY = (desktop->height() - LANUCHER_HEIGHT) / 2;setGeometry(startX, startY, LANUNCHER_WIDTH, LANUCHER_HEIGHT);
}CCWindowWidget::~CCWindowWidget()
{}void CCWindowWidget::paintEvent(QPaintEvent *event)
{QPainter painter(this);painter.save();painter.drawPixmap(rect(), QPixmap(":/res/images/background.png"));painter.restore();
}

3 尺子可拉动头部的实现


这里的要点就是当被拉动时,需要发送信号给父部件,让父部件及时感知,并做出相关调整。

相关代码如下:

ccrulerheader.h:

#ifndef QRULERHEADER_H
#define QRULERHEADER_H#include <QWidget>
#include <QPushButton>
#include <QMouseEvent>class CCRulerHeader:public QWidget
{Q_OBJECT
public:explicit CCRulerHeader(QWidget* parent=0);virtual ~CCRulerHeader();private:QPoint      last_mouse_position;signals:void  rulerHeaderMoveSignal(int posY);void  rulerHeaderMoveDoneSignal();protected:void mousePressEvent(QMouseEvent* event);void mouseMoveEvent(QMouseEvent* event);void mouseReleaseEvent(QMouseEvent* event);void paintEvent(QPaintEvent* event);
};#endif // QRULERHEADER_H

ccrulerheader.cpp如下:

#include "ccrulerheader.h"
#include <QPainter>
#include <QDebug>#define RULERHEADER_WIDTH  82
#define RULERHEADER_HEIGHT 91CCRulerHeader::CCRulerHeader(QWidget* parent):QWidget(parent)
{setGeometry(0,0,RULERHEADER_WIDTH,RULERHEADER_HEIGHT);setStyleSheet("border-image:url(:/images/ImageResources/ruler_head.png)" );
}
CCRulerHeader::~CCRulerHeader()
{}
void CCRulerHeader::mousePressEvent(QMouseEvent* event)
{if (event->button() == Qt::LeftButton){last_mouse_position = event->globalPos();}
}void CCRulerHeader::mouseMoveEvent(QMouseEvent* event)
{if (event->buttons() & Qt::LeftButton){const QPoint position =  event->globalPos() - last_mouse_position;//qDebug()<<"POSY:"<<last_mouse_position<<""<<event->globalPos()<<" "<< position;emit rulerHeaderMoveSignal(position.y());}
}void CCRulerHeader::mouseReleaseEvent(QMouseEvent* event)
{Q_UNUSED(event);emit rulerHeaderMoveDoneSignal();
}
void CCRulerHeader::paintEvent(QPaintEvent* event)
{Q_UNUSED(event);QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing, true);painter.save();painter.drawPixmap(rect(),QPixmap(":/images/ImageResources/ruler_head.png"));painter.restore();}

这里我们需要注意的一点是:当我们要实现控件移动时一定要使用globalPos函数,千万不要使用pos函数,一旦涉及到移动我就要以桌面左上角为参考点来移动,而不是所激活的窗口!


4 整个尺子部分的实现

ccstrechruler.h:

#ifndef QSTRECHRULER_H
#define QSTRECHRULER_H#include <QWidget>class CCRulerHeader;class CCStrechRuler : public QWidget
{Q_OBJECT
public:explicit CCStrechRuler(QWidget *parent = 0);virtual ~CCStrechRuler();void  UpdateRulerHeight(float aValue);void SetRulerReset();private:CCRulerHeader*   m_pRulerHeader;QPoint          m_originalPosition;int             m_currentPosY;signals:void  rulerStrechSignal(float value);void  rulerStrechDoneSignal(float value);private slots:void OnRulerHeadMove(int moveValue);void OnRulerHeadMoveDone();protected:void paintEvent(QPaintEvent* event);
};#endif // QSTRECHRULER_H

ccstrechruler.cpp:

#include "ccstrechruler.h"
#include "ccrulerheader.h"#include <QDebug>
#include <QPainter>#define RULERWIDGET_STARTX 351
#define RULERWIDGET_STARTY 100#define RULERWIDGET_WIDTH  82
#define RULERWIDGET_HEIGHT 574#define RULER_MAX_HEIGHT 486CCStrechRuler::CCStrechRuler(QWidget *parent) : QWidget(parent)
{setGeometry(RULERWIDGET_STARTX,RULERWIDGET_STARTY,RULERWIDGET_WIDTH,RULERWIDGET_HEIGHT);//setAttribute(Qt::WA_TranslucentBackground);setStyleSheet("background-color: rgba(0,0,0,0)");
//    QPalette palette;
//    palette.setColor(QPalette::Background, Qt::green);
//    setPalette(palette);m_pRulerHeader = new CCRulerHeader(this);connect(m_pRulerHeader,SIGNAL(rulerHeaderMoveSignal(int)),SLOT(OnRulerHeadMove(int)));connect(m_pRulerHeader,SIGNAL(rulerHeaderMoveDoneSignal()),SLOT(OnRulerHeadMoveDone()));m_originalPosition=m_pRulerHeader->pos();m_currentPosY = m_originalPosition.ry();
}
CCStrechRuler::~CCStrechRuler()
{}
void  CCStrechRuler::UpdateRulerHeight(float aValue)
{//qDebug()<<"CurrentRatio"<<aValue<<endl;int currentY =  aValue *RULER_MAX_HEIGHT;m_pRulerHeader->move(m_originalPosition.rx(),currentY);repaint();
}void CCStrechRuler::SetRulerReset()
{m_pRulerHeader->move(m_originalPosition.rx(),0);m_currentPosY =0;repaint();
}void CCStrechRuler::OnRulerHeadMove(int aValue)
{if(m_pRulerHeader == NULL){return;}int realPosY= m_currentPosY + aValue;if((realPosY <= RULER_MAX_HEIGHT) && (realPosY >= 0)){m_pRulerHeader->move(m_originalPosition.rx(),realPosY);}//qDebug()<<"POSY:"<<m_pRulerHeader->pos().y()<<" "<<aValue<<" " <<realPosY;float dialRatio = m_pRulerHeader->pos().y() / 486.0;emit rulerStrechSignal(dialRatio);repaint();}void CCStrechRuler::OnRulerHeadMoveDone()
{m_currentPosY=m_pRulerHeader->pos().y();float dialRatio = m_pRulerHeader->pos().y() / 486.0;emit rulerStrechDoneSignal(dialRatio);
}void CCStrechRuler::paintEvent(QPaintEvent* event)
{Q_UNUSED(event);QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing, true);painter.save();painter.setPen(QPen(QColor(127, 159, 124), 1));painter.setBrush(QColor(127, 159, 124));painter.drawRect(15, 3, 52, m_pRulerHeader->pos().y());painter.restore();int lScale =25;int sScale= 5;int currentRulerHeight=m_pRulerHeader->pos().y();int sScale_count = currentRulerHeight / sScale +1;int lScale_count = currentRulerHeight / lScale +1;painter.setPen(QPen(QColor(255, 255, 255),1));for(int i=0; i< sScale_count; i++){if( i % 5 != 0){painter.drawLine(QPointF(67-5, 5*i), QPointF(67, 5*i));}}for(int i=0; i< lScale_count; i++){painter.drawLine(QPointF(67-10, 25*i), QPointF(67, 25*i));}}

5 表盘的实现

ccdialclock.h:

#ifndef CCDIALCLOCK_H
#define CCDIALCLOCK_H#include <QWidget>class CCDialClock : public QWidget
{Q_OBJECT
public:explicit CCDialClock(QWidget *parent = 0);virtual ~CCDialClock();public slots:void  SetupClockTime(float value);protected:void paintEvent(QPaintEvent* event);private:float   m_rotateValue;
};#endif // CCDIALCLOCK_H

ccdialclock.cpp:

#include "ccdialclock.h"
#include <QPainter>
#include <QDebug>#define DIALCLOCK_STARTX 75
#define DIALCLOCK_STARTY 188
#define DIALCLOCK_WIDTH  285
#define DIALCLOCK_HEIGHT 285#define NEEDLE_WIDTH  26
#define NEEDLE_HEIGHT 90CCDialClock::CCDialClock(QWidget *parent) : QWidget(parent)
{setGeometry(DIALCLOCK_STARTX,DIALCLOCK_STARTY,DIALCLOCK_WIDTH,DIALCLOCK_HEIGHT);setStyleSheet("background-color: rgba(0,0,0,0)");m_rotateValue = 0.0;
}
CCDialClock::~CCDialClock()
{}
void CCDialClock::SetupClockTime(float aValue)
{m_rotateValue = 360 * aValue;//qDebug()<<"VALUE:"<<m_rotateValue;repaint();
}void CCDialClock::paintEvent(QPaintEvent* event)
{Q_UNUSED(event);QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing, true);painter.setRenderHint(QPainter::SmoothPixmapTransform, true);painter.drawPixmap(rect(),QPixmap(":/images/ImageResources/dial.png"));painter.save();painter.translate(width()/2,height()/2);painter.rotate(m_rotateValue);painter.drawPixmap(-13,-78,NEEDLE_WIDTH,NEEDLE_HEIGHT,QPixmap(":/images/ImageResources/needle.png"));painter.restore();
}

6 主界面代码实现

ccwindowwidget.h:

#ifndef CCWINDOWWIDGET_H
#define CCWINDOWWIDGET_H#include <QWidget>
#include <QMouseEvent>
#include <QPushButton>
#include <QLabel>
#include <QTimer>class CCStrechRuler;
class CCDialClock;class CCWindowWidget : public QWidget
{Q_OBJECT
public:explicit CCWindowWidget(QWidget *parent = 0);virtual ~CCWindowWidget();private:void loadFrontWidgets();QString caculateFormatTimeWithSeconds(int aSeconds);private:QPoint          last_mouse_position;CCStrechRuler   *m_pStretchRuler;CCDialClock     *m_pDialClock;QPushButton     *m_pPlayButton;QPushButton     *m_pResetButton;QLabel          *m_pTimeLabel;int             m_nRulerSettedSeconds;QTimer          *m_pCountDownTimer;bool            m_bTimerPlaying;private slots:void OnPlayButtonClicked();void OnResetButtonClicked();void OnRulerStrechDone(float aValue);void OnCountDownTimerProcess();protected:void paintEvent(QPaintEvent* event);
};#endif // CCWINDOWWIDGET_H

ccwindowwidget.h:

#include <QDesktopWidget>
#include <QApplication>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QPainter>
#include <QDebug>
#include <cstdlib>
#include <QTime>#include "ccwindowwidget.h"
#include "ccstrechruler.h"
#include "ccdialclock.h"#define LANCHERWIDGET_WIDTH  436
#define LANCHERWIDGET_HEIGHT 775#define TOOLBUTTON_WIDTH    75
#define TOOLBUTTON_HEIGHT   75CCWindowWidget::CCWindowWidget(QWidget *parent) : QWidget(parent)
{setWindowFlags(windowFlags() & ~Qt::WindowMinMaxButtonsHint);setMinimumSize(LANCHERWIDGET_WIDTH ,LANCHERWIDGET_HEIGHT);setMaximumSize(LANCHERWIDGET_WIDTH ,LANCHERWIDGET_HEIGHT);setAutoFillBackground(true);setAttribute(Qt::WA_TranslucentBackground);QDesktopWidget *deskdop = QApplication::desktop();int startX = (deskdop->width() - LANCHERWIDGET_WIDTH)/2;int startY = (deskdop->height() - LANCHERWIDGET_HEIGHT)/2;setGeometry(startX, startY,LANCHERWIDGET_WIDTH,LANCHERWIDGET_HEIGHT);m_nRulerSettedSeconds =0;m_bTimerPlaying = false;loadFrontWidgets();m_pCountDownTimer= new QTimer(this);connect(m_pCountDownTimer,SIGNAL(timeout()),this,SLOT(OnCountDownTimerProcess()));}
CCWindowWidget::~CCWindowWidget()
{if(m_pStretchRuler != NULL){delete m_pStretchRuler;m_pStretchRuler = NULL;}if(m_pDialClock != NULL){delete m_pDialClock;m_pDialClock = NULL;}
}void CCWindowWidget::loadFrontWidgets()
{m_pStretchRuler = new CCStrechRuler(this);m_pDialClock = new CCDialClock(this);connect(m_pStretchRuler,SIGNAL(rulerStrechSignal(float)),m_pDialClock,SLOT(SetupClockTime(float)));connect(m_pStretchRuler,SIGNAL(rulerStrechDoneSignal(float)),this,SLOT(OnRulerStrechDone(float)));QFont font;font.setFamily("PingFang TC");font.setWeight(25);font.setPixelSize(35);m_pTimeLabel = new QLabel(this);m_pTimeLabel->setGeometry(138,525,160,60);m_pTimeLabel->setFont(font);m_pTimeLabel->setStyleSheet("background: transparent;color:#d16b5d");m_pTimeLabel->setAlignment(Qt::AlignCenter);m_pTimeLabel->setText("00:00");m_pPlayButton = new QPushButton(this);m_pPlayButton->setGeometry(111,630,TOOLBUTTON_WIDTH,TOOLBUTTON_WIDTH);m_pPlayButton->setIcon(QIcon(":/images/ImageResources/play.png"));m_pPlayButton->setIconSize(QSize(TOOLBUTTON_WIDTH, TOOLBUTTON_HEIGHT));m_pPlayButton->setAutoFillBackground(true);m_pPlayButton->setFlat( true );m_pPlayButton->setStyleSheet("QPushButton{background: transparent;}");connect(m_pPlayButton,SIGNAL(clicked(bool)),SLOT(OnPlayButtonClicked()));m_pResetButton = new QPushButton(this);m_pResetButton->setGeometry(251,630,TOOLBUTTON_WIDTH,TOOLBUTTON_WIDTH);m_pResetButton->setIcon(QIcon(":/images/ImageResources/reset.png"));m_pResetButton->setIconSize(QSize(TOOLBUTTON_WIDTH, TOOLBUTTON_HEIGHT));m_pResetButton->setAutoFillBackground(true);m_pResetButton->setFlat( true );m_pResetButton->setStyleSheet("QPushButton{background: transparent;}");connect(m_pResetButton,SIGNAL(clicked(bool)),SLOT(OnResetButtonClicked()));}void CCWindowWidget::OnRulerStrechDone(float aValue)
{if(aValue >= 1.0 ){aValue = 0.9999;}int mSeconds = (int)3600*aValue;QString formatTime= caculateFormatTimeWithSeconds(mSeconds);m_pTimeLabel->setText(formatTime);m_nRulerSettedSeconds = mSeconds;if(m_pCountDownTimer->isActive()){m_pCountDownTimer->stop();m_bTimerPlaying = false;}m_pCountDownTimer->start(1000);m_bTimerPlaying = true;m_pPlayButton->setIcon(QIcon(":/images/ImageResources/pause.png"));}QString CCWindowWidget::caculateFormatTimeWithSeconds(int aSeconds)
{int tMinutes = aSeconds / 60;int tSeconds = aSeconds - tMinutes* 60;QString strMinutes = QString("%1").arg(tMinutes);QString strSeconds = QString("%1").arg(tSeconds);if((tMinutes <10) && (tMinutes >=0)){strMinutes = QString("0%1").arg(tMinutes);}if((tSeconds <10) && (tSeconds >=0)){strSeconds = QString("0%1").arg(tSeconds);}QString formatTime = QString("%1:%2").arg(strMinutes).arg(strSeconds);return formatTime;
}void CCWindowWidget::OnCountDownTimerProcess()
{if(m_nRulerSettedSeconds <=0){OnResetButtonClicked();}QString formatTime= caculateFormatTimeWithSeconds(m_nRulerSettedSeconds);m_pTimeLabel->setText(formatTime);float currentRatio = m_nRulerSettedSeconds /3600.0;m_pStretchRuler->UpdateRulerHeight(currentRatio);m_nRulerSettedSeconds--;}void CCWindowWidget::OnPlayButtonClicked()
{if(m_bTimerPlaying == true){if(m_pCountDownTimer->isActive()){m_pCountDownTimer->stop();m_bTimerPlaying = false;}m_pPlayButton->setIcon(QIcon(":/images/ImageResources/play.png"));}else{m_pCountDownTimer->start(1000);m_bTimerPlaying = true;m_pPlayButton->setIcon(QIcon(":/images/ImageResources/pause.png"));}}void CCWindowWidget::OnResetButtonClicked()
{if(m_bTimerPlaying == true){if(m_pCountDownTimer->isActive()){m_pCountDownTimer->stop();}}m_pPlayButton->setIcon(QIcon(":/images/ImageResources/play.png"));m_bTimerPlaying = false;m_nRulerSettedSeconds =0;m_pTimeLabel->setText("00:00");m_pDialClock->SetupClockTime(0.0);m_pStretchRuler->SetRulerReset();}void CCWindowWidget::paintEvent(QPaintEvent* event)
{Q_UNUSED(event);QPainter p(this);p.save();p.drawPixmap(rect(),QPixmap(":/images/ImageResources/background.png"));p.restore();}

main.cpp:

#include <QApplication>
#include "ccwindowwidget.h"int main(int argc, char *argv[])
{QApplication a(argc, argv);CCWindowWidget windowWidget;windowWidget.show();return a.exec();
}

总结:如果是不同对象之间的消息传递我们使用信号与槽即可,如果是父子对象之间的消息传递,子对象向父对象传递消息,我们使用信号与槽,而父对象向子对象传递消息我们直接使用函数即可!

QT自定义控件之倒计时控件相关推荐

  1. Android自定义控件之3D上下翻页效果的倒计时控件

    这是一个自定义的倒计时控件,具有3D上下翻页翻转效果.最近项目中需要做一个倒计时控件,需要和iOS端的效果保持一样.大致效果是这样的,如下图所示: 由于暂时还不会怎么样制作gif动态图,所以想看具体效 ...

  2. Android之打造可定制的全场秒杀倒计时控件

    转载请标明出处: http://blog.csdn.net/hai_qing_xu_kong/article/details/51005062 本文出自:[顾林海的博客] ##前言 这几天翻看之前写的 ...

  3. WPF 实现3D翻转倒计时控件~

    WPF开发者QQ群: 340500857       由于微信群人数太多入群请添加小编微信号  yanjinhuawechat 或 W_Feng_aiQ 邀请入群 需备注WPF开发者  PS:有更好的 ...

  4. java 用户控件_C#自定义控件VS用户控件

    C#中自定义控件VS用户控件大比拼 1 自定义控件与用户控件区别 WinForm中, 用户控件(User Control):继承自 UserControl,主要用于开发 Container 控件,Co ...

  5. android中倒计时控件CountDownTimer分析

    android中倒计时控件CountDownTimer分析1 示例代码 new CountDownTimer(10000, 1000) {public void onTick(long millisU ...

  6. android 一分钟倒计时动画,Android利用属性动画自定义倒计时控件

    本文介绍一下利用属性动画(未使用Timer,通过动画执行次数控制倒计时)自定义一个圆形倒计时控件,比较简陋,仅做示例使用,如有需要,您可自行修改以满足您的需求.控件中所使用的素材及配色均是笔者随意选择 ...

  7. Android开发技巧——自定义控件之组合控件

    Android开发技巧--自定义控件之组合控件 我准备在接下来一段时间,写一系列有关Android自定义控件的博客,包括如何进行各种自定义,并分享一下我所知道的其中的技巧,注意点等. 还是那句老话,尽 ...

  8. VS+QT开发Ocx/ActiveX控件 一

    VS+QT开发Ocx/ActiveX控件 一 VS+QT开发Ocx/ActiveX控件-------网页中全屏 二 QT开发ActiveX控件 一:所用IDE版本,需用管理员权限 二:创建Active ...

  9. Qt开发Activex笔记(二):Qt调用Qt开发的Activex控件

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/113789693 长期持续带来更多项目与技术分 ...

最新文章

  1. CVPR2020论文点评: AdderNet(加法网络)
  2. php打印出来乱码_PHP输出中文乱码的解决方法(转载)
  3. 剑指offer:从上往下打印二叉树
  4. Android的单位px,pt,dp,sp总结和获取屏幕分辨率
  5. 威佐夫博弈:百练OJ:1067:取石子游戏
  6. CSS图片水平垂直居中
  7. OpenCV搜索文件夹中的图片并保存图片路径和信息
  8. 智能优化算法:平衡优化器算法 -附代码
  9. 解决XCode 11 build error 编译错误 image not found
  10. 使用原配的SSD安装和引导DSM5.2 5644 基于zmouse和Formater教程
  11. canon iPF 系列保养墨盒清零方法
  12. 计算机组装小游戏,电脑组装店游戏
  13. matlab模糊控制侧方位泊车
  14. 如何打开注册表编辑器
  15. Java se-画出坦克
  16. 重新认识企业数智化!
  17. Long源码与常见问题
  18. 项目经理产品经理必看,流程图绘制Drawio
  19. 导入EXCEL报错:外部表不是预期的格式错误、文件格式和扩展名不匹配,文件可能已损坏或不安全的解决方法
  20. win7环境下安装ubuntu双系统

热门文章

  1. python内置变量__complex___Python 内置方法
  2. 【控制】《多无人机协同控制技术》周伟老师-第9章-单无人机目标跟踪飞行控制策略
  3. 1.9 可避免误差-深度学习第三课《结构化机器学习项目》-Stanford吴恩达教授
  4. 源码里查看Android版本
  5. 资本主义的历史仍未终结(作者:袁剑)【转】
  6. Python之路(第三十八篇) 并发编程:进程同步锁/互斥锁、信号量、事件、队列、生产者消费者模型...
  7. 梓益C语言学习笔记之链表&动态内存&文件
  8. msm(CentOS 6)及jvm虚拟机性能监控(04)_recv
  9. mysql awr v1.0.1发布
  10. 【流量劫持】躲避 HSTS 的 HTTPS 劫持