Qt学习:自定义控件/Qt事件处理/定时器

1.自定义控件的实现
添加新文件->Qt->Qt设计界面类
在该类中利用UI界面设计好自己的组合控件界面
在类的头文件和cpp中实现一些控件的绑定,以及设计提供给用户的函数接口。

以设计一个输入框和slider绑定的控件为例:
(首先创建设计界面类)
Qt学习:自定义控件/Qt事件处理/定时器_第1张图片
Qt学习:自定义控件/Qt事件处理/定时器_第2张图片
新建项目选择设计界面类后,界面模板可以选择Widget,之后的文件命名等操作按自己需求来命名。

项目中会有两个UI文件,一个是主窗体的UI,一个是创建的自定义控件的设计界面UI。
在UI中按需设计好控件布局
在主窗体中拖出一个Widget控件,右键会有提升为
在窗体中填入自己设计好的界面类头文件名,点添加,点提升。 这样该widget就与自己设计好的界面类绑定到一起并能在项目运行时同步显示该界面类的界面。
(此过程图片省略,实操找一下)

接下来是给界面类设计功能以及对外的函数调用。
列代码如下:
//smallwidget.h


#ifndef SMALLWIDGET_H
#define SMALLWIDGET_H

#include 

namespace Ui {
class SmallWidget;
}

class SmallWidget : public QWidget
{
    Q_OBJECT

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

    void setNum(int num);
    int getNum();

private:
    Ui::SmallWidget *ui;
};

#endif // SMALLWIDGET_H

//smallwidget.cpp

#include "smallwidget.h"
#include "ui_smallwidget.h"

SmallWidget::SmallWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::SmallWidget)
{
    ui->setupUi(this);

    void(QSpinBox:: *spSignal)(int)=&QSpinBox::valueChanged;
    connect(ui->spinBox,spSignal,ui->horizontalSlider,&QSlider::setValue);
    connect(ui->horizontalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);
}

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

void SmallWidget::setNum(int num)
{
    ui->spinBox->setValue(num);
}

int SmallWidget::getNum()
{
    return ui->spinBox->value();
}

这段代码主要实现了两个功能
一是利用connect将QSpinBox控件与QSlider控件绑定起来(此处建的水平slider,horizontal Slider,但是qt中类名都是统称为slider的)

void(QSpinBox::*spSignal)(int) = &QSpinBox::valueChanged;
connect(ui->spinBox,spSignal,ui->horizontalSlider,&Slider::setvalue);

connect(ui->horizontalSlider,&Slider::valueChanged,ui->spinBox,&QSpinBox::setValue);

此处QSpinBox的valueChanged有函数重载,所以要定义函数指针

void(QSpinBox::*spSignal)(int) = &QSpinBox::valueChanged;

二是定义设置数字和获取数字的函数接口

void SmallWidget::setNum(int num)
{
		ui->spinBox->setValue(num);
}
int SmallWidget::getNum()
{
		return ui->spinBox->value();
}

在主窗体的函数实现中可以调用这个自定义类的接口

#include "widget.h"
#include "ui_widget.h"
#include

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    connect(ui->bt_get,&QPushButton::clicked,[=](){
            qDebug()<widget->getNum();
    });

    connect(ui->btn_set,&QPushButton::clicked,[=](){
        ui->widget->setNum(50);
    });
}

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

此处是通过本界面中的widget控件来使用自定义界面类中的函数。 因为该widget控件已经提升为自己设计的界面类。

connect(ui->bt_get,&QPushButton::clicked,[=](){
     qDebug()<widget->getNum();
});
connect(ui->btn_set,&QPushButton::clicked,[=](){
	ui->widget->setNum(50);
});

此处用的是lambda表达式, 本例仅是简单测试两个读数与设置数的函数接口。
基本方法通了后可以根据需要设计自己的复杂控件。
比如仪表等。

此外,设计控件类的思想可以应用在:
在项目中添加一个普通的c++类文件,该类可以按需继承QWidget,QLabel等父类。
以mylabel为例,在窗体的UI类中拉出一个label后可以提升为mylabel。
然后就可以自己设计mylabel控件的具体函数了。

接下来的mylabel文件主要测试学习了鼠标事件。
//mylabel.h

#ifndef MYLABEL_H
#define MYLABEL_H

#include 

class mylabel : public QLabel
{
    Q_OBJECT
public:
    explicit mylabel(QWidget *parent = nullptr);

