Qt学习笔记

目录

对象树

当创建一个对象在堆区时候,如果指定的父亲是QObject派生下来的类或者QObject子类派生下来的类,可以不用管理释放操作,该对象会放入到对象树中

一定程度上化简了内存回收机制

Qt学习笔记

示例代码

mypushbutton.h 文件

#ifndef MYPUSHBUTTON_H
#define MYPUSHBUTTON_H

#include <QPushButton>

class MyPushButton : public QPushButton
{
    Q_OBJECT
public:
    explicit MyPushButton(QWidget *parent = nullptr);

    ~MyPushButton();

signals:

};

#endif // MYPUSHBUTTON_H

mypushbutton.cpp 文件

#include "mypushbutton.h"
#include <QDebug>

MyPushButton::MyPushButton(QWidget *parent) : QPushButton(parent)
{
    qDebug() << "我的按钮调用";
}


MyPushButton::~MyPushButton()
{
    qDebug() << "我的按钮析构";
}

mywidget.h 文件

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class myWidget; }
QT_END_NAMESPACE

class myWidget : public QWidget
{
    Q_OBJECT        // Q_OBJECT宏,允许类中使用信号和槽的机制

public:
    myWidget(QWidget *parent = nullptr);   // 构造函数
    ~myWidget();            // 析构函数

private:
    Ui::myWidget *ui;
};
#endif // MYWIDGET_H

mywidget.cpp 文件

#include "mywidget.h"
#include "ui_mywidget.h"
#include "mypushbutton.h"
#include <QDebug>
#include <QPushButton>      // 按钮控件的头文件


//快捷键
//注释 ctrl + /
//运行 ctrl +r
//编译 ctrl + b
//字体缩放 ctrl + 鼠标滚轮
//查找 ctrl + f
//整行移动 ctr+l + shift + 箭头
//帮助文档 F1
//自动对齐 ctrl + i
//同名之间的.h和.cpp的切换 F4
//帮助文档 D:\QT\5.14.2\mingw73_32\bin


myWidget::myWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::myWidget)
{
    ui->setupUi(this);
    // 创建一个按钮
    QPushButton * btn = new QPushButton;
    //btn->show();    // show以顶层方式弹出窗口控件
    // 让btn对象 依赖在 myWidget 窗口中
    btn->setParent(this);

    // 显示文本
    btn->setText("第一个按钮");

    // 创建第二个按钮 按照控件的大小创建窗口
    QPushButton * btn2 = new QPushButton("第二个按钮", this);

    // 移动btn2按钮
    btn2->move(100, 100);

    // 重置窗口大小
    resize(600, 400);

    // 设置固定窗口大小
    setFixedSize(600, 400);

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


    // 创建一个自己的按钮对象
    MyPushButton * myBtn = new MyPushButton;
    myBtn->setText("我自己的按钮");
    myBtn->move(200, 0);
    myBtn->setParent(this);  // 设置到对象树中


    // 需求 点击我的按钮 关闭窗口
    // connect (信号的发送者,发送的具体信号,信号的接受者,信号的处理(槽))
    // 松散耦合:信号发送者和信号的接收者本身没有关联,通过connect连接将两端耦合在一起
    // 参数1 信号的发送者 参数2 发送的信号(函数的地址) 参数3 信号的接收者 参数4 处理的槽函数
    //connect(myBtn, &MyPushButton::clicked, this, &myWidget::close);
    connect(myBtn, &QPushButton::clicked, this, &QWidget::close);

}

myWidget::~myWidget()
{
    delete ui;

    qDebug() << "myWidget的析构";
}


main 文件

#include "mywidget.h"


#include <QApplication>        // 包含一个应用程序类的头文件

// 命令行变量的数目,命令行变量的内容
int main(int argc, char *argv[])
{
    // a应用程序对象,在QT中,应用程序对象有且只有一个
    QApplication a(argc, argv);


    // 窗口对象 myWidget父类 -> QWidget
    myWidget w;
    w.show();

    // 让应用程序对象进入消息循环,等待用户的操作
    // 让代码阻塞到这行
    return a.exec();
}

信号和槽

连接方式:connect

自定义信号和槽

自定义信号

  1. 写到signals下
  2. 返回void
  3. 需要声明,不需要实现
  4. 可以有参数,可以重载

自定义槽函数

  1. 返回void
  2. 需要声明,也需要实现
  3. 可以有参数,可以重载
  4. 可以写到public下

