alin的学习之路(Qt篇:三)(常用控件,自定义控件,事件捕捉)

alin的学习之路(Qt篇:三)(常用控件,自定义控件,事件捕捉)

1. 常用控件

1.QListWidget

listWidget的每一行都是一个QListWidgetItem,有两种添加的方式

  1. 一次添加一个QListWidgetItem
QListWidgetItem *item = new QListWidgetItem("锄禾日当午");
ui->listWidget->addItem(item);
//给Item设置对齐方式
item->setTextAlignment(Qt::AlignHCenter);
  1. 一次性添加一组QListWidgetItems
//一次性添加多个QListWidgetItem需要使用QStringList,相当于QList<QString> -> list<string>
//这种方式添加无法设置格式
QStringList list;
list << "锄禾日当午" << "汗滴禾下土" << "谁知盘中餐" << "粒粒皆辛苦" ;
ui->listWidget->addItems(list);

2.QTreeWidget

  1. 设置头标签 注意参数类型是QStringList

  2. 创建item 注意参数类型是QStringList

  3. 添加到顶层级别的Item

  4. 再添加的子Item要挂载到顶层Item下

    1. 创建每个信息的Item
    2. 将Item挂载到顶层Item上
//1.设置头标签 注意参数类型是QStringList
ui->treeWidget->setHeaderLabels(QStringList() << "英雄" << "英雄简介");
//2.创建QTreeWidgetItem 注意参数类型是QStringList
QTreeWidgetItem *liItem = new QTreeWidgetItem(QStringList() << "力量");
//3.添加到顶层级别的QTreeWidgetItem
ui->treeWidget->addTopLevelItem(liItem);

QTreeWidgetItem *minItem = new QTreeWidgetItem(QStringList() << "敏捷");
ui->treeWidget->addTopLevelItem(minItem);

QTreeWidgetItem *zhiItem = new QTreeWidgetItem(QStringList() << "智力");
ui->treeWidget->addTopLevelItem(zhiItem);

//4.再添加的子QTreeWidgetItem要挂载到顶层QTreeWidgetItem下
QStringList heroL1;
QStringList heroL2;
heroL1 << "刚被猪" << "前排坦克,能在吸收伤害的同时造成可观的范围输出";
heroL2 << "船长" << "前排坦克,能肉能输出能控场的全能英雄";

QStringList heroM1;
QStringList heroM2;
heroM1 << "月骑" << "中排物理输出,可以使用分裂利刃攻击多个目标";
heroM2 << "小鱼人" << "前排战士,擅长偷取敌人的属性来增强自身战力";

QStringList heroZ1;
QStringList heroZ2;
heroZ1 << "死灵法师" << "前排法师坦克,魔法抗性较高,拥有治疗技能";
heroZ2 << "巫医" << "后排辅助法师,可以使用奇特的巫术诅咒敌人与治疗队友";

//4.1创建每个信息的QTreeWidgetItem
QTreeWidgetItem *l1 = new QTreeWidgetItem(heroL1);
QTreeWidgetItem *l2 = new QTreeWidgetItem(heroL2);
QTreeWidgetItem *m1 = new QTreeWidgetItem(heroM1);
QTreeWidgetItem *m2 = new QTreeWidgetItem(heroM2);
QTreeWidgetItem *z1 = new QTreeWidgetItem(heroZ1);
QTreeWidgetItem *z2 = new QTreeWidgetItem(heroZ2);

//4.2将Item挂载到顶层Item上
liItem->addChild(l1);
liItem->addChild(l2);
minItem->addChild(m1);
minItem->addChild(m2);
zhiItem->addChild(z1);
zhiItem->addChild(z2);

