零基础Qt笔记<传智教育>Qt版本:2022 5.15

目录

1、创建第一个Qt程序

2、命名规范以及快捷键

3、QPushBottom的创建

4、对象树

5、Qt中的坐标系

6、信号和槽

6.1 实现点击按钮关闭窗口

6.2 自定义的信号和槽

6.3 自定义的信号和槽发生重载的解决

6.4 信号连接信号

6.5 Qt4版本信号连接

6.5 Lambda表达式

6.6 信号槽的总结

7、QMainWindow

7.1 菜单栏和工具栏

7.2 状态栏、铆接部件、核心部件 

8、资源文件的添加 

9、模态和非模态对话框创建

10、消息对话框

11、其他对话框

12、登陆窗口布局

13、控件

13.1 按钮组

13.2 QListWidget控件

13.3 QTreeWidget控件

13.4 QTableWidget控件

13.5 其他控件介绍

14、自定义控件

15、Qt的鼠标事件

16、定时器

17、event 事件分发器和事件过滤器 

​编辑

18、QPainter

18.1 绘图事件 

18.2 绘图高级设置

18.3 手动调用绘图事件

18.4 绘图设备 

19、QFile文件读写操作

文件QFile和文件信息读写QFileInfo

20、翻金币项目 

 ***问题总结


1、创建第一个Qt程序

Create Project->Qt Widgets Application(创建一个Qt应用,包含一个基于qt设计师的主窗体)

->Location(不能有空格和中文,可以有下划线),路径选择不能有中文(重要!!!)->Build System(选择qmake,ps:一般的Qt工程你就直接使用qmake就可以了,cmake的强大功能一般人是用不到的 //参考的另一篇博客)->Details(QWidget是QDialog和QMainWindow的父类,Qwidget是空窗口,QMainWindow多了工具栏,QDialog是对话框),选择QWidget作为基类,取消Generate form使用代码编写。->Kits(选择套件)->Summary(finish)团队开发时,添加到版本控制系统(svn,vss,git)

 main函数代码

#include "mywidget.h"

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

// main程序入口 argc命令行变量的数量 argv命令行变量的数组
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);// a应用程序对象,在qt中,有且仅有一个
    MyWidget w;// 创建窗口对象,MyWidget的父类->QWidget
    w.show();// 窗口对象 默认不会显示,必须调用show方法显示
    return a.exec();//让应用程序对象a进入消息循环机制,等待用户点叉叉,使得窗口不会一闪而过,使代码阻塞到这一行
}

2、命名规范以及快捷键

.pro文件不要添加任何东西,除非你知道写的是什么。.pro文件就是工程文件,它是qmake自动生

成的用于生产makefile的配置文件。

QT       += core gui //Qt包含的模块

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets//大于4版本以上,包含widget模块

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
//源文件
SOURCES += \
    main.cpp \
    mywidget.cpp
//头文件 自动生成的
HEADERS += \
    mywidget.h

Qt基本模块

 mywidget.h

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QWidget>//窗口类头文件 QWidget

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

public:
    MyWidget(QWidget *parent = nullptr); // 有参构造函数
    ~MyWidget();
};
#endif // MYWIDGET_H

mywidget.cpp 

#include "mywidget.h"

// 命名规范
// 类名 首字母大写,单词和单词之间首字母大写
// 函数名 变量名称 首字母小写,单词和单词之间首字母大写

// 快捷键
// 注释 ctrl + /
// 运行 ctrl + r
// 编译 ctrl + b
// 字体缩放 ctrl + 鼠标滚轮
// 查找 ctrl + f
// 整行移动 ctrl + shift + ⬆或者⬇
// 帮助文档 F1
// 自动对齐 ctrl + i
// 同名之间的.h和.cpp切换 F4

// 帮助文档,左侧的帮助;在Qt5.16\mingw49_32\bin的Qt助手

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)// 初始化列表
{
}

MyWidget::~MyWidget()
{
}

3、QPushBottom的创建

 构造函数里创建