自定义信号和槽出现重载

  1. 需要利用函数指针,明确指向函数的地址
  2. void(Teacher:: *tSignal)(QString) = &Teacher::hungry;
  3. 信号可以连接信号
  4. 一个信号可以连接多个槽函数
  5. 信号和槽函数的参数必须类型一一对应
  6. 信号和槽的参数个数:信号的参数个数可以多于槽的参数个数,但是类型必须是一一对应

lambda表达式

  1. []标识符 匿名函数
  2. mutable 可以修改拷贝出的数据,改变不了本体
    Qt学习笔记

示例代码

widget.h 文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <teacher.h>
#include <student.h>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

    void classIsOver();

private:
    Ui::Widget *ui;
    Teacher* te;
    Student* st;
};
#endif // WIDGET_H

widget.cpp 文件

#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>



// Teacher 类   老师类
// Student 类   学生类
// 下课后,老师会触发一个信号,饿了,学生响应信号,请客吃饭
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 创建一个老师对象
    this->te = new Teacher(this);

    // 创建一个学生对象
    this->st = new Student(this);

    // 老师饿了,学生请客的连接
//    connect(te, &Teacher::hungry, st, &Student::treat);

//    // 调用下课函数
//    classIsOver();

    // 指针 -> 地址
    // 函数指针 -> 函数地址
    void(Teacher:: *teacherSignal)(QString) = &Teacher::hungry;
    void(Student:: *studentSlot)(QString) = &Student::treat;
    connect(te, teacherSignal, st, studentSlot);
    classIsOver();


    // 点击一个下课按钮,再出发下课
    QPushButton * btn = new QPushButton("下课", this);
    // 重置窗口大小
    resize(600, 400);

    // 点击按钮 触发下课
//    connect(btn, &QPushButton::clicked, this, &Widget::classIsOver);



    // 无参的信号和槽连接
    void(Teacher:: *teacherSignal2)(void) = &Teacher::hungry;
    void(Student:: *studentSlot2)(void) = &Student::treat;
    // 信号与信号连接,信号与槽连接
    connect(te, teacherSignal2, st, studentSlot2);
    connect(btn, &QPushButton::clicked, te, teacherSignal2);
    
    // 断开信号连接
    //disconnect(te, teacherSignal2, st, studentSlot2)

    // 拓展
    // 信号可以连接信号
    // 一个信号可以连接多个槽函数
    // 多个信号可以连接一个槽函数
    // 信号和槽函数的参数必须类型一一对应
    // 信号和槽的参数个数:信号的参数个数可以多于槽的参数个数,但是类型必须是一一对应

    // QT4 版本以前的信号和槽连接方式
    connect(te, SIGNAL(hungry()), st, SLOT(treat(QString)));


	[=](){
        // 指针指向的是同一个区域,所以值传递也可以修改
        btn->setText("aaaaa");
    }();
    
//    [btn](){
//        // 指针指向的是同一个区域,所以值传递也可以修改
//        btn->setText("aaaaa");
//    }();

	// 利用lambda表达式实现点击按钮 关闭窗口
    QPushButton * btn2 = new QPushButton;
    btn2->setText("关闭");
    btn2->move(100, 0);
    btn2->setParent(this);

//    connect(btn2, &QPushButton::click, this, &Widget::close);
    connect(btn2, &QPushButton::clicked, this, [=](){
//        this->close();
        emit te->hungry("宫保鸡丁");
        btn2->setText("aaa");
    });

	// lambda表达式 最常用 [=](){} 

}

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


void Widget::classIsOver()
{
    // 下课函数,调用后,触发老师饿了信号
//    emit te->hungry();
    emit te->hungry("宫保鸡丁");
}

teacher.h 文件

#ifndef TEACHER_H
#define TEACHER_H

#include <QObject>

class Teacher : public QObject
{
    Q_OBJECT
public:
    explicit Teacher(QObject *parent = nullptr);

signals:
    // 自定义信号,写到singals下
    // 返回值是void,只需要声明,不需要实现
    // 可以有参数,可以重载
    void hungry();
    void hungry(QString foodName);


};

#endif // TEACHER_H

teacher.cpp 文件

#include "teacher.h"

Teacher::Teacher(QObject *parent) : QObject(parent)
{

}

student.h 文件

#ifndef STUDENT_H
#define STUDENT_H

#include <QObject>

class Student : public QObject
{
    Q_OBJECT
public:
    explicit Student(QObject *parent = nullptr);
    // 返回值是void
    // 需要声明,也需要实现
    // 可以参数,也可以重载
    void treat();

    void treat(QString foodName);

signals:

};

#endif // STUDENT_H

student.cpp 文件

#include "student.h"
#include <QDebug>

Student::Student(QObject *parent) : QObject(parent)
{

}


