Qt学习笔记9——P30-33. 自定义控件封装,鼠标事件,定时器

发布时间 2023-04-01 16:15:22作者: 我会变强的
  • P30. 自定义控件封装
  • P31. Qt中的鼠标事件
  • P32. 定时器1
  • P33. 定时器2
  • P30. 自定义控件封装(创建了新项目)
  •  添加新的界面和类:右键项目的文件夹(顶层的文件)-> Qt——Qt设计师界面类 -> “选择界面模板”选"Widget" -> 在"Class name"中取个类名(此案例中改成了SmallWidget) -> 别的没什么注意的了,点下一步或完成,其他默认

下面要做的是把“Spin Box”和“Horizontal Slider”封装到一起

先拖一个Spin Box和Horizontal Slider到新添加的ui界面中,调整整个ui的大小和两个控件的位置(水平对齐)

  

切换到主的ui编辑界面中,拖一个“Widget”到界面中,右键此Widget -> 提升为 ->新窗口中的“提升的类名称”中填 一开始添加的在“Class name”中的类名 -> 点“全局包含”(说是可点可不点;作用是方便其他相同的提升),点击“添加” -> 再点击“提升”

(此时新添加的Widget的类名不再是QWidget,而变成了SmallWidget)

下面实现按钮和滑块的同步

(切换到smallwidget.cpp)

1     //QSpinBox移动 QSlider跟着移动
2     //因为valueChanged重载了,需要用函数指针
3     void(QSpinBox:: * spSignal)(int) = &QSpinBox::valueChanged;
4     connect(ui->spinBox,spSignal,ui->horizontalSlider,&QSlider::setValue);
5 
6     //QSlider滑动 QSpinBox数字跟着改变
7     connect(ui->horizontalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);

运行结果:

  

下面实现两个功能:设置数字 和 获取数字

(切换到smallwidget.h,先声明两个函数)

    //设置数字
    void setNum(int num);
    //获取数字
    int getNum();

 

(在smallwidget.cpp中实现上面的函数)

 1 //设置数字
 2 void SmallWidget::setNum(int num)
 3 {
 4     ui->spinBox->setValue(num);
 5 }
 6 //获取数字
 7 int SmallWidget::getNum()
 8 {
 9     return ui->spinBox->value();
10 }

 

(widget.cpp)

1     //点击获取 获取控件当前值
2     connect(ui->btn_get,&QPushButton::clicked,this,[=](){
3         qDebug()<<ui->widget1->getNum();  //widget1是封装的控件的widget变量名;getNum()是刚才在smallwidget.cpp中自己写的函数
4     });
5 
6     //点击设置到一半
7     connect(ui->btn_set,&QPushButton::clicked,this,[=](){
8        ui->widget1->setNum(50);
9     });

  

 

  • P31. Qt中的鼠标事件(创建了新项目)

(将要实现的功能:判断鼠标进入和离开一个区域)

往项目中添加新的类,不需要ui界面:右键项目名称 -> Add New -> 左边选C/C++,中间选“C++ Class”,“Choose” -> “Class name”中取个名字(此案例中为“myLabel”),“Base class”选“QWidget” -> 下一步,完成

(mylabel.h)

1     //鼠标进入事件
2     void enterEvent(QEvent * event);
3     //鼠标离开事件
4     void leaveEvent(QEvent *);

 

(mylabel.cpp)

 1 //鼠标进入事件
 2 void myLabel::enterEvent(QEvent * event)
 3 {
 4     qDebug()<<"鼠标进入了";
 5 }
 6 //鼠标离开事件
 7 void myLabel::leaveEvent(QEvent *)
 8 {
 9     qDebug()<<"鼠标离开了";
10 }

 

(一个因为之前新建错误 而导致现在必要的操作)

在“mylabel.h”中:

#include <QLabel>

把 class myLabel : public QWidget 改成 class myLabel : public QLabel

 

在“mylabel.cpp”中:

把 myLabel::myLabel(QWidget *parent) : QWidget(parent) 改成 myLabel::myLabel(QWidget *parent) : QLabel(parent)

 

往ui编辑界面中拖拽一个"Label",右键 -> 提升为 -> “提升的类的名称”里填“myLabel” -> 添加,提升

  

(因为这个新添加的控件的基类是QLabel,所以提升的类也要是QLabel,所以刚才要把QWidget改成QLabel)

 

  • ui中的Label添加进去之后,不好找,怎么办?:

选中添加进去的Label,右下角“frameShape”可以选“Box”,就有边框了

运行一下:

  

(实现几个其他的鼠标功能)

(mylabel.h)

1     //鼠标按下
2     virtual void mousePressEvent(QMouseEvent *ev);
3     //鼠标释放
4     virtual void mouseReleaseEvent(QMouseEvent *ev);
5     //鼠标移动
6     virtual void mouseMoveEvent(QMouseEvent *ev);

 

