zoukankan      html  css  js  c++  java
  • Qt学习笔记

    Qt 学习笔记

    一、入门

    1、对象树

    在Qt中创建的每个对象都有一个parent指针,下面来详细解释parent是干什么的

    • QObject是以对象书的形式组织起来的
      • 每当创建一个QObject对象时,会看到QObject的构造函数接收一个QObject指针作为参数,这个参数就是 parent,也就是父对象指针。这相当于给自己parent的属性赋值,值就是传递过来的参数,就是给创建的QObject对象提供一个父对象,我们创建的这个QObject对象会自动添加到其父对象的children()列表。
      • 当父对象析构的时候,这个列表中的所有对象也会被析构。(注意,这里的父对象并不是继承意义上的父类!)
    • QWidget是能够在屏幕上显示的一切组件的父类
      • QWidget继承自QObject,因此也继承了这种对象树关系。一个孩子自动地成为父组件的一个子组件。因此,它会显示在父组件的坐标系统中,被父组件的边界剪裁。例如,当用户关闭一个对话框的时候,应用程序将其删除,那么,我们希望属于这个对话框的按钮、图标等应该一起被删除。事实就是如此,因为这些都是对话框的子组件。
      • 我们也可以自己删除子对象,它们会自动从其父对象列表中删除。比如,当我们删除了一个工具栏时,其所在的主窗口会自动将该工具栏从其子对象列表中删除,并且自动调整屏幕显示。
    • 当一个QObject对象在堆上创建的时候,Qt 会同时为其创建一个对象树。不过,对象树中对象的顺序是没有定义的。这意味着,销毁这些对象的顺序也是未定义的。
    • 任何对象树中的 QObject对象 delete 的时候,如果这个对象有 parent,则自动将其从 parent 的children()列表中删除;如果有孩子,则自动 delete 每一个孩子。Qt 保证没有QObject会被 delete 两次,这是由析构顺序决定的。

    2、入门案例

    2.1 创建项目

    1、首先新建项目

    在这里唯一要注意的是项目名称不能有空格,否则会报错

    QWidget就是qt项目中的顶级类

    • .pro:就是项目文件
    • main.cpp:主函数文件

    2.2 主函数

    #include "widget.h"
    #include <QApplication>
    
    //main 程序入口 argc命令行变量的数量argv命令行变量的数组
    int main(int argc, char *argv[])
    {
        //a - 应用程序对象,有且仅有一个
        QApplication a(argc, argv);
        
        //窗口对象
        Widget w;
        
        //窗口对象默认不会显示,必须调用show()方法显示窗口
        w.show();
    
        //让程序进入消息循环,而不是一闪而过
        return a.exec();
    }
    

    QApplication就是Qt中的应用程序类的头文件

    2.3 Qt模块

    Qt模块

    2.4 项目文件

    打开.pro文件

    QT       += core gui	# qt项目包含的模块
    
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets	# 大于Qt4版本的时候包含widgets
    
    TARGET = demo6			# 目标:生成exe文件名称
    TEMPLATE = app			# 模板:应用程序模板 Application
    
    DEFINES += QT_DEPRECATED_WARNINGS
    
    CONFIG += c++11
    
    SOURCES += 			# 源文件
            main.cpp 
            widget.cpp
    
    HEADERS += 			# 头文件
            widget.h
    
    qnx: target.path = /tmp/$${TARGET}/bin
    else: unix:!android: target.path = /opt/$${TARGET}/bin
    !isEmpty(target.path): INSTALLS += target
    

    2.5 头文件

    打开.h文件

    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QWidget>
    
    class Widget : public QWidget
    {
        Q_OBJECT	//是一个宏,允许类中使用信号和槽机制
    
    public:
        Widget(QWidget *parent = 0);
        ~Widget();
    };
    
    #endif // WIDGET_H
    
    

    c++有一个关键字explicit为了防止隐式转化

    3、编译器快捷键

    ctrl+/:注释

    ctrl+r:运行

    ctrl+b:编译

    ctrl+f:查找

    ctrl+i:自动对齐

    ctrl+shift+{up}:整行向上移动

    ctrl+shift+{down}:整行向下移动

    f4:同名.h 文件和.cpp文件切换

    设置自动补全:工具->选项->环境->键盘

    4、帮助文档

    • F1
    • 编译器左侧按钮
    • 路径D:QtQt5.11.35.11.3mingw53_32inassistant.exe(参考)

    5、其他

    1、格式化字符串

    QString str = QString("我是 %1,年龄 %2").arg("hel").arg(20);
    

    2、Debug输出

    qDebug()<<"output"
    

    二、信号和槽机制

    信号槽是 Qt 框架引以为豪的机制之一。所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。

    1、connect() 函数

    connect()函数最常用的一般形式:

    connect(sender, signal, receiver, slot);
    

    参数解释:

    • sender:发出信号的对象
    • signal:发送对象发出的信号
    • receiver:接收信号的对象
    • slot:接收对象在接收到信号之后所需要调用的函数(槽函数)

    disconnect()函数:用户断开连接参数同connect()

    2、系统自带的信号和槽

    示例代码:

    QPushButton * quitBtn = new QPushButton("关闭窗口",this);
    connect(quitBtn,&QPushButton::clicked,this,&MyWidget::close);
    

    3、自定义的信号和槽

    1、新建一个Teacher类,并查看teacher.h

    #ifndef TEACHER_H
    #define TEACHER_H
    
    #include <QObject>
    
    class Teacher : public QObject
    {
        Q_OBJECT
    public:
        explicit Teacher(QObject *parent = nullptr);
    
    signals:
    
    public slots:
    };
    
    #endif // TEACHER_H
    

    signals:用来定义信号函数,返回值是void只需要声明,不需要实现,可以有参数,可以重载

    slots:用来定义槽函数,早期版本必须写到slots标签下,高级版本可以直接定义到public标签下,需要声明,也需要实现,可以有参数,可以重载

    4、带参数的槽函数处理

    1、信号函数

    void Widget::classOver(){
    	emit teacher->hungry("鸡肉");
    }
    

    2、槽函数

    void Student::treat(QString food){
    	qDebug() << "老师要吃:" << food
    }
    

    3、连接

    //函数指针定义:函数返回值类型 (* 指针变量名)(函数参数列表);
    
    //函数指针 -> 地址
    void(Teacher:: *teacherSignal)(QString) = &Teacher::hungry;
    void(Student:: *studentSlot)(QString) = &Student::treat;
    connect(teacher, teacherSignal, st)
    

    5、Qt4版本信号槽连接

    connect(zt, SINGAL(hungry()), st, SLOT(treat()));
    

    优点:参数直观

    缺点:类型不做检测,类型不一致时照样可以编译成功,不利于排错

    6、Lambda表达式

    Lambda表达式用于定义并创建匿名的函数对象,以便简化编程工作,基本构成如下

    [capture](parameters) mutable ->return-type
    {
    	statement
    }
    
    [函数对象参数](操作符重载函数参数)mutable ->返回值{函数体}
    
    • 函数对象参数
      • 空:没有使用任何函数对象参数
      • =:按照值传递方式使用Lambda所在作用域范围内的变量
      • &:按照引用传递方式使用Lambda所在作用域范围内的变量
      • this:使用Lambda所在作用范围内的成员变量
      • a:将a按值进行传递,函数体内不能修改传递进来的a的拷贝,因为默认情况下函数是const的。要修改传递进来的a的拷贝,可以添加mutable修饰符。
      • &a:将a按引用进行传递。
      • a, &b:将a按值进行传递,b按引用进行传递。
      • =,&a, &b:除a和b按引用进行传递外,其他参数都按值进行传递。
      • &, a, b:除a和b按值进行传递外,其他参数都按引用进行传递。
    • 操作符重载函数参数
      • 标识重载的()操作符的参数,没有参数时,这部分可以省略。参数可以通过按值(如:(a,b))和按引用(如:(&a,&b))两种方式进行传递
    • 可修改标示符
      • mutable声明,这部分可以省略。按值传递函数对象参数时,加上mutable修饰符后,可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身)

    7、注意事项

    • 发送者和接收者都需要是QObject的子类(槽函数是全局函数、Lambda 表达式等无需接收者的时候除外);
    • 信号和槽函数返回值是 void
    • 信号只需要声明,不需要实现
    • 槽函数需要声明也需要实现
    • 槽函数是普通的成员函数,作为成员函数,会受到 public、private、protected 的影响
    • 使用 emit 在恰当的位置发送信号
    • 使用connect()函数连接信号和槽。
    • 任何成员函数、static 函数、全局函数和 Lambda 表达式都可以作为槽函数
    • 信号槽要求信号和槽的参数一致,所谓一致,是参数类型一致
    • 在槽函数中可以忽略信号传来的数据,也就是槽函数的参数比信号的少

    三、QMainWindow

    QMainWindow是一个为用户提供主窗口程序的类,包含一个菜单栏(menu bar)、多个工具栏(tool bars)、多个锚接部件(dock widgets)、一个状态栏(status bar)及一个中心部件(central widget),是许多应用程序的基础,如文本编辑器,图片编辑器等。

    常用方法

    (1)重置窗体大小

    resize(600, 400);
    

    (2)设置窗口的标题

    setWindowTitle("myWindow")
    

    (3)设置窗口大小不可变

    setFixedSize(600, 400)
    

    (4)设置菜单栏

    setMenuBar(bar)
    

    1、菜单栏

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

    (1)引入头文件

    #include<QMenuBar>
    

    (2)创建菜单栏

    QMenuBar * bar = menuBar();
    

    (3)设置设置菜单栏

    setMenuBar(bar)
    

    (4)创建菜单

    QMenu * fileMenu = bar->addMenu("文件");
    

    (5)创建菜单项

    fileMenu->addAction("新建");
    

    (6)创建分隔线

    fileMenu->addSeparator();
    

    2、工具栏

    (1)引入头文件

    #include<QToolBar>
    

    (2)创建工具栏

    QToolBar * toolBar = new QToolBar(this);
    

    (3)设置工具栏

    addToolBar(toolBar);	//默认在上方,可拖拽
    addToolBar(Qt::LeftToolBarArea, toolBar); //停靠在左边,可拖拽
    

    (4)设置允许停靠区域

    toolBar->setAllowedAreas(Qt::LeftToolBarArea, Qt::RightToolBarArea);
    

    (5)设置浮动

    toolBar->setMovable(false);//不可浮动
    

    (6)添加控件

    QPushButton * btn = new QPushButton("myButton", this);
    toolBar->addWidget(btn); //添加widget
    
    toolBar->addAction(); // 添加QAction
    

    3、状态栏

    最多也只能有一个

    (1)引入头文件

    #include<QStatusBar>
    

    (2)创建窗台栏

    QStatusBar * statusBar = QStatusBar();
    

    (3)设置状态栏

    setStatusBar(statusBar);
    

    (4)添加控件

    QLabel * label = new QLabel("提示信息", this);
    statusBar->addWidget(label);//默认在最左边
    
    QLabel * label = new QLabel("右边提示信息", this);
    statusBar->addPermanentWidget(label);
    

    4、铆接部件

    浮动窗口

    (1)引入头文件

    #include<QDockWidget>
    

    (2)创建浮动窗口

    QDockWidget * dockWidget = new QDockWidget("浮动", this);
    

    (3)添加浮动窗口

    addDockWidget(Qt::BottomDockWidgetArea, dockwidget);//添加到核心部件下边
    

    (4)设置允许停靠区域

    //允许停靠在上下
    dockWidget->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
    

    5、核心部件(中心部件)

    只能有一个

    (1)引入头文件

    #include<QTextEdit>
    

    (2)创建中心部件

    QTextEdit * edit = new QTextEdit(this);
    

    (3)设置中心部件

    setCentralWidget(edit);
    

    6、资源文件

    (1)添加资源到项目目录中

    (2)添加资源文件


    (3)给资源文件起个名字

    (4)添加前缀

    (5)添加文件,然后选中第一步我们放进去的资源就行了

    (6)使用资源,设置图标

    //如何使用: “前缀 + 文件相对路径”
    //或者更简单的方式,右键想要使用的文件,可以复制url
    ui->actionnew->setIcon(QIcon(":/img/folder.ico"));
    //在这里actionnew是一个菜单项对应的变量名
    

    7、使用creator ui设计

    注意

    • 添加菜单栏时先输入英文,然后在右边属性栏中设置text显示值
    • 可以拖拽Action Editor内的控件,以便复用,如下

    四、QDialog 对话框

    首先引入头文件

    #include<QDialog>
    

    1、模态窗口

    (1)创建窗口对象

    QDialog dialog(this); //注意这是在栈上创建的
    

    (2)使用exec()方法显示窗口

    dialog.exec(); //exec()方法会让控件进入消息循环,所以即使在栈上创建的对象不会立即释放
    

    2、非模态窗口

    (1)在堆上创建对象,一般都在堆上创建,上面只是举个例子

    QDialog *dialog = new QDialog(this);
    dialog->show();//使用show就是非模态方式
    
    //若还使用之前在栈上创建的对象,运行程序仅会看到一闪而逝的窗口,所以对象一般要在堆上创建
    
    //设置属性让其在dialog叉掉后自动释放内存
    dialog->setAttribute(Qt::WA_DeleteOnClose);
    

    3、系统内置对话框

    • QColorDialog:选择颜色

    • QFileDialog:选择文件或者目录

    • QFontDialog:选择字体

    • QInputDialog:允许用户输入一个值,并将其值返

    • QPageSetupDialog:为打印机提供纸张相关的选项

    • QPrintDialog:打印机配置

    • QPrintPreviewDialog:打印预览

    • QProgressDialog:显示操作过程

    • QMessageBox:模态对话框,用于显示信息、询问问题等

      • QMessageBox通过静态成员函数创建对话框,例如QMessageBox::question(……)
      • 参数1:父亲,参数2:标题,参数3:显示内容,参数4:案件类型,参数5:默认关联回车按键
      • 返回值是StandardButton类型,利用返回值判断用户的输入

    五、布局管理器

    1、系统提供的布局控件

    使用起来不灵活

    2、利用widget做布局

    六、常用控件

    1、按钮相关

    (1)QPushButton 常用按钮

    • 方法一

    1、引入头文件

    #include<QPushButton>
    

    2、创建button组件

    QPushButton *btn = new QPushButton;
    

    3、显示button

    btn->setParent(this);
    

    不能直接调用show()方法,因为他会以顶层的方式弹出,正确的方式因该是让btn对象依赖在父对象中

    4、设置button文字

    btn->setText("myButton");
    
    • 方法二

    1、第一步同上

    2、创建组件

    QPushButton * btn = new QPushButton("myButton", this);
    

    这种方式将方式二简化了,但存在一个问题,就是父窗体的大小是根据组件的大小确定的,从而导致窗体非常小

    重置窗体大小

    resize(600, 400);
    

    这样重置一下大小,窗体就会变得正常了

    虽然现在button组件是创建出来了,但是他的位置默认是在左上角,所以我们要将他移动到我们想要的位置

    移动button

    btn->move(600, 400)
    

    设置窗口的标题

    setWindowTitle("myWindow")
    

    设置窗口大小不可变

    setFixedSize(600, 400)
    

    (2)QToolButton 工具按钮

    用于显示图片,如想显示文字,需要修改风格按钮:toolButtonStyle,凸起风格autoRaise

    (3)radioButton 单选按钮

    设置默认

    ui->myradiobtn->setChecked(true);
    

    (4)checkbox 多选按钮

    监听状态:2 选中,1 半选, 0 未选中

    2、标签

    (1)引入头文件

    #include<QLabel>
    

    (2)创建标签

    QLabel * label = new QLabel("myLabel", this);
    

    (3)利用label显示图片

    ui->lb_image->setPixmap(QPixmap(":/img/1.png"));
    

    (4)显示动图

    QMovie * movie = new QMovie(":/img/mario.gif");//创建动图
    ui->lb_movie->setMovie(movie);//设置动图
    movie->start();//播放动图
    

    3、列表相关

    (1)引入列表项头文件

    #include<QListWdgetItem>
    

    (2)创建列表项

    QListWidgetItem *item =  new QlistWidgetItem("list1");
    

    (3)添加列表项至列表

    ui->listWidget->addItem(item);
    

    (4)设置列表项文本对齐方式

    item->setTextAlignment(Qt::AlignHCenter);
    

    (5)添加多个列表项至列表

    QStringList list;
    list << "list1" << "list2" << "list3"
    ui->listWidget->addItems(list);
    

    4、树形控件

    (1)设置水平头

    ui->treeWidget->setHeaderLabels(QStringList()<<"姓名"<<"年龄");
    

    (2)创建节点

    QTreeWidgetItem * item = new QTreeWidgetItem(QString()<<"老师");
    

    (3)设置顶层节点

    ui->treeWidget->addTopLevelItem(item);
    

    (4)追加子节点

    QTreeWidgetItem * itemChild = new QTreeWidgetItem(QString()<<"李四" << "20");
    item->addChild(itemChild);
    

    5、表格控件

    (1)设置列数

    ui->tableWidget->setColumnCount(3);
    

    (2)设置水平头

    ui->tableWidget->setHorizontalHeaderLabels(QStringList()<<"姓名"<<"性别"<<"性别");
    

    (3)设置行数

    ui->tableWidget->setRowCount(3);
    

    (4)设置正文

    ui->tableWidget->setItem(0, 0, new QTableWidgetItem("亚瑟"));
    

    6、其他控件

    (1)滚动区域:Scroll Area

    (2)工具盒:Tool Box,类似与QQ的联系分类列表

    (3)选项卡:tabWidget

    (4)栈部件:Stacked Widget,类似于java swing中的卡片布局控制器

    //设置当前页面
    ui->satckedWidget->setCurrentIndex(1);
    

    (5)下拉框:comboBox

    //添加项
    ui->comboBox->addItem("item1");
    //设置选中项
    ui->comboBox->setCurrentIndex(1);
    

    (6)当行文本编辑框:Line Edit

    可以通过设置echo mode设置输入模式

    (7)文本区域:Text Edit,支持文本加粗等样式的文本

    (8)普通文本区域:Plain Text Edit,仅支持纯文本

    七、事件

    1、鼠标事件

    (1)鼠标进入事件:enterEvent(QWidget *event=0)

    (2)鼠标离开事件:leaveEvent(QEvent *)

    (3)鼠标按下事件:mousePressEvent(QMouseEvent *ev)

    (4)鼠标释放事件:mouseReleaseEvent(QMouseEvent *ev)

    (5)鼠标移动事件:mouseMoveEvent(QMouseEvent *ev)

    (6)坐标:ev->x()ev->y()

    (7)判断按键:ev->button(),判断事件的类型ev->type()

    (8)判断组件按键:ev->buttons(),通过&操作符

    (9)设置鼠标追踪状态:setMouseTracking(true),默认是false

    2、定时器

    1、重写方法

    (1)重写timerEvent(QTimerEvent *ev)实现定时功能

    (2)启动定时器

    startTimer(1000);
    
    //函数会返回timerId
    int timerId = startTimer(1000);
    

    (3)获取timerId

    ev->timerId()
    

    2、定时器类

    (1)创建定时器对象

    QTimer * timer = new QTimer(this);
    

    (2)启动定时器

    timer->start(500);
    

    (3)信号函数

    定时器事件到了会发送一个信号:QTimer::timerout

    (4)停止定时器

    timer->stop();
    

    3、事件分发器

    通过重写bool event(QEvent *ev)方法,返回true代表用户进行拦截,不在向下分配

    4、事件拦截器

    通过事件拦截器,可以在程序分发到event事件之前再做一次高级拦截

    使用步骤:

    1、给控件安装事件过滤器

    ui->label->installEventFilter(this);
    

    2、重写eventFilter事件

    bool Widget::eventFilter(QObject *obj, QEvent *e){
    
    }
    

    八、绘图

    1、基本用法

    通过重写void paintEvent(QPaintEvent * ev)事件

    1、实例化画家对象

    QPainter painter(this);
    

    2、画线

    painter.drawLine(this);
    

    3、画圆

    painter.drawEllipse(QPoint(100, 100), 50, 50);
    

    4、画矩形

    painter.darwRect(QRect());
    

    5、画文字

    painter.drawText(QRect(10, 200, 100, 500), "文字");
    

    6、画笔

    QPen pen(QColor(255, 0, 0));//创建画笔对象
    pen.setWidth(1);			//设置画笔宽度
    pen.setStyle(Qt::DotLine);	//设置画笔风格
    painter.setPen(pen);		//设置画笔
    

    7、画刷

    QBrush brush(QColor(0, 255, 0));//创建画刷对象
    brush.setStyle(Qt::Dense7Pattern);//设置画刷风格
    painter.setBrush(brush);		//设置画刷
    

    8、抗锯齿

    painter.setRenderHint(QPainter::Antialiasing);
    

    9、画家相对基址偏移

    painter.translate(100, 0);
    

    10、保存画家状态

    painter.save();
    

    11、还原画家保存状态

    painter.restore();
    

    12、绘制图片

    painter.drawPixmap(0, 0, QPixmap(":/img/1.png"));
    

    2、绘图设备

    • QPixmap专门为图像在屏幕上的显示做了优化

    (1)创建pixmap对象

    QPixmap pix(300, 300);
    

    (2)填充颜色

    pix.fill(Qt::white);
    

    (3)设置画家

    QPainter painter(&pix);
    painter.setPen(QPen(Qt::green));
    painter.drawEllipse(QPoint(100, 100), 50, 50);
    

    (4)保存

    pix.save("D://1.png");
    
    • QBitmapQPixmap的一个子类,它的色深限定为1,可以使用QPixmapisQBitmap()函数来确定这个QPixmap是不是一个QBitmap
    • QImage专门为图像的像意级访问做了优化

    操作基本同QPixmap,特色操作如下

    //创建
    QImage img(300, 300, QImage::Format_RGB32);
    //加载图片
    img.load(":/img/1.png");
    //设置像素
    QRgb value = qRgb(255, 0, 0);
    img.setPixel(x, y, value);
    
    • QPicture 则可以记录和重现QPainter的各条命令
    //创建绘图对象
    QPicture pic;
    //创建画家
    QPainter painter;
    //设置绘图设备,开始绘制
    painter.begin(&pic);
    painter.drawEllipse(QPoint(150, 150), 50, 50);
    //结束绘制
    painter.end();
    

    九、文件读写

    1、文件对象

    (1)获取文件路径

    QString path = QFileDialog::getOpenFileName(this, "打开文件");
    

    (2)创建文件对象

    QFile file(Path);//参数就是文件的路径
    

    (3)设置打开方式

    file.open(QIODevice::ReadOnly);//只读
    file.open(QIODevice::Append);//追加
    

    (4)读取全部数据

    QByteArray array = file.readAll();
    

    (5)读取一行数据

    file.readLine();
    

    (6)判断文件是否结尾

    file.atEnd();//返回true代表结束
    

    (7)写文件

    file.write();
    

    (8)关闭文件

    file.close();
    

    2、文件信息对象

    • size():大小
    • suffix():后缀
    • fileName():文件名称
    • created():创建日期
    • lastModified():最后修改信息
  • 相关阅读:
    Struts2+Spring3+Mybatis3开发环境搭建
    spring+struts2+mybatis
    【LeetCode】Populating Next Right Pointers in Each Node
    【LeetCode】Remove Duplicates from Sorted Array
    【LeetCode】Remove Duplicates from Sorted Array II
    【LeetCode】Binary Tree Inorder Traversal
    【LeetCode】Merge Two Sorted Lists
    【LeetCode】Reverse Integer
    【LeetCode】Same Tree
    【LeetCode】Maximum Depth of Binary Tree
  • 原文地址:https://www.cnblogs.com/hemou/p/12273037.html
Copyright © 2011-2022 走看看