void Student::treat()
{
    qDebug() << "请客吃饭";
}

void Student::treat(QString foodName)
{
    // QString -> char *  打印出来不带指针
    // 先转成QByteArray(.toUtf8())再转成char *()(.data())
    qDebug() << "请客吃饭,吃" << foodName.toUtf8().data();
}

main 文件

#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

第一次作业

widget.h 文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

widget.cpp 文件

#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QWidget>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QPushButton * btn = new QPushButton("open", this);
    btn->move(100, 200);
    QPushButton * btn2 = new QPushButton("close", this);
    btn2->move(300, 200);
    resize(500, 500);
    setWindowTitle("作业");

    QWidget * newWidget = new QWidget;

//    connect(btn, &QPushButton::clicked, newWidget, [=](){
//        newWidget->show();
//    });

//    connect(btn2, &QPushButton::clicked, newWidget, [=](){
//        newWidget->close();
//    });

    connect(btn, &QPushButton::clicked, newWidget, [=](){
        if(btn->text()=="open"){
            newWidget->show();
            btn->setText("close");
        }else{
            newWidget->close();
            btn->setText("open");
        }
    });

}

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

main 文件

#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

QMAINWINDOW

Qt学习笔记

示例代码

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMenuBar>
#include <QToolBar>
#include <QDebug>
#include <QPushButton>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // 重置窗口大小
    resize(600, 400);

    // 菜单栏最多只能有一个
    // 菜单栏创建
    QMenuBar * bar = new QMenuBar();
    // 将菜单栏放入到窗口中
    setMenuBar(bar);


    // 创建菜单
    QMenu *fileMenu = bar->addMenu("文件");
    QMenu *editMenu = bar->addMenu("编辑");

    // 创建菜单项
    QAction * newAction = fileMenu->addAction("新建");
    // 添加分割线
    fileMenu->addSeparator();
    QAction * newAction2 = fileMenu->addAction("打开");


    // 工具栏  可以有多个
    QToolBar * toolBar = new QToolBar(this);
    // 将工具栏放入到窗口中(修改默认停靠位置)
    addToolBar(Qt::LeftToolBarArea, toolBar);

    // 后期设置,只允许左右停靠
    toolBar->setAllowedAreas(Qt::LeftToolBarArea|Qt::RightToolBarArea);
    // 设置浮动
    toolBar->setFloatable(false);
    // 设置移动(总开关)
    toolBar->setMovable(false);

    // 工具栏中设置内容
    toolBar->addAction(newAction);
    // 添加分割线
    toolBar->addSeparator();
    toolBar->addAction(newAction2);  // 相当于功能公用
    
    // 工具栏中添加控件
    QPushButton * btn = new QPushButton("aaa", this);
    toolBar->addWidget(btn);



    // 状态栏  最多只能有一个
    QStatusBar * stBar = statusBar();
    // 设置到窗口中
    setStatusBar(stBar);
    // 放标签控件
    QLabel * label = new QLabel("提示信息", this);
    stBar->addWidget(label);

    QLabel * label2 = new QLabel("右侧提示信息", this);
    stBar->addPermanentWidget(label2);



    // 铆接部件(浮动窗口)   可以有多个(有多个的是add,只能有一个的是set)
    QDockWidget *dockWidget = new QDockWidget("浮动", this);
    // 将默认浮动位置设置为下面(核心窗口的下面)
    addDockWidget(Qt::BottomDockWidgetArea, dockWidget);
    // 设置后期停靠区域,只允许上下
    dockWidget->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
    



    // 设置中心部件 只能有一个
    QTextEdit * edit = new QTextEdit(this);
    setCentralWidget(edit);


}

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


资源文件的添加

  1. 将资源文件拷贝到项目位置下
  2. 右键项目—添加新文件—Qt—Qt resource file—给资源文件起名
  3. res 生成res.qrc
  4. open in edit 编辑资源
  5. 添加前缀 添加文件
  6. 使用 “:+ 前缀名 + 文件名”

对话框