#include "mywidget.h"
#include <QPushButton>

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)// 初始化列表
{
    // 创建一个按钮
    QPushButton * btn = new QPushButton;
    // btn->show();// show以顶层方式弹出窗口控件
    // 让btn对象 依赖在 MyWdget窗口中
    btn->setParent(this);

    // 显示文本
    btn->setText("first button");

    // 创建第二个按钮 按照控件的大小创建窗口
    QPushButton * btn2 = new QPushButton("second button",this);
    // 重置窗口大小 长x宽
    resize(600,400);
    
    // 移动btn2按钮,设置坐标
    btn2->move(100,100);
    
    // 设置固定窗口大小,用户不能改变串窗口大小
    setFixedSize(600,400);
    
    // 设置窗口标题
    setWindowTitle("第一个窗口");

}

MyWidget::~MyWidget()
{
}

4、对象树

父类先构造,子类先析构

在Qt中创建对象的时候会提供一个Parent对象指针。

QObject是以对象树的形式组织起来的。

当你创建一个QObject对象时候,会看到QObject的构造函数接收一个QObject指针作为参数,这个参数就是Parent,也就是父对象指针。

这相当于,在创建QObject对象时,可以提供一个其父对象,我们创建的这个QObject对象会自动添加到其父类对象的children()列表。

当父类对象析构的时候,这个列表中的所有对象也会被析构(注意:这里的父对象并不是继承意义的父类

QWdget是能够在屏幕上显示的一切组件的父类。
QWidget继承自QObject,因此也继承了这种对象树关系。一个孩子自动地成为父组件的一个子组件。因此,它会显示在父组件的坐标系统中,被父组件的边界剪裁。例如,当用户关闭一个对话框的时侯,应用程序将共刑除,那么,我们希望属于这个对话框的按钮、图标等应该一起被迸除。事实就是如此,因为这些都是对话框的子组件。

 MyPushButton类的创建

#ifndef MYPUSHBUTTON_H
#define MYPUSHBUTTON_H

#include <QPushButton>//继承QPushButton,没有这个选择就先选择继承它的父亲

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

    ~MyPushButton();

signals:

};

#endif // MYPUSHBUTTON_H
#include "mypushbutton.h"
#include <QDebug>//打印输出

MyPushButton::MyPushButton(QWidget *parent)
    : QPushButton(parent)//换父亲
{
    qDebug()<<"我的按钮类构造调用";
}

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

打印先打印的是儿子的析构,但是是后面释放。 

#include "mywidget.h"
#include <QPushButton>
#include <mypushbutton.h>
#include <QDebug>//打印输出
MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)// 初始化列表
{

    // 创建一个自己的按钮对象
    MyPushButton *mybtn = new MyPushButton;
    mybtn->setText("我自己的按钮");
    mybtn->move(200,0);
    mybtn->setParent(this);
    qDebug()<<"MyWidget构造";
}

MyWidget::~MyWidget()
{
    qDebug()<<"MyWidget析构";
}


总结:当创建的对象在堆区时候,如果指定的父亲是QObject派生下来的类或者QObject子类派生下来的类,可以不用管理释放的操作(就是不用deletex),将对象会放入到对象树中。一定程度上简化了内存回收机制

5、Qt中的坐标系

左上角为(0,0),x向右增大,y向下增大

6、信号和槽

6.1 实现点击按钮关闭窗口

connect( 信号的发送者,发送的具体信号,信号的接受者,信号的处理(槽))

信号槽的优点:松散耦合,信号发送端和接受端本身是没有关联的,通过connect连接将两端耦合在一起。 

#include "mywidget.h"
#include <QPushButton>
#include <mypushbutton.h>
#include <QDebug>//打印输出
MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)// 初始化列表
{

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

    // 点击我的按钮,关掉窗口
    // 参数1:信号的发送者,参数2:发送的具体信号(点击)函数的地址;参数3:信号的接受者this窗口,参数4:信号的处理(槽)函数地址
    connect(mybtn,&MyPushButton::clicked,this,&MyWidget::close);
    //connect(mybtn,&QPushButton::clicked,this,&QWidget::close);// 用父类的也可以
}

MyWidget::~MyWidget()
{
}

6.2 自定义的信号和槽

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

自定义槽:早期Qt槽函数必须写在public slot下,高级版本可以写道public或者全局下;返回值是void,需要声明,也需要实现;可以有参数,可以重载。

触发自定义信号:emit