3.QTableWidget

  1. 设置列数

  2. 设置表头水平标签

  3. 设置行数

  4. 设置正文

    //1.设置列数
    ui->tableWidget->setColumnCount(3);
    //2.设置水平表头标签
    ui->tableWidget->setHorizontalHeaderLabels(QStringList() << "姓名" << "性别" << "年龄");
    //3.设置行数
    ui->tableWidget->setRowCount(5);
    //4.设置正文
    QStringList namelist;
    namelist << "亚瑟" << "刘备" << "妲己" << "上官婉儿" << "梦琪";
    QStringList sexlist;
    sexlist << "男" << "男" << "女" << "女" << "男";
    for(int i=0 ;i<5 ;++i)
    {
        int col = 0;
        //插入正文的每一个元素都是一个QTableWidgetItem
        ui->tableWidget->setItem(i,col++,new QTableWidgetItem(namelist[i]));
        ui->tableWidget->setItem(i,col++,new QTableWidgetItem(sexlist.at(i)));
        ui->tableWidget->setItem(i,col++,new QTableWidgetItem(QString::number(18+i)));
    }
    
  5. 创建两个按钮来添加和删除一行内容

    connect(ui->btn_add,&QPushButton::clicked,[=](){
        //判断赵云是否已在表格中,findItems返回的是一个QList
        bool isEmpty = ui->tableWidget->findItems("赵云",Qt::MatchExactly).isEmpty();
        if(!isEmpty)
        {
            QMessageBox::warning(this,"警告","赵云已存在,无法重复添加");
        }
        else
        {
            int col = 0;
            //先添加一行,再在添加的这行上操作
            ui->tableWidget->insertRow(0);
            ui->tableWidget->setItem(0,col++,new QTableWidgetItem(QString("赵云")));
            ui->tableWidget->setItem(0,col++,new QTableWidgetItem(QString("男")));
            ui->tableWidget->setItem(0,col++,new QTableWidgetItem(QString::number(30)));
        }
    });
    
    connect(ui->btn_del,&QPushButton::clicked,[=](){
        bool isEmpty = ui->tableWidget->findItems("赵云",Qt::MatchExactly).isEmpty();
        if(isEmpty)
        {
            QMessageBox::warning(this,"警告","赵云不存在,无法删除");
        }
        else
        {
            int rowNum = ui->tableWidget->findItems("赵云",Qt::MatchExactly).first()->row();
            ui->tableWidget->removeRow(rowNum);
        }
    });
    

4.stackedWidget

  1. 概述:可以用来显示不同的界面,达到隐藏其他界面的效果

  2. 使用它来存放:scrollArea,toolBox和tabWidget,并且使用三个按钮达到点击切换的效果

    //设置初始显示
    ui->stackedWidget->setCurrentIndex(0);
    //点击按钮显示指定的stackedWidget页
    connect(ui->btn_Scroll,&QPushButton::clicked,[=](){
        ui->stackedWidget->setCurrentIndex(0);
    });
    connect(ui->btn_Tool,&QPushButton::clicked,[=](){
        ui->stackedWidget->setCurrentIndex(1);
    });
    connect(ui->btn_Tab,&QPushButton::clicked,[=](){
        ui->stackedWidget->setCurrentIndex(2);
    });
    

5.comboBox

下拉框式选择

//添加comboBox中的Item
ui->comboBox->addItem("奔驰");
ui->comboBox->addItem("宝马");
ui->comboBox->addItem("保时捷");
connect(ui->btn_select,&QPushButton::clicked,[=](){
    //点击跳转到目的Item
    //ui->comboBox->setCurrentIndex(2);
    ui->comboBox->setCurrentText("保时捷");
});

6.label添加图片

  1. 静态图:使用QPixmap进行添加

    //给label添加图片,并且要贴合大小
    QPixmap pix;
    pix.load(":/Image/butterfly.png");
    ui->label_picture->setPixmap(pix);
    ui->label_picture->resize(pix.width(),pix.height());
    
  2. 动图:使用QMovie进行添加,添加后要调用start()才能放映

    //利用label显示动图 使用QMovie
    QMovie *movie = new QMovie(":/Image/mario.gif");
    ui->label_movie->setMovie(movie);
    movie->start();   //有这条语句才可播放
    movie->setSpeed(500);   //设置倍速
    
    //设置播放完就停止 不循环播放
    //方法:当动图播放到最后一帧时设置停止
    connect(movie,&QMovie::frameChanged,[=](int frameId){
        if(frameId == movie->frameCount()-1)
        {
            movie->stop();
        }
    });
    

2.自定义控件

需求:使用SpinBox和HorizontalSlider进行联动,改变SpinBox的值HorizontalSlider的进度条会移动,移动HorizontalSlider的进度条SpinBox的值会改变

步骤:

1. 创建一个Qt设计师界面类并将两个控件进行封装成一个类
2. 在主界面添加一个Widget将其提升为类
3. 在封装的类中书写实现联动的代码
//更改SpinBox的值 Slider跟着滑动
void(QSpinBox::* signal)(int) = &QSpinBox::valueChanged;
connect(ui->spinBox,signal,ui->horizontalSlider,&QSlider::setValue);

//滑动Slider 更改Spinbox的值
connect(ui->horizontalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);

创建两个按钮:一个点击实现将值设置为50,一个点击获取值

//点击设置为50
connect(ui->btn_set,&QPushButton::clicked,[=](){
    ui->widget->setData(50);
});

//点击返回当前值
connect(ui->btn_get,&QPushButton::clicked,[=](){
    qDebug() << ui->widget->getData();
});

3.事件捕捉

1.鼠标相关事件

捕捉鼠标进入一个label和在label中点击相关的事件

步骤:

  1. 添加一个label并创建一个MyLabel类
  2. 将label提升为MyLabel类,在MyLabel类中重写事件捕捉的相关函数