示例代码

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>
#include <QDebug>

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

    // 点击新建按钮 弹出一个对话框
    connect(ui->actionnew, &QAction::triggered, [=](){
        // 对话框 分类
        // 模态对话框(不可以对其他窗口进行操作)   非模态对话框(可以对其他窗口进行操作)


        // 模态对话框创建
        // 这里不使用指针了吗   注意使用指针有可能造成内存泄露(频繁多次点击)
//        QDialog * dig = new QDialog(this);
//        // 设置大小
//        dig->resize(200, 100);

//        // 只有按x才能继续执行
//        dig->exec();

//        qDebug() << "模态对话框弹出了";



        // 非模态对话框  必须要放到堆区中
        QDialog * dig2 = new QDialog(this);
        dig2->resize(200, 100);
        dig2->show();
        // 防止对象无限创建
        dig2->setAttribute(Qt::WA_DeleteOnClose);
        qDebug() << "非模态对话框弹出";


		// 消息对话框
        // 错误对话框
        //QMessageBox::critical(this, "critial", "错误");

        // 信息对话框
        //QMessageBox::information(this, "info", "信息");

        // 提问对话框
        // 参数1 父亲 参数2 标题 参数3 提示内容 参数4 按键类型 参数5 默认关联回车按键
        // 可以利用返回值判断用户的输入
//        if(QMessageBox::Save == QMessageBox::question(this, "ques", "提问", QMessageBox::Save | QMessageBox::Cancel, QMessageBox::Cancel))
//        {
//            qDebug() << "选择的是保存";
//        }else{
//            qDebug() << "选择的是取消";
//        }


        // 警告对话框
        QMessageBox::warning(this, "warning", "警告");

        // 其他标准对话框
        // 颜色对话框
//        QColor color = QColorDialog::getColor(QColor(255, 0, 0));
//        qDebug() << "r=" << color.red() << " g=" << color.green() << " b=" << color.blue();



        // 文件对话框(注意要使用\\)    参数1 父亲   参数2 标题    参数3 默认打开路径  参数4 过滤文件格式
        // 返回值是选取的路径
//        QString str = QFileDialog::getOpenFileName(this, "打开文件", "C:\\Users\\Administrator\\Desktop", "(*.txt)");
//        qDebug() << str;


        // 字体对话框
        bool flag;
        QFont font = QFontDialog::getFont(&flag, QFont("华文彩云", 36));
        qDebug() << "字体:" << font.family().toUtf8().data() << " 字号:" << font.pointSize() << " 是否加粗:" << font.bold();
    });

}

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


界面布局

  1. 实现一个登录窗口
  2. 利用布局的方式对窗口进行美化
  3. 选取widget进行布局,水平布局、垂直布局、栅格布局
  4. 给用户名、密码、登录、退出按钮进行布局
  5. 默认窗口和控件之间有9像素的间隙,可以调整layoutleftMargin
  6. 利用弹簧进行布局
  7. 垂直策略设置为fixed

控件

按钮组

  1. QPushButton 常用按钮
  2. QtoolButton 工具按钮 用于显示图片,如果想提示文字,修改风格:toolButtonStyle,凸起风格:autoRaise
  3. radioButton 单选按钮,设置默认 ui->rBtnMan->setChecked(this)
  4. checkBox 多选按钮,监听状态,2选中,1半选,0未选中

QListWidget 列表容器

  1. QListWidgetitem * item 一行内容
  2. ui->listWidget->additem(item)
  3. 设置居中方式 item->setTextAlignment(Qt::AlignHCenter)
  4. 可以利用additems一次性添加整个诗内容

示例代码

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QCheckBox>
#include <QListWidget>

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

    // 设置单选按钮 男默认选中
    ui->rBtnMan->setChecked(true);

    // 选中女后 打印信息
    connect(ui->rBtnWoman, &QRadioButton::clicked, [=](){
        qDebug() << "选中了女了!";
    });


    // 多选按钮     2是选中,0是未选中
    connect(ui->cBox, &QCheckBox::stateChanged, [=](int state){
        qDebug() << state;
    });

    // 利用listWidfet写诗
//    QListWidgetItem * item = new QListWidgetItem("锄禾日当午");
//    // 将一行诗放入到listWidget中
//    ui->listWidget->addItem(item);
//    item->setTextAlignment(Qt::AlignHCenter);


    // QStringList  QList<QString>
    QStringList list;
    list << "锄禾日当午" << "汗滴禾下土" << "谁知盘中餐" << "粒粒皆辛苦";
    ui->listWidget->addItems(list);

}

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


树控件

  1. 设置头
  2. 设置根节点
  3. 添加根节点
  4. 追加子节点

示例代码

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

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

    // treeWidget树控件使用
    // 设置水平头
    ui->treeWidget->setHeaderLabels(QStringList() << "英雄" << "英雄介绍");

    QTreeWidgetItem * item = new QTreeWidgetItem(QStringList() << "力量");
    // 加载顶层节点
    ui->treeWidget->addTopLevelItem(item);
    QTreeWidgetItem * item1 = new QTreeWidgetItem(QStringList() << "敏捷");
    QTreeWidgetItem * item2 = new QTreeWidgetItem(QStringList() << "智力");
    ui->treeWidget->addTopLevelItem(item1);
    ui->treeWidget->addTopLevelItem(item2);


    // 追加子节点
    QStringList heroL1;
    heroL1 << "刚被猪" << "前排坦克,能在吸收伤害的同时造成可观的范围输出";
    QTreeWidgetItem * l1 = new QTreeWidgetItem(heroL1);
    item->addChild(l1);
}

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