#include "widget.h"

// Teacher 类 老师类
// Student 类 学生类
// 下课后,老师会触发一个信号,饿了,学生响应信号,请客吃饭

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    // 创建老师和学生对象,并且指定父亲,就不用释放
    this->zt = new Teacher(this);
    this->st = new Student(this);

    connect(zt,&Teacher::Hungry,st,&Student::treat);

    // 调用下课,触发老师饿了,随后学生响应
    classisover();
}

Widget::~Widget()
{
}

void Widget::classisover()
{
    // 下课函数 调用后触发老师饿了信号
    emit zt->Hungry();
}

6.3 自定义的信号和槽发生重载的解决

1.需要利用函数指针明确指向函数的地址,成员函数指针需要加上作用域

2.QString->char * 先转成QByteArray(.toUtf8())再转char*(),.data的返回值是char *

Widget代码 

#include "widget.h"

// Teacher 类 老师类
// Student 类 学生类
// 下课后,老师会触发一个信号,饿了,学生响应信号,请客吃饭

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    // 创建老师和学生对象,并且指定父亲,就不用释放
    this->zt = new Teacher(this);
    this->st = new Student(this);

    //connect(zt,&Teacher::Hungry,st,&Student::treat);

    // 调用下课,触发老师饿了,随后学生响应
    //classisover();
    // 函数指针->函数地址,&+函数名
    void(Teacher::*teacherSignal)(QString) = &Teacher::Hungry;// 成员函数的函数指针
    void(Student::*studentSlot)(QString) = &Student::treat;
    // 当出现重载的时候,需要出现设置信号和槽的函数地址
    connect(zt,teacherSignal,st,studentSlot);//重载出现二义性

    classisover();
}

Widget::~Widget()
{
}

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

 槽函数重载

#include "student.h"
#include <QDebug>
Student::Student(QObject *parent)
    : QObject{parent}
{

}

void Student::treat()
{
    qDebug()<<"请老师吃饭";
}
void Student::treat(QString foodname)// 重载treat
{
    //打印QString类型有引号,要转成char*就没有引号
    //qDebug()<<"请老师吃饭,老师要吃:"<<foodname;
    // QString->char * 先转成QByteArray(.toUtf8())再转char*(),data的返回值是char *
    qDebug()<<"请老师吃饭,老师要吃:"<<foodname.toUtf8().data();
}

 信号重载

void Hungry();
void Hungry(QString foodname);

6.4 信号连接信号

connect(btn,&QPushButton::clicked,zt,teacherSignal);teacherSignal要换成无参形式,否则参数不匹配;

#include "widget.h"
#include <QPushButton>
// Teacher 类 老师类
// Student 类 学生类
// 下课后,老师会触发一个信号,饿了,学生响应信号,请客吃饭

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    // 创建老师和学生对象,并且指定父亲,就不用释放
    this->zt = new Teacher(this);
    this->st = new Student(this);

    //点击一个按钮,再下课,再触发老师饿了
    QPushButton *btn = new QPushButton("下课",this);
    this->resize(600,400); // 重置窗口大小
    connect(btn,&QPushButton::clicked,this,&Widget::classisover);

    //无参信号和槽连接
    void(Teacher::*teacherSignal)(void) = &Teacher::Hungry;// 成员函数的函数指针
    void(Student::*studentSlot)(void) = &Student::treat;
    connect(zt,teacherSignal,st,studentSlot);

    // 信号连接信号 之间跳过下课,按钮直接使老师饿了
    connect(btn,&QPushButton::clicked,zt,teacherSignal);


    // 断开信号
    //disconnect(zt,teacherSignal,st,studentSlot);
}

Widget::~Widget()
{
}

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

6.5 Qt4版本信号连接

1.信号可以连接信号;

2.一个信号可以连接多个槽函数;

3.多个信号可以连接同一个槽函数;

4.信号和槽函数的参数,必须一一对应;

5.信号的参数个数可以多于槽函数的参数个数,但是类型要一一对应

clicked的参数是bool类型,teacherSignal如果是QString参数就不是一一对应,如果是void参数就是信号的参数比槽函数的参数多,所以不会报错。

