Qt:控制图片的移动

笔记 · 2023-09-08 · 455 人浏览
Qt:控制图片的移动

  本次实验涉及Qt中的绘图来绘制资源图片,使用 connect 信号连接手动控制图片的移动以及通过定时器来实现自动控制。

需求描述

如下图:当程序运行后,程序中的图片会自动向屏幕右侧移动,直至消失后再次出现在屏幕中,依此循环。期间可以通过按钮手动控制暂停和继续,也能通过手动调整相应位置。

最终效果图:
2023-09-08T07:11:25.png

需求分析

  1. 控制区域应该区分开来分为手动/自动
  2. 若在自动时切换手动控制自动应不受影响
  3. 手动按钮应该支持长按加减位置
  4. 图片移动区域应不能超过屏幕最大宽度
  5. UI 界面设置最小尺寸,控制区和图片区域互不影响

备注:所使用Qt版本为5.14.2,Qt Creator版本为4.11.1



功能实现

上文提及到的定时器已在上次实验完成,以下便不再详细说明。

实验原理

  首先创建一个 QDialog 窗口类型,需要勾选UI界面(Generate form),然后在UI中添加相应区域并添加所属控件。引入定时器来实现自动移动图片,PushButton 来手动控制。
2023-09-08T03:10:16.png

资源图片载入

  这里建议将需要加载的图片放在当前文件夹下,然后添加一个新的资源文件即可,剩下的都是默认操作,最好使用英文(名称、前缀、文件名),添加完成构建即可。
2023-09-08T03:18:26.png

UI 界面

  利用Stacked Widget + Radio Button 来区分自动和手动两种选择按钮,采用的是栅格化布局以及加上水平和垂直的弹簧使页面能够做到响应式。
2023-09-08T05:20:19.png

相关代码

以下代码中,需要注意:

  1. 变量 result 应在 dialog.h 中声明为全局。
  2. 函数 paintEvent 应重写,否则绘图将会不显示。
  3. 控件 Stacked Widget 要注意填入 setCurrentIndex 的索引值(index)。

widget.h:

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QTimer>

QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACE

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = nullptr);
    ~Dialog();

    // 绘图事件
    void paintEvent(QPaintEvent *);

    int result = 0; // 记录值

private:
    Ui::Dialog *ui;
};
#endif // DIALOG_H

widget.cpp:

#include "dialog.h"
#include "ui_dialog.h"
#include <QDebug>
#include <QPainter>   // 画家类

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

    /*********** 定时器对象 *************/
    QTimer * timer = new QTimer(this);
    timer->start(100);  // 启动定时器 1s

    connect(timer, &QTimer::timeout, [=](){
        result += 20;
        update();  // 更新图片位置
        });

    /********* 手/自(栈控件) **********/
    ui->rBtnAuto->setChecked(true);

    connect(ui->rBtnAuto, &QRadioButton::clicked, [=](){
        // 自动 ->>  0
        ui->stackedWidget->setCurrentIndex(0);
    });

    connect(ui->rBtnManual, &QRadioButton::clicked, [=](){
        // 手动 ->>  1
        ui->stackedWidget->setCurrentIndex(1);
    });

    /////////// 自动控制按钮 //////////
    connect(ui->auto_btn, &QPushButton::clicked, [=](){
        if(ui->auto_btn->text() == "暂停")
        {
            timer->stop();
            ui->auto_btn->setText("启动");
        }
        else
        {
            timer->start();
            ui->auto_btn->setText("暂停");
        }
    });

    /////////// 手动控制按钮 //////////

    ui->btnAdd->setAutoRepeat(true); //启用长按
    ui->btnReduce->setAutoRepeat(true);

    ui->btnAdd->setAutoRepeatDelay(200); //触发长按的时间
    ui->btnReduce->setAutoRepeatDelay(200);

    ui->btnAdd->setAutoRepeatInterval(20); //长按时click信号间隔
    ui->btnReduce->setAutoRepeatInterval(20);

    connect(ui->btnAdd, &QPushButton::clicked, [=](){
        // 若是自动状态,则手动控制无效
        if(ui->rBtnManual->isChecked() && ui->auto_btn->text() == "启动")
            result += 10;
        update();  // 更新图片位置
    });

    connect(ui->btnReduce, &QPushButton::clicked, [=](){
        if(ui->rBtnManual->isChecked() && ui->auto_btn->text() == "启动")
            result -= 10;
        update();  // 更新图片位置
    });
}

void Dialog::paintEvent(QPaintEvent *)
{
    /************ 资源图片 **************/

    // 重新回到屏幕
    if(result > this->width())
        // 露头
        result = -200;

    QPainter painter(this);
    painter.drawPixmap(result, 20, 200, 200, QPixmap(":/img/plane.png"));

}

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

以上代码仅供参考。如若有任何问题和建议,还望大佬指正!

Qt 实验
  1. xxcheng 2023-09-14

    点赞~~

  2. LosKartos 2023-09-08

    给你点个赞。程序员的想法总是这么棒!

Theme Jasmine by Kent Liao

本网站由 又拍云 提供CDN加速/云存储服务

鄂ICP备2023005457号    鄂公网安备 42011302000815号