QTableWidget 表格控件

  1. 设置列数
  2. 设置水平表头
  3. 设置行数
  4. 设置正文

示例代码

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

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


    // TableWidget控件
    // 设置列数
    ui->tableWidget->setColumnCount(3);

    // 设置水平表头
    ui->tableWidget->setHorizontalHeaderLabels(QStringList() << "姓名" << "性别" << "年龄");

    // 设置行数
    ui->tableWidget->setRowCount(5);

    // 设置正文
    ui->tableWidget->setItem(0, 0, new QTableWidgetItem("亚瑟"));
    QStringList nameList;
    nameList << "亚瑟" << "赵云" << "张飞" << "关羽" << "花木兰";

    QList<QString> sexList;
    sexList << "男" << "男" << "男" << "男" << "女";

    for(int i = 0; i < 5; ++i){
        int col = 0;
        ui->tableWidget->setItem(i, col++, new QTableWidgetItem(nameList[i]));
        ui->tableWidget->setItem(i, col++, new QTableWidgetItem(sexList.at(i)));
        // int 转 QString
        ui->tableWidget->setItem(i, col++, new QTableWidgetItem(QString::number(i+18)));
    }

}

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


其他控件介绍

  1. stackedWidget 控件
  2. 下拉框
  3. QLabel 显示图片
  4. QLabel 显示动图 gif图片

示例代码

#include "widget.h"
#include "ui_widget.h"
#include <QPixmap>
#include <QMovie>

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

    // 栈控件使用
    // 设置默认定位到scrollArea
    ui->stackedWidget->setCurrentIndex(0);

    // scrollArea按钮
    connect(ui->btn_scrollArea, &QPushButton::clicked, [=](){
       ui->stackedWidget->setCurrentIndex(0);
    });

    // toolBox按钮
    connect(ui->btn_toolBox, &QPushButton::clicked, [=](){
       ui->stackedWidget->setCurrentIndex(1);
    });

    // 下拉框
    ui->comboBox->addItem("奔驰");
    ui->comboBox->addItem("宝马");
    ui->comboBox->addItem("拖拉机");

    // 点击按钮选中拖拉机选项
    connect(ui->btn_select, &QPushButton::clicked, [=](){
        //ui->comboBox->setCurrentIndex(2);
        ui->comboBox->setCurrentText("拖拉机");
    });


    // 利用QLabel显示图片
    ui->label->setPixmap(QPixmap(":/image/770761.jpg"));

    // 利用QLabel显示gif动态图片
    QMovie * movie = new QMovie(":/");
    ui->lbl_movie->setMovie(movie);
    // 播放动图
    movie->start();

}

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


自定义控件封装

  1. 添加一个新文件 Qt设计师界面类
  2. ui中设计 QSpinBox 和 QSlider 两个控件
  3. Widget 中使用自定义控件,拖曳一个Widget,点击提升为,点击添加,点击提升
  4. 实现功能,改变数字,滑动条跟着移动,信号槽监听
  5. 提供 getNum() 和 setNum() 接口

示例代码

Widget.h 文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

Widget.cpp 文件

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>

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

    // 点击获取  获取到控件当前的值
    // 这里的widget就是smallwidget
    connect(ui->btn_get, &QPushButton::clicked, [=](){
        qDebug() << ui->widget->getNum();
    });


    // 设置到一半
    connect(ui->btn_set, &QPushButton::clicked, [=](){
        ui->widget->setNum(50);
    });

}

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


smallWidget.h 文件

#ifndef SMALLWIDGET_H
#define SMALLWIDGET_H

#include <QWidget>

namespace Ui {
class SmallWidget;
}

class SmallWidget : public QWidget
{
    Q_OBJECT

public:
    explicit SmallWidget(QWidget *parent = nullptr);
    ~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);

    // QSpinBox移动 QSlider跟着移动
    void(QSpinBox:: * spSignal)(int) = &QSpinBox::valueChanged;
    connect(ui->spinBox, spSignal, ui->horizontalSlider, &QSlider::setValue);


    // QSlider滑动, QSpinbox数字跟着改变
    connect(ui->horizontalSlider, &QSlider::valueChanged, ui->spinBox, &QSpinBox::setValue);

}