6.Qt4:connect(zt,SIGNAL(hungry()),st,SLOT(treat(QString));参数直观,但是不做类型检测,不推荐。

6.5 Lambda表达式

C++11中的Lambda表达式用于定义并创建匿名函数对象,以简化编程工作。

表达式:[函数对象参数](操作符重载函数参数)mutable->返回值(函数体)

 ① “=”为值传递,“&”为地址传递,a为只对a可见;

 ② mutable关键字,用于修饰值传递的变量,修改拷贝而不是本体;

 ③ int ret = [ ]( )->int {return 100;}();使得ret=100;

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{

    QPushButton *btn = new QPushButton;
    this->resize(600,400); // 重置窗口大小
    btn->setText("close");
    btn->setParent(this);//把按钮安到窗口上
    //利用lambda表达式实现关闭按钮
    connect(btn,&QPushButton::clicked,this,[=](){
        this->close();
        btn->setText("aaa");
    });

}

6.6 信号槽的总结

 任务:设计一个窗口,两个按钮,点击open打开另一个窗口,点击close关闭窗口。

#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QPushButton *btn = new QPushButton;
    btn->setText("open");
    btn->setParent(this);
    resize(600,400);

    QPushButton *btn2 = new QPushButton;
    btn2->setText("close");
    btn2->setParent(this);
    btn2->move(200,200);

    QWidget *w2=new QWidget;

    connect(btn,&QPushButton::clicked,w2,&QWidget::show);

    connect(btn2,&QPushButton::clicked,w2,&QWidget::close);

}

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

  任务:设计一个窗口,一个按钮,点击open打开另一个窗口,open变成close,再点击close关闭窗口,close变成open。

#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QPushButton *btn = new QPushButton;
    btn->setText("open");
    btn->setParent(this);
    resize(600,400);

    QWidget *w1 = new QWidget;

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

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

7、QMainWindow

7.1 菜单栏和工具栏

1.菜单栏最多只有一个,工具栏可以有多个

2.QMenu,QToolBar

#include "mainwindow.h"
#include <QMenuBar>
#include <QToolBar>
#include <QPushButton>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    // 重置窗口大小
    resize(600,400);

    // 菜单栏的创建 最多只有一个
    QMenuBar *bar = menuBar();// 本身在对象树
    setMenuBar(bar); // 将菜单栏放入窗口中
    QMenu *fileMenu = bar->addMenu("文件"); // 创建菜单
    QMenu *editMenu = bar->addMenu("编辑");
    QAction * newAction = fileMenu->addAction("新建");// 创建菜单项
    // 添加分割线
    fileMenu->addSeparator();

    QAction * newAction1 = fileMenu->addAction("打开");
    editMenu->addAction("复制");

    // 工具栏的创建 可以有多个
    QToolBar *toolBar = new QToolBar(this);
    addToolBar(Qt::LeftToolBarArea,toolBar);//默认在左边
    // 只允许左右停靠
    toolBar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);
    // 设置浮动
    toolBar->setFloatable(false);
    // 设置移动,bool值设置是否可以移动,相当于总开关
    toolBar->setMovable(false);
    // 设置内容
    toolBar->addAction(newAction);
    toolBar->addSeparator();
    toolBar->addAction(newAction1);
    // 工具栏添加控件
    QPushButton* btn = new QPushButton("aa",this);
    toolBar->addWidget(btn);

}

MainWindow::~MainWindow()
{
}

7.2 状态栏、铆接部件、核心部件 

 1.QStatusBar,QDockWidget(浮动窗口),QTextEdit;

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

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

    // 铆接部件(浮动窗口)可以有多个
    QDockWidget *dockWidget = new QDockWidget("浮动",this);
    addDockWidget(Qt::BottomDockWidgetArea,dockWidget);
    // 只允许上下
    dockWidget->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);;

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

8、资源文件的添加 

1. 将图片文件拷贝到项目位置;

2. 右键项目->添加新文件->Qt->Qt recourse File->给资源文件起名

3. rec生成rec.qrc

4. open in editor打开文件

5. 添加前缀 添加文件,编译

6. 使用“:+前缀名+文件名”

9、模态和非模态对话框创建

1. 模态对话框:不可以对其他窗口进行操作;QDialog dlg(this);dlg.exec();