    virtual void enterEvent(QEvent *event);
    virtual void leaveEvent(QEvent *);
    virtual void mousePressEvent(QMouseEvent *ev);
    virtual void mouseReleaseEvent(QMouseEvent *ev);
    virtual void mouseMoveEvent(QMouseEvent *ev);

    //通过event事件分发器拦截事件
    virtual bool event(QEvent *e);
signals:

public slots:
};

#endif // MYLABEL_H

此处都是虚函数重写鼠标事件。 (属c++继承里的语法,算是函数接口,自定义所需动作)

//mybel.cpp

#include "mylabel.h"

#include
#include
#include

mylabel::mylabel(QWidget *parent) : QLabel(parent)
{
    setMouseTracking(true);
}

void mylabel::enterEvent(QEvent *event)
{
  //  qDebug()<<"mouse enter";
}
void mylabel::leaveEvent(QEvent *)
{
  //  qDebug()<<"mouse leave";
}

void mylabel::mousePressEvent(QMouseEvent *ev)
{
    if(ev->button()==Qt::LeftButton)
{
    QString str = QString("mouse press x=%1 y=%2 gx=%3  gy =%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
    qDebug()<button()==Qt::LeftButton)
{
    QString str = QString("mouse release x=%1 y=%2 gx=%3  gy =%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
    qDebug()<buttons() &Qt::LeftButton)  //位与操作符判断按键状态
//{
    QString str = QString("mouse press x=%1 y=%2 gx=%3  gy =%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
    qDebug()<type()==QEvent::MouseButtonPress)
    {
        QMouseEvent *ev = static_cast(e);
        QString str = QString("event mouse release x=%1 y=%2 gx=%3  gy =%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug()<

本文件中测试了一些鼠标按下、移动等事件及事件分发器中的拦截
另外,有两个小点,一是QString的格式化输出

QString str = QString("mouse press %1  %2").arg(ev->x()).arg(ev-y());

另一个是类型转换以匹配

QMouseEvent *ev = static_caste;

开启鼠标追踪

setMouseTracking(true);   //默认是关,此处设成开

下面的主窗体widget .cpp中,测试了定时器以及事件过滤器

#include "widget.h"
#include "ui_widget.h"
#include
#include
#include

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    id1 = startTimer(1000);  //参数1 间隔  单位是毫秒

    id2 = startTimer(2000);

    //定时器的第二种方式
    QTimer *timer = new QTimer(this);
    timer->start(500);
    connect(timer,&QTimer::timeout,[=](){
         static int num2 = 1;

        ui->label_3->setText(QString::number(num2++));
    });

    connect(ui->stop,&QPushButton::clicked,[=](){
            timer->stop();
    });

    //给label安装事件过滤器
    ui->label->installEventFilter(this);

}

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

bool  Widget::eventFilter(QObject *watched, QEvent *event)
{
    if(watched == ui->label)
    {
        if(event->type()==QEvent::MouseButtonPress)
        {
             QMouseEvent *ev = static_cast(event);
            QString str = QString("eventfilter mouse release x=%1 y=%2 gx=%3  gy =%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
             qDebug()<timerId()==id1)
{
    static int num = 1;
    ui->label_2->setText(QString::number(num++));

}
if(event->timerId()==id2)
{
   //  static int num2 = 1;
  //  ui->label_3->setText(QString::number(num2++));
}

}

事件过滤器上,需要给控件安装事件过滤器

    //给label安装事件过滤器
    ui->label->installEventFilter(this);
bool  Widget::eventFilter(QObject *watched, QEvent *event)
{
    if(watched == ui->label)
    {
        if(event->type()==QEvent::MouseButtonPress)
        {
             QMouseEvent *ev = static_cast(event);
            QString str = QString("eventfilter mouse release x=%1 y=%2 gx=%3  gy =%4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
             qDebug()<

定时器使用有两种方式:
1.QTimerEvent
通过返回值来区分定时器id。

 id1 = startTimer(1000);  //参数1 间隔  单位是毫秒
 id2 = startTimer(2000);

重写timerEvent函数来处理定时器

void Widget::timerEvent(QTimerEvent *event)
{
	if(event->timerId == id1)
	if(event->timerId==id2)
	
}

2.QTimer 类
建立QTimer类对象

    QTimer *timer = new QTimer(this);
    timer->start(500);
    connect(timer,&QTimer::timeout,[=](){
         static int num2 = 1;
          ui->label_3->setText(QString::number(num2++));
    });

下面这段代码为QString将数字输出到文本

  ui->label_3->setText(QString::number(num2++));

你可能感兴趣的:(Qt,Qt,自定义控件,事件,界面类,定时器)