// 设置数字
void SmallWidget::setNum(int num)
{
    ui->spinBox->setValue(num);
}

// 获取数字
int SmallWidget::getNum()
{
    return ui->spinBox->value();
}

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

main 文件

#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

鼠标事件

  1. 鼠标进入事件 enterEvent
  2. 鼠标离开事件 leaveEvent
  3. 鼠标按下事件 mousePressEvent
  4. 鼠标释放事件 mouseReleaseEvent
  5. 鼠标移动事件 mouseMoveEvent
  6. ev->x() x坐标 ex->y() y坐标
  7. ex->button() 可以判断所有按键 Qt::LeftButton
  8. ev->buttons()判断组合按键 判断 move 时候的左右键

示例代码

myLabel.h 文件

#ifndef MYLABEL_H
#define MYLABEL_H

#include <QLabel>

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

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

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

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

    // 鼠标按下事件
    void mousePressEvent(QMouseEvent *ev) override;

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

signals:

};

#endif // MYLABEL_H

myLabel.cpp 文件

#include "mylabel.h"
#include <QDebug>
#include <QMouseEvent>

myLabel::myLabel(QWidget *parent) : QLabel(parent)
{
    // 设置鼠标追踪状态
    setMouseTracking(true);
}


// 鼠标进入事件
void myLabel::enterEvent(QEvent *event)
{
    //qDebug() << "鼠标进入";
}

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


// 鼠标移动事件
void myLabel::mouseMoveEvent(QMouseEvent *ev)
{
//    if(ev->buttons() & Qt::LeftButton)
//    {
        QString  str = QString("鼠标移动 x = %1  y = %2  globalX = %3  golbalY = %4 ").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug() <<  str;
//    }
}

// 鼠标按下事件
void myLabel::mousePressEvent(QMouseEvent *ev)
{
    // 当鼠标左键按下 提示信息
    if(ev->button() == Qt::LeftButton)
    {
        QString  str = QString("鼠标按下 x = %1  y = %2  globalX = %3  golbalY = %4 ").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug() <<  str;
    }
}

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

定时器1

  1. 利用事件 void timerEvent( QTimerEvent * ev)
  2. 启动定时器 start(1000) 毫秒单位

示例代码

widget.h 文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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


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

private:
    Ui::Widget *ui;
    int id1;            // 定时器1的唯一标识
    int id2;            // 定时器2的唯一标识
};
#endif // WIDGET_H

widget.cpp 文件

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

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 num3 = 1;
        ui->label_4->setText(QString::number(num3++));
    });

    // 点击暂停按钮 停止定时器
    connect(ui->btn, &QPushButton::clicked, [=](){
        timer->stop();
    });



    // 给 label1 安装事件过滤器
    // 步骤1 安装事件过滤器
    ui->label->installEventFilter(this);
    // 步骤2 重写eventfilter事件
}

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

void Widget::timerEvent(QTimerEvent * ev)
{
    if(ev->timerId() == id1)
    {
        // label2每隔1秒+1
        static int num = 1;
        ui->label_2->setText(QString::number(num++));
    }

    if(ev->timerId() == id2)
    {
        // label3每隔2秒+1
        static int num2 = 1;
        ui->label_3->setText(QString::number(num2++));
    }

}

定时器2

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

event事件

  1. 用途:用于事件分发
  2. 也可以做拦截操作 不建议
  3. bool event(QEvent * e)
  4. 返回值 如果是 true 代表用户处理这个事件,不向下分发了
  5. e->type() == 鼠标按下
    Qt学习笔记

事件过滤器

  1. 在程序将事件分发到事件分发器前,可以利用过滤器做拦截
  2. 步骤:1. 给控件安装事件过滤器 2. 重写eventFilter函数(obj, ev)
    Qt学习笔记

QPainter 绘图

  1. 绘图事件 void paintEvent()
  2. 声明一个画家对象 QPainter painter(this) this 指定绘图设备
  3. 画线、画圆、画矩形、画文字
  4. 设置画笔 QPen 设置画笔宽度、风格
  5. 设置画刷 QBrush 设置画刷风格

示例代码

Widget.h 文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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


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

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

Widget.cpp 文件

#include "widget.h"
#include "ui_widget.h"
#include <QPainter>  // 画家类

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


	// 点击移动按钮, 移动图片
    connect(ui->pushButton, &QPushButton::clicked, [=](){
        posX += 20;
        // 如果要手动调用绘图事件,用update更新
        update();
    });
}

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