//MyLabel.h
    
public:
explicit MyLabel(QWidget *parent = nullptr);

//鼠标进入事件
void enterEvent(QEvent *event);

//鼠标离开事件
void leaveEvent(QEvent *event);

//鼠标点击事件
void mousePressEvent(QMouseEvent *ev);

//鼠标释放事件
void mouseReleaseEvent(QMouseEvent *ev);

//鼠标移动事件
void mouseMoveEvent(QMouseEvent *ev);

//事件分发器
bool event(QEvent *e);    
//MyLabel.cpp
//鼠标进入事件
void MyLabel::enterEvent(QEvent *event)
{
    //qDebug() << "鼠标进入了";
}

//鼠标离开事件
void MyLabel::leaveEvent(QEvent *event)
{
    //qDebug() << "鼠标离开了";
}

//鼠标点击事件
void MyLabel::mousePressEvent(QMouseEvent *ev)
{
    if(ev->button() == Qt::LeftButton)
    {
        QString str = QString("鼠标点击了, x = %1 , y = %2").arg(ev->x()).arg(ev->y());
        qDebug() << str;
    }
}

//鼠标释放事件
void MyLabel::mouseReleaseEvent(QMouseEvent *ev)
{
    if(ev->button() == Qt::LeftButton)
    {
        QString str = QString("鼠标释放了, x = %1 , y = %2").arg(ev->x()).arg(ev->y());
        qDebug() << str;
    }
}

//鼠标移动事件
void MyLabel::mouseMoveEvent(QMouseEvent *ev)
{
    //注意判断按键时,要使用buttons()的接口&相应的枚举值
    if(ev->buttons() & Qt::LeftButton)
    {
        QString str = QString("鼠标移动了, x = %1 , y = %2").arg(ev->x()).arg(ev->y());
        qDebug() << str;
    }
}

2.事件分发器

事件分发器处于app与事件捕获函数之间,是高一级的事件处理

//事件分发器
bool MyLabel::event(QEvent *e)
{
    //捕获事件
    if(e->type() == QEvent::MouseButtonPress)
    {
        QMouseEvent* ev = dynamic_cast<QMouseEvent*>(e);
        QString str = QString("在event中 鼠标点击了, x = %1 , y = %2").arg(ev->x()).arg(ev->y());
        qDebug() << str;

        return true;    //true代表拦截,不向下分发
    }

    //其他交给父类处理
    return QLabel::event(e);
}

3.事件过滤器

事件过滤器处于app和事件分发器之间,是更高一级的事件处理

步骤:

  1. 给指定控件添加事件过滤器
  2. 重写事件过滤器函数
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    //1.先给控件安装过滤器
    ui->label->installEventFilter(this);
}

//2.重写事件过滤器函数
//参数1:判断控件  参数2:判断事件
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    //判断是哪一控件
    if(watched == ui->label)
    {
        //捕获事件
        if(event->type() == QEvent::MouseButtonPress)
        {
            QMouseEvent* ev = dynamic_cast<QMouseEvent*>(event);
            QString str = QString("在eventFilter中 鼠标点击了, x = %1 , y = %2").arg(ev->x()).arg(ev->y());
            qDebug() << str;

            return true;    //true代表拦截
        }
    }
    //其他交给父类处理
    return QWidget::eventFilter(watched,event);
}

4.定时器事件

定时器事件用于定时触发事件,有两种书写方法:

  1. 定时器事件

    //开启一个定时器,单位是毫秒,返回一个该定时器的唯一标识int
    this->m_Id1 = startTimer(1000);
    
    this->m_Id2 = startTimer(2000);
    
    //定时器事件
    void Widget::timerEvent(QTimerEvent *event)
    {
        if(event->timerId() == m_Id1)
        {
            static int num = 1;
            ui->label->setText(QString::number(num++));
        }
    
        if(event->timerId() == m_Id2)
        {
            static int num = 1;
            ui->label_2->setText(QString::number(num++));
        }
    }
    
  2. 定时器类(同时设定两个按钮来控制暂停和开始)

    //使用定时器类
    QTimer *timer = new QTimer(this);
    timer->start(500);    //与定时器事件的接口区分,该接口是start()
    connect(timer,&QTimer::timeout,[=](){
        static int num = 1;
        ui->label_3->setText(QString::number(num++));
    });
    
    //按钮暂停
    connect(ui->pushButton,&QPushButton::clicked,[=](){
        timer->stop();
    });
    
    //按钮开始
    connect(ui->pushButton_2,&QPushButton::clicked,[=](){
        timer->start(500);
    });
    

猜你喜欢

转载自blog.csdn.net/qq_41775886/article/details/107165600