(mylabel.cpp)

 1 //鼠标按下
 2 void myLabel::mousePressEvent(QMouseEvent *ev)
 3 {
 4     //当鼠标左键按下 提示信息
 5     if(ev->button() == Qt::LeftButton)
 6     {
 7         //如果没有上面的if,这里的操作鼠标左右键都可以进行
 8         QString str = QString("鼠标按下了 x = %1 y = %2 globalX = %3 globalY = %4" ).arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY()); //%1 和 %2 都是占位的,%1的位置将是ev->x(),%2的位置将是ev->y()
 9         qDebug()<<str;
10     }
11 
12 }
13 //鼠标释放
14 void myLabel::mouseReleaseEvent(QMouseEvent *ev)
15 {
16     if(ev->button() == Qt::LeftButton)
17     {
18         QString str = QString("鼠标释放了 x = %1 y = %2 globalX = %3 globalY = %4" ).arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY()); //%1 和 %2 都是占位的,%1的位置将是ev->x(),%2的位置将是ev->y()
19         qDebug()<<str;
20     }
21 
22 }
23 //鼠标移动
24 void myLabel::mouseMoveEvent(QMouseEvent *ev)
25 {
26     if(ev->buttons() & Qt::LeftButton)  //跟上面的判断不同:1. buttons 2. &
27     {
28         QString str = QString("鼠标移动了 x = %1 y = %2 globalX = %3 globalY = %4" ).arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY()); //%1 和 %2 都是占位的,%1的位置将是ev->x(),%2的位置将是ev->y()
29         qDebug()<<str;
30     }
31 
32 }

 

1     //设置鼠标追踪
2     setMouseTracking(true);

设置了鼠标追踪后,即使鼠标在区域中不按下,也会显示移动(但是要把判断移动的“if”注释掉)

总结:

  • 鼠标进入事件  enterEvent
  • 鼠标离开事件  leaveEvent
  • 鼠标按下  mousePressEvent(QMouseEvent * ev)
  • 鼠标释放  mouseReleaseEvent
  • 鼠标移动  mouseMoveEvent
  • ev->x() x坐标  ev->y() y坐标
  • ev->button() 可以判断左右按键  Qt::LeftButton  Qt::RightButton
  • ev->buttons() 判断组合按键 判断move时候的左右键 结合 & 操作符
  • 格式化字符串 QString("%1 %2").arg(111).arg(222)

 

  • P32. 定时器(沿用了上P项目)

(下面做:每隔一秒数字增加1)

在ui编辑界面里拖拽一个“Label”

(widget.h)

1     //重写定时器事件
2     void timerEvent(QTimerEvent *);

 

(widget.cpp)

1     //构造函数中
2     //启动定时器
3     startTimer(1000);    //参数1.间隔(单位 毫秒)
4 ...
5 void Widget::timerEvent(QTimerEvent *)
6 {
7     static int num = 1; //静态变量
8     ui->label_2->setText(QString::number(num++));
9 }

 

(下面实现:一个隔一秒+1,一个隔两秒+1)

再往ui编辑界面拖拽一个“Label”

(widget.h)

    //public中
    int id1;    //定时器1的唯一标识
    int id2;    //定时器2的唯一标识

 

(widget.cpp)

 1 //构造函数中
 2     //启动定时器
 3     id1 = startTimer(1000);    //参数1.间隔(单位 毫秒);startTimer返回的是定时器id
 4     id2 = startTimer(2000);
 5 ...
 6 //全局函数
 7 void Widget::timerEvent(QTimerEvent *ev)
 8 {
 9     if(ev->timerId() == id1)
10     {
11         static int num = 1; //静态变量
12         ui->label_2->setText(QString::number(num++));
13     }
14     if(ev->timerId()==id2)
15     {
16         static int num2=1;
17         ui->label_3->setText(QString::number(num2++));
18     }
19 }

总结:

  • 利用事件 void timerEvent(QTimerEvent * ev)
  • 启动定时器 startTimer(1000) 单位毫秒
  • timerEvent 的返回值是定时器的唯一标识 可以和ev->timerId 作比较

 

  • P33. 定时器2(推荐这种方法)(沿用了上P项目)

定时器第二种方式

(实现每隔0.5s数字+1)

在ui编辑界面再拖拽一个“Label”

(widget.cpp)

1 //构造函数中
2 //定时器第二种方式
3     QTimer * timer = new QTimer(this);
4     //启动定时器
5     timer->start(500);  //单位毫秒
6     connect(timer,&QTimer::timeout,this,[=](){
7         static int num3 =1;
8         ui->label_4->setText(QString::number(num3++));
9     });

 

(下面实现:点一个按钮暂停)

在ui编辑界面拖拽一个“Push Button”(改名“暂停”,变量名“btn”)

(widget.cpp)

1     //点击暂停按钮 实现停止计时器
2     connect(ui->btn,&QPushButton::clicked,this,[=](){
3        timer->stop();
4     });
5     //如果恢复那就再添加一个按钮,然后连接timer->start(间隔)

总结:

  • 利用定时器类 QTimer
  • 创建定时器对象 QTimer * timer = new QTimer (this)
  • 启动定时器 timer->start(毫秒)
  • 每隔一定毫秒,发送信号 timeout,进行监听
  • 暂停 timer->stop()

(〃>_<;〃)(〃>_<;〃)(〃>_<;〃)