// 绘图事件
void Widget::paintEvent(QPaintEvent *)
{
    // 实例化画家对象 this指定的是绘图的设备
    QPainter painter(this);

    // 设置画笔
    QPen pen(QColor(255, 0, 0));
    // 设置画笔的宽度
    pen.setWidth(3);
    pen.setStyle(Qt::DotLine);
    // 让画家 使用这个笔
    painter.setPen(pen);


    // 设置画刷
    QBrush brush(Qt::green);
    // 设置画刷风格
    brush.setStyle(Qt::Dense7Pattern);
    // 让画家使用画刷
    painter.setBrush(brush);

    // 画线
    painter.drawLine(QPoint(0, 0), QPoint(100, 100));

    // 画圆
    painter.drawEllipse(QPoint(100, 100), 50, 50);

    // 画矩形
    painter.drawRect(QRect(20, 20, 50, 50));

    // 画文字
    painter.drawText(QRect(10, 200, 150, 50), "好好学习, 天天向上");

    // 高级设置
    QPainter painter(this);
//    painter.drawEllipse(QPoint(100, 50), 50, 50);
//    // 设置抗锯齿能力  效率较低
//    painter.setRenderHint(QPainter::Antialiasing);
//    painter.drawEllipse(QPoint(200, 50), 50, 50);
    painter.drawRect(QRect(20, 20, 50, 50));

    painter.translate(100, 0);
    // 保存画家状态
    painter.save();
    painter.drawRect(QRect(20, 20, 50, 50));

    painter.translate(100, 0);
    // 还原画家状态
    painter.restore();
    painter.drawRect(QRect(20, 20, 50, 50));


    // 利用画家来画资源图片
    QPainter painter(this);

    // 如果超出了屏幕 从0开始
    if(posX > this->width()){
        posX = 0;
    }
    painter.drawPixmap(posX, 0, QPixmap(":/image/770761.jpg"));

}

QPainter 高级设置

  1. 抗锯齿 效率低 painter.setRenderHint(QPainter::Antialiasing);
  2. 画家进行移动 painter translate(100, 0);
  3. 状态保存 painter.save()
  4. 状态还原 painter.restore()
  5. 如果想手动调用绘图事件,利用update
  6. 利用画家画图片, painter.drawPixmap(posX, 0, QPixmap(":/image/770761.jpg"));

QPainter 绘图设备

  1. QPixmap QImage QBitmap(黑白色) QPicture QWidget
  2. QPixmap 对不同平台做了显示的优化
  3. QImage 可以对像素进行访问
  4. QPicture 记录和重现绘图指令 可以保存任意后缀名

示例代码

widget.cpp 文件

#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QPixmap>
#include <QImage>
#include <QRgb>
#include <QPicture>

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

    // Pixmap 绘图设备 专门为平台做了显示的优化
//    QPixmap pix(300, 300);

//    // 背景填充
//    pix.fill(Qt::white);
//    QPainter painter(&pix);

//    painter.setPen(QPen(Qt::green));
//    painter.drawEllipse(QPoint(150, 150), 100, 100);


//    // 保存
//    pix.save("D:\\pix.png");

    // QImage 绘图设备  可以对每个像素点进行访问
//    QImage img(300, 300, QImage::Format_RGB32);
//    // 底色填充
//    img.fill(Qt::white);

//    QPainter painter(&img);
//    painter.setPen(QPen(Qt::green));
//    painter.drawEllipse(QPoint(150, 150), 100, 100);

//    img.save("D:\\img.png");


    // Qpicture 绘图设备 可以记录和重现绘图指令
    QPicture pic;
    QPainter painter;
    painter.begin(&pic);       // 开始pic上画画
    painter.setPen(QPen(Qt::cyan));
    painter.drawEllipse(QPoint(150, 150), 100, 100);
    painter.end();      // 结束画画

    pic.save("D:\\pic.zt");

}

// 绘图事件
void Widget::paintEvent(QPaintEvent *event)
{
//    // 利用QImage 对像素进行修改
//    QPainter painter(this);
//    QImage img;
//    img.load(":/image/770761.jpg");


//    // 修改像素点
//    for(int i = 50; i< 100; ++i){
//        for(int j = 50; j<100; ++j){
//            QRgb value = qRgb(255, 0, 0);
//            img.setPixel(i, j, value);
//        }
//    }
//    painter.drawImage(0, 0, img);

    // 重现QPicture的绘图指令
    QPainter painter(this);
    QPicture pic;
    pic.load("D:\\pic.zt");
    painter.drawPicture(0, 0, pic);




}

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


QFile

  1. 对文件进行读写操作
  2. QFile file( path 文件路径)
  3. 读 file.open(打开方式) QIODevice::ReadOnly
  4. 默认支持编码格式utf-8,也可以利用编码格式类指定编码格式

