• Qt基础学习笔记


    Qt中的常用快捷键

    注释:ctrl + /
    运行:ctrl + r
    编译:ctrl + b
    帮助文档:F1
    自动对齐:ctrl + i
    同名之间.h文件与.cpp文件的切换:F4

    QPushButton按钮

    需要引入<QPushButton>头文件,QPushButton继承于QWidget类

    创建一个按钮

    // 默认构造
    QPushButton * btn = new QPushButton();
    
    // 构造创建按钮 弊端:默认以控件的大小创建窗口
    QPushButton* btn2 = new QPushButton("第二个按钮", this); // 通过构造指定父类和文本
    
    • 1
    • 2
    • 3
    • 4
    • 5

    显示按钮

    btn->show(); // 默认顶层方式弹出,独立的窗口
    
    • 1

    要想按钮显示在指定窗口中,需要指定父类

    btn->setParent(this); // 将按钮的父类设置为myWidget,使其显示在myWidget窗口中
    btn->setText("第一个按钮"); // 按钮的文本
    
    • 1
    • 2

    设置按钮位置
    坐标是以左上角为(0,0)

    // 移动按钮至指定坐标处
    btn2->move(100, 100);
    
    • 1
    • 2

    窗口和按钮大小

    // 重置窗口大小
    resize(600, 400);
    
    // 按钮重置大小
    btn2->resize(50,50);
    
    // 设置固定的窗口大小
    setFixedSize(600, 400); // 不能通过鼠标拖拽来改变窗口的大小
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    设置窗口标题

    // 设置窗口标题
    setWindowTitle("第一个窗口");
    
    • 1
    • 2

    对象树

    1、当创建的对象在堆区时,如果指定的对象是QObject或者其子类派生下来的类,可以不用管理释放的操作,将对象放入到对象树中。
    2、对象树的构造是现有父类再有子类的,析构顺序是先析构子类再析构父类。
    3、当析构函数中有输出语句时,先打印父类的析构语句,但这并不意味着析构顺序。西沟的顺序依然是先子类后父类。
    4、对象树一定程度上简化了内存回收机制。

    信号和槽

    信号槽的优点:松散耦合。
    什么是松散耦合:信号的发送端 和 接收端本身是没有关联的,通过connect连接将两端耦合在一起。
    connect(发送者, 发送的信号, 接收者, 信号的处理(槽));

    1. 参数1:信号的发送者
    2. 参数2:发送的信号(存放函数的地址)(clicked点击,pressed按下,released弹起,toggled切换)
    3. 参数3:信号的接收者
    4. 参数4:处理的槽函数(函数地址)
    connect(myBtn, &PushButton::clicked, this, &Widget::close);
    
    // 断开信号, 传参与connect一致
    disconnect(btn, &QPushButton::clicked, this, &Widget::classIsOver);
    
    // Qt4版本信号槽的连接
    connect(zt, SIGNAL(hungry()), st, SLOT(treat()));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Qt4版本的优点,直观。缺点,类型不做检测

    自定义信号
    自定义信号使用signals关键字修饰
    规定:
    1、没有返回值;
    2、只需要声明不需要实现;
    3、可以有参数;
    4、可以重载;

    signals:
        // 自定义信号写在这里
        void hungry();
        void hungry(QString foodName); // 信号的重载
    
    • 1
    • 2
    • 3
    • 4

    自定义槽函数
    规定:
    1、无返回值;
    2、需要声明也需要实现;
    3、可以有参数;
    4、可以发生重载;

    public slots:
        // 槽函数写在这里,早期版本必须写在这里,Qt5之后可以不使用slots关键字
        void treat();
        void treat(QString foodName); 
    
    • 1
    • 2
    • 3
    • 4

    重载后的槽函数连接时需要指明函数类型

    // 创建一个老师对象
    this->zt = new Teacher(this);
    
    // 创建一个学生对象
    this->st = new Student(this);
    
    // 有参信号的连接
    void (Teacher:: *teacherSignal)(QString) = &Teacher::hungry;
    void (Student:: *studentSlots)(QString) = &Student::treat;
    connect(zt, teacherSignal, st, studentSlots);
    
    // 无参信号的连接
    void (Teacher:: *teacherSignal2)(void) = &Teacher::hungry;
    void (Student:: *studentSlots2)(void) = &Student::treat;
    connect(zt, teacherSignal2, st, studentSlots2);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    槽函数必须有对应的实现。
    使用时用connect将信号与槽函数连接在一起即可。

    信号的发送
    使用emit

    emit zt->hungry(); // 使用emit发送信号
    emit zt->hungry("有参的信号");
    
    • 1
    • 2

    信号和槽的连接
    1、信号连接多个槽函数
    2、多个信号连接同一个槽函数
    3、信号连接信号
    注意: 信号的参数可以多于槽,但是必须一一对应

    Lambda表达式

        // []标识一个Lambda的开始不能省略
        [=](){ // 值传递
            btn->setText("下课111");
        }();
        [&](){ // 引用传递
            btn2->setText("下课222");
        }();
        [btn](){ // 锁定值传递,只有btn生效
            btn->setText("下课222");
            //btn2->setText("下课222"); // 看不到,报错
        }();
        [=]()mutable{ // 加上mutable关键字,可以修改值传递的拷贝,注意只能修改拷贝,而不是传入值的本身
            btn->setText("下课111");
        }();
        int ret = []()->int{return 1000;}(); // ->代表Lambda的返回值类型
        qDebug() << ret << endl;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    菜单栏

    一个程序中菜单栏 只能最多有一个

    	// 菜单栏的创建
    	QMenuBar *bar = menuBar();
    	// 将菜单栏放入窗口中
    	setMenuBar(bar);
    	
    	// 新增菜单
        QMenu * fileMenu = bar->addMenu("文件");
        QMenu * editMenu = bar->addMenu("编辑");
    
        // 创建菜单项
        QAction* newAction = fileMenu->addAction("新建");
        fileMenu->addSeparator(); // 添加分割线
        QAction* openAction = fileMenu->addAction("打开");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    工具栏

    工具栏可以有多个

        QToolBar* toolBar = new QToolBar(this);
        //addToolBar(toolBar); // 将工具栏加载到窗口中,默认位置在上面,可以拖拽
        addToolBar(Qt::LeftToolBarArea, toolBar); // 指定左边
    
        // 只允许工具栏左右停靠
        toolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);
    
        // 设置工具栏浮动
        toolBar->setFloatable(false); // 默认值为 true 可以浮动。设置false不允许浮动
    
        // 设置不可拖拽,默认可拖拽
        toolBar->setMovable(false);
    
        // 在工具栏中设置选项
        toolBar->addAction(newAction); // 跟上面fileMenu公用一个
        toolBar->addAction(openAction);
        toolBar->addSeparator(); // 添加分割线
        toolBar->addAction("自己"); // 也可以自己设置一个选项
    
        // 工具栏中添加控件
        QPushButton * btn = new QPushButton("aa", this);
        toolBar->addWidget(btn); // 将按钮放入工具栏中
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    状态栏

    可以有多个

        QStatusBar* stBar = statusBar();
        // 将状态栏设置在窗口中
        setStatusBar(stBar);
        // 往状态栏中放标签控件
        QLabel* label = new QLabel("提示", this);
        stBar->addWidget(label); // 将标签放入状态栏
    
        QLabel* label2 = new QLabel("右侧提示", this);
        stBar->addPermanentWidget(label2);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    铆接部件

        // 铆接部件(浮动窗口)  可以有多个  可拖拽
        QDockWidget* dockWidget = new QDockWidget("浮动",this);
        addDockWidget(Qt::BottomDockWidgetArea, dockWidget); // 围绕核心,根据核心确定位置
    
        // 设置后期停靠只能上下
        dockWidget->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    核心部件

    只能有一个

    	// 设置中心部件, 只能有一个
        QTextEdit* edit = new QTextEdit(this);
        setCentralWidget(edit); // 设置中心部件到窗口
    
    • 1
    • 2
    • 3

    各个栏的布局情况
    在这里插入图片描述

    添加资源文件

    第一步:先将资源复制到项目所在文件夹
    第二步:在Qt中右键项目—>添加新文件(Add New…),出现如下界面
    在这里插入图片描述
    第三步:名称自己起,添加成功后Qt列表会多出资源的文件夹
    在这里插入图片描述
    第四步:右键.qrc资源文件
    在这里插入图片描述
    第五步:添加前缀可以自定义,先添加前缀再添加文件
    在这里插入图片描述
    然后保存编译一下,就能看到项目列表中的资源文件了。

    资源文件的使用
    路径前必须写 ( “:” + “前缀”)

    ui->actionnew->setIcon(QIcon(":/img/1.jpg")); // 这样就算代码移到别的电脑也可以使用这个图片
    
    • 1

    对话框

    Qt都提供了哪些标准对话框:

    1. QColorDialog:选择颜色对话框。
    2. QFileDialog:选择文件对话框。
    3. QFontDialog:选择字体对话框。
    4. QInputDialog:允许用户输入一个值,并将其值返回。
    5. QMessageBox:消息(模态)对话框,用于显示信息,或询问等。
    6. QPageSetupDialog:为打印机提供纸张相关选项。
    7. QPrintDialog:打印机配置。
    8. QPrintPreviewDialog:打印预览。
    9. QProgressDialog:显示操作过程。

    1、模态对话框:该对话框弹出后必须响应,否则不能点其他的窗口

    // 点击按钮,弹出对话框
    connect(ui->actionnew, &QAction::triggered, [=](){
    	// 模态对话框(不可以对其他窗口进行操作)
    	QDialog dlg(this);
    	dlg.resize(200, 100); // 对话框太小有警告,系统提示对话框太小可能显示不了有效信息,所以警告
    	dlg.exec(); // 阻塞  必须对对话框操作完毕才放开阻塞,向下执行
    	qDebug() << "模态对话框操作完毕!";});
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2、非模态对话框:该对话框弹出后可以不响应,依然可以点击其他窗口

    // 点击按钮弹出对话框
    connect(ui->actionnew, &QAction::triggered, [=](){
    	// 非模态对话框(可以对其他窗口进行操作)
    	QDialog *dlg2 = new QDialog(this); // 交给对象树释放
    	dlg2->resize(200, 100);
    	dlg2->show(); // 对话框独立展示后,还可以向下执行
    	qDebug() << "非模态对话框执行了!" << endl;});
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    注意:
    如果不停的点击按钮触发非模态对话框,就会不停的new空间,
    但是对象树是在程序结束时统一释放的,
    所以这个对象就有可能导致内存溢出,
    解决方法:
    设置Attribute属性,在对话框关闭的时候就释放申请的空间

    dlg2->setAttribute(Qt::WA_DeleteOnClose);
    
    • 1

    3、消息对话框

    connect(ui->actionww, &QAction::triggered, this, [=]{
    	QMessageBox::critical(this, "hello", "错误:");
    });
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    返回值:选项;参数1:指定父类;参数2:对话框标题;参数3:显示的内容;参数4:选项;参数5:关联回车的选项;
    其他都类似,列举一下:

    // 信息对话框
    QMessageBox::information(this, "information", "信息:");
    // 提问对话框
    QMessageBox::question(this, "question", "请问:");
    // 警告对话框
    QMessageBox::warning(this, "warning", "警告:");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    提问对话框可以修改选项值,默认为yes|no

    // 提问对话框
    QMessageBox::question(this, "question", "请问:", 
    							QMessageBox::Save|QMessageBox::Cancel);
    
    • 1
    • 2
    • 3

    提问对话框的第五参数表示默认关联回车的选项

    // 提问对话框
    QMessageBox::question(this, "question", "请问:", 
    							QMessageBox::Save|QMessageBox::Cancel,
    							QMessageBox::Cancel);
    
    • 1
    • 2
    • 3
    • 4

    其他对话框

    // 颜色选择对话框,返回值是颜色的QColor类型的色域值
    QColor color = QColorDialog::getColor(QColor(255,0,0,2)); // 第四参数为透明度
    qDebug() << color.red() << color.green() << color.blue() << color.alpha() << endl;
    
    // 文件对话框
    QString str = QFileDialog::getOpenFileName(this, "D:/DeskTop", "(*.txt)"); // 第三参数文件过滤
    qDebug() << "str: " << str << endl;// 返回值是选中文件的路径
    
     // 字体对话框
    bool flag = true;
    QFont font = QFontDialog::getFont(&flag, QFont("华文彩云", 36));
    qDebug() << "字体:" << font.family().toUtf8().data() << "字号:" << font.pointSize() 
             << "是否加粗:" << font.bold() << "是否倾斜:" << font.italic() << endl; // 返回值
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    界面布局

    在这里插入图片描述

    对齐方式
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    运行结果
    在这里插入图片描述

    若想将用户名和密码框都对齐,可将这4个组件拖入一个widget中进行栅格布局。

    自定义控件

    右键项目—>添加新文件(Add New…)—>选Qt—>设计师界面类—>确定。
    在这里插入图片描述
    在这里插入图片描述
    然后给自己的ui界面起一个名字
    创建成功后就出现了一个新的ui
    在这里插入图片描述

    在自己创建的ui文件中自定义拖拽想要封装的控件组合成一个新的控件。
    在这里插入图片描述

    记下自己创建的是什么控件类型
    在这里插入图片描述

    然后点击进入程序默认创建的ui文件
    在这里插入图片描述

    因为我创建的控件类型是widget
    在这里插入图片描述

    右键widget控件—>提升为
    在这里插入图片描述
    在这里插入图片描述

    成功后可以看到这个控件的类型变成了自定义控件类型
    在这里插入图片描述

    运行看结果,封装成功
    在这里插入图片描述
    若想给自定义控件加功能,在自定义的类中写逻辑代码即可。

    	// QSpinBox移动 QSlider跟着移动
        void (QSpinBox::* sp)(int) = &QSpinBox::valueChanged;
        connect(ui->spinBox, sp, ui->horizontalSlider, &QSlider::setValue);
    
        // QSlider滑动 QSpinBox数字跟着变化
        connect(ui->horizontalSlider, &QSlider::valueChanged, ui->spinBox, &QSpinBox::setValue);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Qt中的鼠标事件

    myLabel::myLabel(QWidget* parent): QLabel(parent)
    {
        // 设置鼠标追踪,不需要按下,鼠标移动就能被捕获到
        setMouseTracking(true);
    }
    
    void myLabel::enterEvent(QEvent* event){
    //    qDebug() << "鼠标进入了" << endl;
    }
    void myLabel::leaveEvent(QEvent*){
    //    qDebug() << "鼠标离开了" << endl;
    }
    
    // 鼠标移动
    void myLabel::mouseMoveEvent(QMouseEvent *ev){
        QString str; // 移动检测得用buttons()函数,并用&操作
        if(ev->buttons() & Qt::LeftButton) // 右键
        str = QString("鼠标释放了  x = %1  y = %2 "
                              "globalx = %3  global = %4")
                .arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug() << "鼠标移动了" << endl;
    }
    // 鼠标按下
    void myLabel::mousePressEvent(QMouseEvent *ev){
        QString str;
        // Qt中的字符串格式化
        // x,y函数是基于控件的,globalx,globaly是基于整个电脑屏幕的
        if(ev->button() == Qt::LeftButton) // 鼠标左键
        str = QString("鼠标按下了  x = %1  y = %2 "
                              "globalx = %3  global = %4")
                .arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug() << str << endl;
    }
    // 鼠标释放
    void myLabel::mouseReleaseEvent(QMouseEvent *ev){
        QString str;
        if(ev->button() == Qt::RightButton) // 右键
        str = QString("鼠标释放了  x = %1  y = %2 "
                              "globalx = %3  global = %4")
                .arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug() << str << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    定时器

    Widget::Widget(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Widget)
    {
        ui->setupUi(this);
    
        // 启动定时器
        startTimer(1000);// 参数1:间隔时间 毫秒
    }
    // 重写定时器事件
    void Widget::timerEvent(QTimerEvent *){
        static int num = 1;
        ui->label_2->setText(QString::number(num++));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    startTimer()函数返回值是定时器的唯一标识,当有多个定时器时可以用来做区分

    Widget::Widget(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Widget)
    {
        ui->setupUi(this);
    
        // 启动定时器
        id1 = startTimer(1000);// 参数1:间隔时间 毫秒
        id2 = startTimer(2000);
    	// 定义成员变量来存放定时器的唯一值
    }
    // 重写定时器事件
    void Widget::timerEvent(QTimerEvent * ev){
        if(ev->timerId() == id1){
            static int num = 1;
            ui->label_2->setText(QString::number(num++));
        }
        if(ev->timerId() == id2){
            static int num2 = 1;
            ui->label_3->setText(QString::number(num2++));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    实际上,当startTimer函数调用后会启动一个全局唯一的定时器,在指定时间间隔后调用定时器事件,事件函数可通过timerId函数来区分是哪个定时器调用的当前事件。
    按时间间隔重复调用事件函数。

    定时器的另一种实现 (推荐使用)

        // 定时器的第二种实现方式
        QTimer *time = new QTimer(this);
        time->start(500); // 单位毫秒
        connect(time, &QTimer::timeout, this, [=](){
            static int num = 1;
            ui->label_4->setText(QString::number(num++));
        });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    event事件分发器

    在这里插入图片描述

    事件拦截 (不建议实际使用,仅供学习练习)
    不让事件分发器继续向下分发

    // event分发拦截
    bool myLabel::event(QEvent *e){
        // 如果是鼠标按下事件
        if(e->type() == QEvent::MouseButtonPress){
            qDebug() << "鼠标按下事件被拦截了" << endl;
            return true;
        }
        
        // 其他事件交给父类处理
        return QLabel::event(e);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    事件过滤器

    在这里插入图片描述

        // 步骤1:给label安装事件过滤器
        ui->label->installEventFilter(this);
    }
    // 步骤2:重写事件过滤器事件
    bool Widget::eventFilter(QObject* obj, QEvent* e){
        if(obj == ui->label){
            if(e->type() == QEvent::MouseButtonPress){
                qDebug() << "事件过滤:" << endl;
                QMouseEvent* ev = static_cast<QMouseEvent *>(e); // 强制类型转换,静态转换
                QString str = QString("鼠标按下了  x = %1  y = %2 "
                                      "globalx = %3  global = %4")
                        .arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
                qDebug() << str << endl;
                return true;
            }
        }
    
        return QWidget::eventFilter(obj,e);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    绘图事件

    只需重写paintEvent函数,系统会自动调用。

    // 绘图事件
    void Widget::paintEvent(QPaintEvent*){
        // 实例化画家对象  this指定的是绘图的设备
        QPainter painter(this);
    
        // 设置画笔的颜色
        QPen pen(QColor(255, 0, 0));
        pen.setWidth(3); // 设置笔的宽度(粗细)
        pen.setStyle(Qt::DotLine); // 设置画笔风格 (DotLine为虚线)
    
        // 让画家使用这个笔
        painter.setPen(pen);
    
        // 画刷,封闭图形填充
        QBrush brush(QColor(0,255,0));
        // 设置画刷风格
        brush.setStyle(Qt::Dense7Pattern);
    
        // 让画家使用刷子
        painter.setBrush(brush);
    
        // 画线
        painter.drawLine(QPoint(0,0), QPoint(100,100));
        // 画圆
        painter.drawEllipse(QPoint(100,100), 50, 50); // 第二参数和第三参数相当于椭圆中的a和b系数
        // 画矩形
        painter.drawRect(QRect(20,20,60,50)); // 在20,20点画长为60宽为50的矩形
        // 画文字
        painter.drawText(QRect(10, 200, 200, 50), "好好学习,天天向上");
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    高级绘图

    // 绘图事件
    void Widget::paintEvent(QPaintEvent*){
        // 实例化画家对象  this指定的是绘图的设备
    	QPainter pain(this);
    
        pain.drawEllipse(QPoint(100,50), 50, 50);
    
        // 设置 抗锯齿能力,消除走样(线条更精细单效率下降)
        pain.setRenderHint(QPainter::Antialiasing);
        pain.drawEllipse(QPoint(200,50), 50, 50);
    
        pain.drawRect(QRect(100, 150, 60, 30));
        // 移动画家的起始位置
        pain.translate(200, 0);
        pain.drawRect(QRect(100, 150, 60, 30)); // 因为移动了画家的位置,所以这两个矩形不在同一个位置
        // 移动画家的起始位置
        pain.translate(200, 0);
        // 保存画家状态
        pain.save();
        pain.drawRect(QRect(100, 150, 60, 30));
        // 移动画家的起始位置
        pain.translate(200, 0);
        // 还原画家上一次状态
        pain.restore();
        pain.drawRect(QRect(100, 150, 60, 30)); // 因为移动了画家的位置,所以这两个矩形不在同一个位置
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    画资源图片

    // 绘图事件
    void Widget::paintEvent(QPaintEvent*){
        // 实例化画家对象  this指定的是绘图的设备
    	QPainter painter(this);
        painter.drawPixmap(posx, 100, QPixmap(":/img/2.jpg"));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    手动调用绘画事件

    Widget::Widget(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Widget)
    {
        ui->setupUi(this);
    
    
        connect(ui->pushButton, &QPushButton::clicked, this, [=](){
            posx+=20;
            // 如果要手动调用绘图事件,最好用update()更新
            update();
        });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    绘图设备

    绘图设备是指继承QPainterDevice的子类,Qt一共提供了4个这样的类。

    • QPixmap:专门为图像在屏幕上的显示做了优化。
    • QBitmap:是QPixmap的一个子类,它的色深限定为1,可以使用QPixmap的isQBitmap()函数来确定这个QPixmap是不是一个QBitmap。只有黑色和白色。
    • QImage:专门为图像的像素级访问做了优化。可以访问具体的像素点。
    • QPicture:则可以记录和重现QPainter的各条命令。
  • 相关阅读:
    k8s--基础--26.3--监控告警系统--prometheus--部署
    Linux基础(四)
    【一】工程配置与电机控制part1
    【开源】使用Python+Flask+Mysql快速开发一个用户增删改查系统
    某大厂高级测试岗位面试题...
    linux之线程
    数据库练习丽丽
    Servlet规范之部署描述符
    使用Uiautomator2进行APP自动化测试
    基于场景分析法的电动车优化调度(Matlab代码实现)
  • 原文地址:https://blog.csdn.net/Stars____/article/details/125535301