2. 非模态对话框:可以对其他窗口进行操作;QDialog *dlg2 = new QDialog(this);dlg2->show();

#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 dlg(this);
        dlg.resize(200,100);
        dlg.exec();//模态方式创建,阻塞功能

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

        // 非模态对话框
        QDialog *dlg2 = new QDialog(this);//存在内存泄漏风险,创建堆区
        dlg2->resize(200,100);
        dlg2->show();
        dlg2->setAttribute(Qt::WA_DeleteOnClose);//设置属性,差掉就释放内存
        qDebug()<<"非模态对话框弹出了";

    });
}

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

10、消息对话框

QMessageBox 静态成员函数 创建对话框

错误、信息、提问、警告

利用返回值来判断用户的选择

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>
#include <QDebug>
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 点击新建按钮 弹出会话框
    connect(ui->actionnew,&QAction::triggered,[=](){

        //消息对话框
        //QMessageBox::critical(this,"critical","错误");//错误对话框
        //QMessageBox::information(this,"info","信息");//信息对话框
        //提问对话框
        //参数1:父亲,参数2:标题;参数3:提示内容;参数4:按键类型;参数5:默认关联回车按键
//        QMessageBox::question(this,"ques","提问",QMessageBox::Save|QMessageBox::Cancel,QMessageBox::Cancel);
//        if(QMessageBox::Save ==  QMessageBox::question(this,"ques","提问",QMessageBox::Save|QMessageBox::Cancel,QMessageBox::Cancel))
//        {
//            qDebug()<<"选择了保存";
//        }
//        else
//        {
//            qDebug()<<"选择了取消";
//        }

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

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

11、其他对话框

QColorDialog,QFileDialog,QFontDialog

 // 点击新建按钮 弹出会话框
    connect(ui->actionnew,&QAction::triggered,[=](){
        //颜色对话框
//        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,"打开文件","E:\\BaseFile\\senior\\C++work","(*.doc)");
//        qDebug()<<str;
        bool flag;
        QFont font = QFontDialog::getFont(&flag,QFont("华文彩云",32));
        qDebug()<<font.family();
    });

12、登陆窗口布局

1. 实现登录窗口;

2. 利用布局方式 给窗口进行美化;

3. 选取widget进行布局,水平布局、垂直布局、栅格布局;

4. 给用户名、密码、登录、退出按钮进行布局;

5. 默认窗口和控件之间有9间隙,可以调整 layoutLeftMargin;

6. 利用弹簧进行布局。

13、控件

13.1 按钮组

1. QPushButton 常用按钮;

2. QToolButton 工具按钮;用于显示图片,如图想显示文字,修改风格;ToolButtonStyle;

3. radioButton 单选按钮,设置默认选择ui->woman->setChecked(true);

4. checkbox 多选按钮,监听状态,2是选中,1是半选,0是未选。

 

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

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

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

13.2 QListWidget控件

 QListWidget 列表容器:QListWidgetItem 显示一行内容;

设置居中方式setTextAlignment(),通过查询assitant帮助文档查询参数。

 // 利用listWidget写诗
//    QListWidgetItem *item = new QListWidgetItem("一川烟雨,满城风絮,梅子黄时雨");
//    ui->listWidget->addItem(item);//放到listWidget控件里
//    item->setTextAlignment(Qt::AlignCenter);//水平居中
    //QStringList QList<QString>
    QStringList list;
    list<<"陌上花开"<<"可缓缓归矣";
    ui->listWidget->addItems(list);

13.3 QTreeWidget控件

1. 设置水平头 setHeaderLabels();

2. 创建根节点  QTreeWidgetItem *item1 = new QTreeWidgetItem(QStringList()<<"力量");

3. 添加根节点到树控件  ui->treeWidget->addTopLevelItem(item1);

4. 添加子节点 item1->addChild(l1);

#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 *item1 = new QTreeWidgetItem(QStringList()<<"力量");//匿名对象
    QTreeWidgetItem *item2 = new QTreeWidgetItem(QStringList()<<"敏捷");
    QTreeWidgetItem *item3 = new QTreeWidgetItem(QStringList()<<"智力");
    // 加载顶层的节点
    ui->treeWidget->addTopLevelItem(item1);
    ui->treeWidget->addTopLevelItem(item2);
    ui->treeWidget->addTopLevelItem(item3);
    //追加子节点
    QStringList heroL1,heroL2,heroL3;
    heroL1<<"200";
    heroL2<<"100";
    heroL3<<"130";
    QTreeWidgetItem *l1 = new QTreeWidgetItem(heroL1);
    QTreeWidgetItem *l2 = new QTreeWidgetItem(heroL2);
    QTreeWidgetItem *l3 = new QTreeWidgetItem(heroL3);
    item1->addChild(l1);
    item2->addChild(l2);
    item3->addChild(l3);
}

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

13.4 QTableWidget控件

#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)));//at越界抛异常
        //int 转QString
        ui->tableWidget->setItem(i,col++,new QTableWidgetItem(QString::number(i+18)));
    }

}

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