示例代码

#include "widget.h"
#include "ui_widget.h"
#include <QFileDialog>
#include <QTextCodec>


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

    // 点击选取文件按钮,弹出文件对话框
    connect(ui->pushButton, &QPushButton::clicked, [=](){
        QString path = QFileDialog::getOpenFileName(this, "打开文件", "D:\\");
        // 将路径放入到LineEdit中
        ui->lineEdit->setText(path);

        // 编码格式类
        //QTextCodec * codec = QTextCodec::codecForName("gbk");
        // 读取内容 放入到textEdit中
        // QFile默认支持的格式是utf-8
        QFile file(path);
        file.open(QIODevice::ReadOnly);

        //QByteArray array = file.readAll();

        QByteArray array;
        while(!file.atEnd()){
            array += file.readLine();   // 按行读
        }

        ui->textEdit->setText(array);
        //ui->textEdit->setText(codec->toUnicode(array));

        // 对文件对象进行关闭
        file.close();

        // 进行写文件
        // 用追加的方式进行写
        file.open(QIODevice::Append);
        file.write("啊啊啊");
        file.close();

 		// QFileInfo 文件信息类
        QFileInfo info(path);
        qDebug() << "大小:" << info.size() << " 后缀名:" << info.suffix() << " 文件名称:" << info.fileName() << " 文件路径:" << info.filePath();
        qDebug() << "创建日期:" << info.created().toString("yyyy/MM/dd hh:mm:ss");
        qDebug() << "最后修改日期:" << info.lastModified().toString("yyyy/MM/dd hh:mm:ss");

    });
}

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


翻金币项目

1. 项目基本配置

  1. 设置背景图标
  2. 设置固定大小
  3. 设置项目标题
  4. 设置背景
  5. 设置背景标题
  6. 开始菜单 - 退出功能

2. 创建开始按钮

  1. 封装自定义按钮 MyPushButton
  2. 构造函数封装
  3. 测试开始按钮
  4. 开始制作特效
  5. zoom1 向下
  6. zoom2 向上

3. 创建选择关卡场景

  1. 点击开始按钮后,延时进入到 选择关卡场景
  2. 配置选择关卡场景(图标、标题、大小)
  3. 设置背景图片、设置标题、图片
  4. 设置返回按钮

4. 选择关卡返回按钮特效操作

  1. 点击后切换另一张图片
  2. 重写 mousePressEvent
  3. 重写 mouseReleaseEvent

5. 开始场景与选择关卡场景的切换

  1. 点击选择关卡场景的返回按钮,发送一个自定义信号
  2. 在主场景中监听

6. 选择关卡中的按钮创建

  1. 利用一个 for 循环将所有按钮布置到场景中
  2. 在按钮上面设置一个 QLabel 显示关卡数
  3. QLabel 设置大小、显示文字、对齐方式、鼠标穿透
  4. 给每个按钮设置一个监听点击事件

7. 翻金币场景创建

  1. 点击选择关卡按钮后,进入到翻金币游戏场景
  2. 配置翻金币游戏场景 设置标题、图标、大小、设置背景
  3. 实现返回按钮
  4. 实现三个场景之间的切换

8. 实现显示关卡的Level标签

9. 创建金币类

  1. 先将金币的背景图案 放入到playScene中
  2. 创建MyCoin自定义金币按钮类
  3. MyCoin::MyCoin[QString btnImg] 构造函数传入默认显示的图片金币
  4. 在playScene中创建所有的金币

10. 每个关卡的默认显示

  1. 先引入 dataConfig.h 和 dataConfig.cpp 文件到项目中
  2. 在 PlayScene 中写了 int GameArray[4][4]的数组 维护每个关卡的金币状态
  3. 初始化每个关卡的显示

11. 金币翻转特效

  1. 给每个硬币加属性 posX坐标 posY坐标 bool flag 正反面标志
  2. 给 MyCoin 加函数 changeFlag改变标志

12. 解决快速点击的效果不好

  1. 在 MyCoin 中加入了 isAnimation 判断 是否正在做动画条件
  2. 当按下 MyCoin 判断是否在做动画,如果做动画,直接return,保证金币和银币动态切换的完成效果

13. 反转周围金币

  1. 点击金币后,延时翻转周围金币

14. 胜利图片特效

  1. 将胜利图片放入到游戏场景外
  2. 当游戏胜利时,移动到屏幕*
上一篇:MySQL安装以及与Navicat建立连接出现1251错误


下一篇:为什么说“除非深思熟虑,尽量使用 notifyAll(),kotlin函数式接口