13.5 其他控件介绍

1. stackedWidget控件

2. 下拉框控件comboBox

3. QLabel显示图片和gif 

#include "widget.h"
#include "ui_widget.h"
#include <QMovie>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 栈控件使用
    // 欢迎按钮
    // 设置默认页面
    ui->stackedWidget->setCurrentIndex(0);

    connect(ui->btn_welcome,&QPushButton::clicked,[=](){
        ui->stackedWidget->setCurrentIndex(0);
    });
    // 编辑按钮
    connect(ui->btn_edit,&QPushButton::clicked,[=](){
        ui->stackedWidget->setCurrentIndex(1);
    });
    // 项目按钮
    connect(ui->btn_project,&QPushButton::clicked,[=](){
        ui->stackedWidget->setCurrentIndex(2);
    });
    // 下拉框
    ui->comboBox->addItem("奔驰");
    ui->comboBox->addItem("宝马");
    ui->comboBox->addItem("自行车");

    connect(ui->btn_bike,&QPushButton::clicked,[=](){
        //ui->comboBox->setCurrentIndex(2);
        ui->comboBox->setCurrentText("自行车");
    });
    // 利用QLabel显示图片和gif动态图片
    ui->lb1->setPixmap(QPixmap(":/Image/1.jpg"));
    QMovie *movie = new QMovie(":/Image/m.gif");
    ui->lb1->setMovie(movie);//嵌入到lbl
    movie->start();//动起来
}

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

14、自定义控件

1、添加新文件,Qt->设计师界面类(.cpp .h .ui)

2、.ui中设计 QSpinBox和QSlider两个控件

3、Widget中使用自定义控件,拖拽一个Widget,点击提升为,点击添加,点击提升,将.ui变成一个smallWidget类

4、在smallWidget.cpp实现功能,改变数字,滑动条跟着移动,信号槽监听

5、提供两个按钮,对ui的smallWidget实例对象进行操作

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 点击获取控件当前值
    connect(ui->btn_set,&QPushButton::clicked,[=](){
        qDebug()<<ui->widget->getNum();
    });
    connect(ui->btn_half,&QPushButton::clicked,[=](){
       ui->widget->setNum(50);
    });
}

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

15、Qt的鼠标事件

1、鼠标进入事件enterEvent

2、鼠标离开事件leaveEvent

3、鼠标移动 mouseMoveEvent

4、鼠标按下 mousePressEvent

5、鼠标释放 mouseReleaseEvent

6、ev->x(),ev->y()

7、ev->button() 可以判断所有按键,Qt::LeftButton,Qt::RightButton

8、ev->buttons() 判断组合按键,判断用 &

9、格式化字符串 QString str = QString(“%1  %2 %3 ...”).arg().arg().arg()...

#include "mylabel.h"
#include <QDebug>
#include <QMouseEvent>
myLabel::myLabel(QWidget *parent)
    : QLabel{parent}
{
    //设置鼠标追踪状态,默认是false
    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 globaly = %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 globaly = %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 globaly = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug()<<str;
//    }

}

16、定时器

1、利用事件void timerEvent(QTimerEvent *e)

2、启动定时器 startTimer(1000)毫秒单位

3、timerEvent的返回值是定时器定时器的唯一标识,可以和 e->timerId 做比较

4、利用定时器类 QTimer

5、先创建定时器对象,启动定时器start(毫秒)

6、每隔一定毫秒,发送信号timeout,进行监听

#include "widget.h"
#include "ui_widget.h"
#include <QTimer>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 启动定时器 单位是毫秒
    id1 = startTimer(1000);
    id2 = startTimer(2000);

    //定时器第二种方式
    QTimer *timer = new QTimer(this);
    //启动定时器
    timer->start(500);//0.5s进入中断
    connect(timer,&QTimer::timeout,[=](){
        static int num = 1;
        //每0.5s加1;
        ui->label_4->setText(QString::number(num++));
    });
    connect(ui->stop,&QPushButton::clicked,[=](){
        timer->stop();
    });
}

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

void Widget::timerEvent(QTimerEvent *e)
{

    //label_2 每隔1s +1
    if(e->timerId()==id1)
    {
        static int num1 = 1;
        ui->label_2->setText(QString::number(num1++));
    }

    //label_3 每隔2s +1
    if(e->timerId()==id2)//判断定时器
    {
        static int num2 = 1;
        ui->label_3->setText(QString::number(num2++));
    }

}

17、event 事件分发器和事件过滤器 

1、用于时间的分发,也可以做拦截(不建议)

2、bool event(QEvent *e)返回值是true代表永华处理这个事件,不向下分发 

3、e->type() == 鼠标按下

bool myLabel::event(QEvent *e)
{
    if(e->type() == QEvent::MouseButtonPress)//鼠标按下,在事件event事件中做拦截操作
    {
        QMouseEvent *ev = static_cast<QMouseEvent*>(e);//将e转换为ev类型
        QString str = QString("event中,,鼠标按下了,x = %1 y = %2 globalx = %3 globaly = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug()<<str;
        return true;//代表用户自己处理事件,不向下分发
    }
    //其他事件交给父类处理

    return QLabel::event(e);
}
---------------------------------------------------------------------------------
bool Widget::eventFilter(QObject *obj,QEvent *e)
{
    if(obj == ui->label)
    {
        if(e->type() == QEvent::MouseButtonPress)//鼠标按下,在事件event事件中做拦截操作
        {
            QMouseEvent *ev = static_cast<QMouseEvent*>(e);//将e转换为ev类型
            QString str = QString("事件过滤器中,,鼠标按下了,x = %1 y = %2 globalx = %3 globaly = %4").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
            qDebug()<<str;
            return true;//代表用户自己处理事件,不向下分发
        }
    }
    // 其他默认处理
    return QWidget::eventFilter(obj,e);
}

18、QPainter

18.1 绘图事件 

1、绘图事件 void paintEvent()

2、声明一个画家对象

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::cyan);
    //设置画刷风格
    brush.setStyle(Qt::Dense7Pattern);
    //让画家使用画刷
    painter.setBrush(brush);


    //划线
    painter.drawLine(QPoint(0,0),QPoint(100,100));
    //画圆 椭圆
    painter.drawEllipse(QPoint(100,100),50,50);
}

18.2 绘图高级设置

1、抗锯齿,效率低

2、对画家进行移动,保存状态,还原状态

void Widget::paintEvent(QPaintEvent *)
{
    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));
}

18.3 手动调用绘图事件

如果想手动调用绘图事件,利用update,利用画家画图片painterDrawPixmap

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

    //移动
    connect(ui->btn_move,&QPushButton::clicked,[=](){

      //如果要手动调用绘图事件,用update更新
      update();
      posx += 20;

    });
}
void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    //如果超过屏幕,重新开始
    if(posx > this->width())
    {
        posx = 0;
    }
    painter.drawPixmap(posx,0,QPixmap(":/Image_1/10.jpg"));
}

18.4 绘图设备 

1. QPixmap QImage QBitmap(黑白)QPicture QWidget

2. QPixmap 对不同平台做了显示优化

3. QImage可以对像素进行访问

4. QPicture可以记录和重现绘图指令

#include "widget.h"
#include "ui_widget.h"
#include <QPixmap>
#include <QPainter>
#include <QImage>
#include <QPicture>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

//    //Pixmap绘图设备 专门为平台做了显示的优化
//    QPixmap pix(400,400);
//    QPainter painter(&pix);
//    //填充颜色
//    pix.fill(Qt::white);
//    painter.setPen(QPen(Qt::blue));
//    painter.drawEllipse(QPoint(200,200),100,100);

//    //保存到磁盘
//    pix.save("E:\\pix.png");

    //QImage 绘图设备 可以对像素进行访问
//    QImage img(300,300,QImage::Format_RGB666);
//    img.fill(Qt::white);
//    QPainter painter(&img);
//    painter.setPen(QPen(Qt::blue));
//    painter.drawEllipse(QPoint(200,200),100,100);
//    img.save("E:\\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("E:\\pic.zt");


}
void Widget::paintEvent(QPaintEvent *event)
{
     //利用QImage对像素点修改
//    QPainter painter(this);
//    QImage img;
//    img.load(":/Image_1/10.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("E:\\pic.zt");
     painter.drawPicture(0,0,pic);
}

19、QFile文件读写操作

文件QFile和文件信息读写QFileInfo

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //点击选取文件按钮,弹出文件对话框
    connect(ui->btn_file,&QPushButton::clicked,[=]()
            {
                QString path = QFileDialog::getOpenFileName(this,"打开文件","E:\\1.Qt_temporary_files");
                //将路径放入到lineEdit
                ui->lineEdit->setText(path);

                //编码格式类
                //QTextCodec *codec = QTextCodec::codecForName("gbk");

                //读取内容,放入textEdit中
                QFile file(path);//参数就是读取文件的路径
                //设置打开方式
                file.open(QIODevice::ReadOnly);

                //QByteArray array = file.readAll();

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


                //将读入的数据放入textEdit
                ui->textEdit->setText(array);

                //转成gbk格式,默认是utf-8格式
                //ui->textEdit->setText(codec->toUnicode(array));

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

                //QFileInfo读取文件信息
                QFileInfo info(path);

                qDebug()<<"大小:"<<info.size()<<"后缀名:"<<info.suffix()<<"文件名:"<<info.fileName();
                qDebug()<<"创建日期:"<<info.birthTime().toString("yyyy/MM/dd hh:mm:ss");
            });
}

20、翻金币项目 

 翻金币提取码: z95t

打包后的游戏提取码: h327

 ***问题总结

1、因为有的函数没有自动补全,所以按照网上操作改了一些插件导致后面设计界面打不开,只能右键选中Qt designer打开,点击帮助,插件,把Qt Creator插件全部勾上就可以了。(我也不知道为什么,重启就没有了)

2、Qt:无法定位程序输入点于动态链接库等。我是按照下面这个博客解决的

Qt:无法定位程序输入点于动态链接库等。_阿远苏喂喂的博客-CSDN博客_qt无法定位程序输入点于动态链接库

  • 12
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
使用DOM4J解析books.xml文件并打印出图书信息的代码如下: ```java import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class BookParser { public static void main(String[] args) { try { // 创建一个SAXReader对象 SAXReader reader = new SAXReader(); // 读取XML文件 Document document = reader.read("books.xml"); // 获取根元素 Element root = document.getRootElement(); // 遍历所有book元素 for (Element book : root.elements("book")) { // 获取图书信息 String id = book.attributeValue("id"); String publisher = book.attributeValue("出版社"); String name = book.elementText("name"); String author = book.elementText("author"); String price = book.elementText("price"); String stock = book.elementText("body").substring(3); // 打印图书信息 System.out.println("编号id: " + id); System.out.println("出版社: " + publisher); System.out.println("书名: " + name); System.out.println("作者: " + author); System.out.println("价格: " + price); System.out.println("库存: " + stock); System.out.println("----------------------"); } } catch (DocumentException e) { e.printStackTrace(); } } } ``` 运行以上代码,将会解析books.xml文件并打印出图书信息: ``` 编号id: 01 出版社: 传智出版社 书名: Java编程思想 作者: James 价格: 98.00 库存: 30 ---------------------- 编号id: 02 出版社: 传智出版社 书名: JavaEE从入门到精通 作者: 传智播客 价格: 40.00 库存: 20 ---------------------- 编号id: 03 出版社: 传智出版社 书名: Java开发手册 作者: 阿里巴巴 价格: 15.00 库存: 300 ---------------------- ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值