QT开发——笔记

前言:
由于硬件开发中,免不了要做一些调试,别人的调试工具,好用是好用,但不是很美观,没有针对性和个性,所以就想着自己开发一些上位机,既可以硬件进行调试,又加入自己喜欢的元素,看着全部都是自己的劳动成果,岂不美哉。萌生想法,说干就干,一步一个脚印,QT务必拿下。

一、QT简介

Qt是一个跨平台的C++应用程序框架, 支持Windows、 Linux、 MacOS X、 Android、 iOS、 Windows Phone、 嵌入式系统等。 也就是说, Qt可以同时支持桌面应用程序开发、 嵌入式开发和移动开发, 覆盖了现有的所有主流平台。 开发者只需要编写一次代码, 而后在发布到不同平台之前重新编译即可。

我学QT主要是想为以后往Linux方向接触,Windows下一般用c#开发窗口程序,但Linux下不能。而QT开发,就避免这种情况,一次开发,全平台通用,岂不Nice。

我选用QT的另一个原因是Qt的文档设计得相当优秀, 可以到https://doc.qt.io/上一睹芳容。 Qt的文档完备且详细地覆盖了Qt的方方面面,比如开发Java,要经常去API手册中看相关类介绍和函数介绍啥的。而QT这些都不用单独去找,它自身就含有这些,QT中每一个类和方法都被详尽描述, 巨细靡遗, 举例充实。通过Qt Assistant工具可以方便地从一个类或者方法跳转到其他的类。 文档还包含了一个初学者教程和一些典型应用的例子, 方便用户查阅。 省去了开发中找资料的大部分时间。

二、安装QT软件

1、下载QT软件的网址:
https://download.qt.io/archive/qt/

上面下载的是离线包(推荐),当然也可以下载在线安装的包,但速度很慢,建议不要这样。

2、安装QT参考文章:安装QT

3、安装注意的地方:
在这里插入图片描述

1) 可能自从QT5.12版本后,安装中的上个页面就不能跳过了,必须去官网注册一个QT账号,然后填上下面的账号名和密码,才会出现NEXT(下一步)的选项。

在这里插入图片描述
2) 最伤的莫过于安装QT时的组件的选择安装了,全部安装,太占硬盘,又不会选择安装,对小白来说很不友好。我第一次也是丈二和尚摸不着头脑。

在这里插入图片描述

大致介绍可参考一位博主文章: 组件介绍

在选择要安装的组件时,需要注意的是,QT可以用两种编译器编译QT程序,一个是Visual Studio,另外一个是MinGW,是Minimalist GNUfor Windows的缩写。

如果选择了Visual Studio作为编译器,就必须安装对应版本的Visual Studio,刚开始我是安装Visual Studio2015,但是发现VS 太大了,十几个G,安装之后C盘所剩无几。虽然安装时选到了其他盘,但是大部分仍然还是被装到了C盘,卸载的时候也很无奈,得从控制面板中一个个卸载。

虽然安装QT时选择了MSVC组件,但是Visual Studio编译器并没有一起安装,因为Visual Studio是微软的软件,QT是不敢把它集成到自己的安装包中,但是如果选择了MinGW,就会在安装上MinGW编译器,因为MinGW是开源的.

所以我就选择时,第一个选择的的就是MinGW ***** 64bit。Tools中还是默认选择的QT creator那个。然后就一路NEXT就行。

安装好了,可以去网上找相关资料,试着新建一个工程项目,看是否安装好了。

三、软件学习

1、初始化main.cpp文件介绍

在这里插入图片描述

2、.pro工程文件介绍

在这里插入图片描述
在对某些功能进行编程时,需要在.pro文件下添加相应模块(例如网路编程就需要添加Network模块)
在这里插入图片描述

3、mywidget.h文件介绍

在这里插入图片描述

3、mywidget.cpp文件介绍

在这里插入图片描述

四、编程学习

1、信号与槽

(1)、自定义信号和槽函数

实例:
  创建一个项目,用默认的widget类作为父窗口,再创建一个subwidget类作为子窗口。最后实现功能:在父窗口中添加一个按钮A,在子窗口中添加一个按钮B;点击按钮A时,父窗口隐藏,子窗口显示;点击按钮B时,子窗口隐藏,父窗口显示。

代码实例:

  • widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QPushButton>

#include "subwidget.h"

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

    void widgetClose();     //槽函数:关闭父窗口,显示子窗口
    void subwidgetClose();  //槽函数:显示父窗口,关闭子窗口

private:
    Ui::Widget *ui;

    QPushButton *btn_widget;    //定义一个按钮类
    //Subwidget *subwidget;       //定义一个子窗口类
    Subwidget subwidget;
};
#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);

    //subwidget = new Subwidget(this);

    btn_widget = new QPushButton("显示子窗口",this);
    btn_widget->move(100,100);
    this.resize(200,200);

    connect(btn_widget,&QPushButton::clicked,this,&Widget::widgetClose);    //将按钮的点击信号和槽函数绑定
    connect(&subwidget,&Subwidget::close,this,&Widget::subwidgetClose);      //将子窗口的close信号和槽函数绑定
}

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

void Widget::widgetClose()
{
    this->hide();
    subwidget.show();
//    subwidget->show();

}

void Widget::subwidgetClose()
{
    this->show();
    subwidget.hide();
//    subwidget->hide();
}


  • subwidget.h
#ifndef SUBWIDGET_H
#define SUBWIDGET_H

#include <QWidget>
#include <QPushButton>
class Subwidget : public QWidget
{
    Q_OBJECT
public:
    explicit Subwidget(QWidget *parent = nullptr);

    void emitSignal();      //定义一个槽函数,向外发送给信号

private:
    QPushButton *btn_subwidget;     //定义一个按钮类

signals:
    void close();         //自己定义一个信号

};

#endif // SUBWIDGET_H

  • subwidget.cpp
#include "subwidget.h"

Subwidget::Subwidget(QWidget *parent) : QWidget(parent)
{
    btn_subwidget = new QPushButton("显示父窗口",this);
    btn_subwidget->move(100,100);	//移动按钮的位置
    this.resize(200,200);	//指定当前窗口的大小

    connect(btn_subwidget,&QPushButton::clicked,this,&Subwidget::emitSignal);   //将按钮点击信号和槽函数关连

}

void Subwidget::emitSignal()
{
    emit close();     //向外发送一个关闭子窗口的信号
}

注意:

  1、widget类中创建了一个subwidget类,所以可以在widget窗口中对当前widget窗口和subwidget子窗口进行直接操作,但是在subwidget类中,却不能对那个widget窗口进行操作(可以好好想一想)。所以如果需要在subwidget类中对widget类进行操作,就可以利用信号机制,即subwidget发送一个信号给widget类,然后通知widget对自身进行操作。

(2)、自定义信号的重载

//如果发送的信号需要携带参数,那么槽函数也就需要接收此参数。
1、对信号进行重载:

signals:
    void signal();
    void signal(int);
    void signal(QString);

2、将重载的信号和对应的槽函数进行绑定:

方法一:通过QT4版本的SIGNAL()和SLOT()功能。

方法二:通过将重载信号赋值给有参的指针函数。

void (MainWindow:: *s0)(int) = &MainWindow::signal;
connect(this,s0,[=](){
           				qDebug()<<"signal0"
 });

void (MainWindow:: *s1)(int) = &MainWindow::signal;
connect(this,s1,[=](int i){
           					qDebug()<<i;
 });
 
void (MainWindow:: *s2)(QString) = &MainWindow::signal;
connect(this,s2,[=](QString str){
          				  		 qDebug()<<str
            });

方法三:通过OverLoad方式。

connect(this, QOverload<>::of(&MainWindow::signal),[=](){

           qDebug()<<"signal0";
             });
connect(this, QOverload<int>::of(&MainWindow::signal),[=](int i){

           qDebug()<<i;
             });   
connect(this, QOverload<QString>::of(&MainWindow::signal),[=](QString str){

           qDebug()<<str;
             });                       

对信号进行重载,发送有参信号时需要指定其中的参数:

emit signal();
emit signal(1);
emit signal("aaaa");


此时如果再用上面的连接语句,编译器就不知道对应的信号和槽是有参还是无参。

//此种连接不行了
connect(&subwidget,&Subwidget::close,this,&Widget::subwidgetClose);      //将子窗口的close信号和槽函数绑定

//换成如下(利用函数指针):

	//定义一个指向subwidget类的有参函数指针,并将信号函数的地址赋值给它,此时编译器就知道这个函数指针指向了有参信号函数。
void (subwidget::*subwidgetSignal)(QString) = &subwidget::close;		
	//同理,定义一个指向有参槽函数的函数指针
void (widget::*subwidgetSignal)(QString) = &Widget::subwidgetClose;	
	//此时调用如下语句,就指向了有参的信号和槽函数了
connect(&subwidget,&Subwidget::close,this,&Widget::subwidgetClose);      //将子窗口的close信号和槽函数绑定

注意:

带参数的信号和对应的带参数的槽函数,参数类型要一一对应。

信号中的参数可以比对应连接的槽函数参数多,但是反之不行!

(3)、信号连接槽函数

1、QT4版本的connect函数
在这里插入图片描述
还有就是,在上面重载有参信号和槽函数时,不是需要创建有参/无参的函数指针吗?

如果用QT4版本的信号和槽函数写法,完全不用那么麻烦,直接将参数类型带到函数里面就行,比如SIGNAL(signal(int))。

2、QT5版本的connect函数

  • 2.1、通过编写槽函数的方式:
    connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method);
    即connect(信号发送者对象指针,发送者对象的信号函数地址,信号接收者对象指针,接收者对象的槽函数地址);
  • 2.2、通过lamda表达式:
    connect(const QObject *sender, const char *signal,{/ * 这里写槽函数的功能代码 * /});

注意:在UI设计界面中,选中控件,然后通过鼠标右键转到槽函数,这样的槽函数不需要通过connect将信号和该槽函数进行绑定,系统会自动绑定。比较方便。这样的槽函数系统命名都有规律:

即:1,以on_开头 2,加上组件名称,如pushButton_1(组件的名称一定要正确,否则不会自动关联),3,在加上操作_clicked()void MainWindow::on_pushButton_clicked()
{
}

(4)、信号连接信号

我们一般用connect函数用于将一个信号和另一个槽函数进行连接。除此之外,我们也可以将一个信号和另一个信号进行连接。

例如:在自定义信号和槽函数那个程序里,subwidget窗口中,有一个按钮,当我们点击按钮后,按钮会触发click信号,我们将按钮的click信号和emitSignal槽函数进行连接,然后在emitSignal槽函数发送close信号的。(这种方法需要定义一个点击按钮的槽函数,比较麻烦)

所以有了信号连接信号的功能,我们可以直接将按钮的click信号和subwidget的close信号进行连接:

 connect(btn_subwidget,&QPushButton::clicked,this,&Subwidget::close);   //将按钮点击信号和close信号连接

(5)、断开信号连接

程序中需要将某些信号和槽函数断开连接,可以用 disconnect() 函数,其中参数和connect写法一样。

总结:

在这里插入图片描述

2、菜单栏、工具栏、状态栏和浮动窗口

在这里插入图片描述

(1)、菜单栏

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
注意创建菜单栏有两种方式:
(1)、创建一个可以指定父亲的菜单栏

QMenuBar * menuBar = new QMenuBar(this);
this->setMenuBar(menuBar);

(2)、创建默认父亲是mainwindow的菜单栏

QMenuBar * menuBar = menuBar();
this->setMenuBar(menuBar);

对于这种创建方式,当创建菜单项时,可以进行简化为:

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

(2)、工具栏

在这里插入图片描述
在这里插入图片描述

(3)、状态栏

在这里插入图片描述

(4)、浮动窗口

在这里插入图片描述

(5)、实例代码

代码:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMenuBar>
#include <QMenu>
#include <QToolBar>
#include <QPushButton>
#include <QStatusBar>
#include <QLabel>
#include <QDockWidget>
#include <QTextEdit>
#include <QDebug>

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

    //注意:创建的菜单栏、工具栏、状态栏、浮动窗口都需要加入到mainwindow中去!!!

//1、新建菜单栏
    QMenuBar *menuBar = new QMenuBar(this);     //新建菜单栏对象
    this->setMenuBar(menuBar);                  //将菜单栏加入到mainwindow中去

    //在菜单栏中添加菜单项
    QMenu *fileMenu = menuBar->addMenu("文件");
    QMenu *editMenu =  menuBar->addMenu("编辑");

    //修改菜单栏的背景颜色
    //this->setStyleSheet("QMenu::item:selected{background-color:#ff0000;} QMenuBar{background-color:#ee00ff;}");//紫色

    //对菜单项添加动作
    QAction *fileOpenAction = fileMenu->addAction("打开");
    QAction *fileSaveAction = fileMenu->addAction("保存");
    QAction *editCopyAction = editMenu->addAction("复制");

    //给菜单的动作添加槽函数
    connect(fileOpenAction,&QAction::triggered,this,[=](){qDebug()<<"打开成功!";});

//2、新建工具栏
    QToolBar *toolBar = new QToolBar(this);             //新建工具栏对象
    this->addToolBar(toolBar);                          //将工具栏对象加入到mainwindow中去
    //toolBar->setAllowedAreas(Qt::LeftToolBarArea|Qt::RightToolBarArea);      //设置工具栏可以存在的区域

    //为工具栏中添加动作
    toolBar->addAction("编辑");
    toolBar->addAction("项目");

    //为工具栏添加按钮控件
    QPushButton *btn = new QPushButton("工具栏控件",this);
    toolBar->addWidget(btn);

//3、新建状态栏
    QStatusBar *statusBar = new QStatusBar(this);       //新建一个状态栏对象
    this->setStatusBar(statusBar);                      //将状态栏添加到mainwindow中去

    //给状态栏添加控件
    QLabel *label1 = new QLabel("状态栏的一个标签控件",this);
    QLabel *label2 = new QLabel("状态栏的一个标签控件,属于固定控件",this);
    statusBar->addWidget(label1);
    statusBar->addWidget(new QLabel("标签2"));
    statusBar->addPermanentWidget(label2);
    statusBar->addPermanentWidget(new QLabel("固定标签2"));

//4、新建浮动窗口
    QDockWidget *dockWidget = new QDockWidget();                //新建一个浮动窗口对象
    this->addDockWidget(Qt::RightDockWidgetArea,dockWidget);    //将浮动窗口添加到mainwindow中

    //给浮动栏中添加控件
    QTextEdit * textEdit = new QTextEdit(this);
    dockWidget->setWidget(textEdit);
}

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


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

3、资源文件添加

在程序中,有的控件需要显示ICON图标,
一种方式就是指定图片文件的路径,如果图片路径被改变,需要重新指定。
二种就是将图片文件放在工程文件下,然后将这些图片添加到工程的资源文件中去(推荐)。这里举例第二种:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注:为什么添加文件的时候需要先添加前缀?
因为一个大的工程项目,往往需要用到很多资源文件,通过前缀可以对资源文件进行分类。

使用资源文件:

//对ui中菜单项下的Action事件添加资源文件下的图片
ui->actionopen->setIcon(QIcon(":/pictures/2.png")); 
 
//对ui中的标签控件添加资源文件下的图片               
ui->label_2->setStyleSheet("border-image: url(:/pictures/2.png)");  

或者
ui->label_2->setPixmap(QPixmap(":/pictures/2.png"));

注:添加资源文件——“: + 前缀 + 文件名”

4、模态和非模态对话框

在对话框存在时,不能对其它窗口进行操作,即为模态对话框。反之为非模态。

1、模态对话框:
实现点击按钮,弹出一个模态对话框。

connect(ui->pushButton,&QPushButton::clicked,this,[=](){
        QDialog *dialog = new QDialog(this);
        qDebug()<<"模态对话框打开了";
//        dialog->open();   //非阻塞

        dialog->exec();     //阻塞在这里,等待关闭
        dialog.setAttribute(Qt::WA_DeleteOnClose);
        qDebug()<<"模态对话框关闭了";
    });

2、非模态对话框:
实现点击按钮,弹出一个模态对话框。

connect(ui->pushButton,&QPushButton::clicked,this,[=](){
        QDialog *dialog = new QDialog(this);
		dialog->show();
		dialog.setAttribute(Qt::WA_DeleteOnClose);
    });

关闭对话框后,对话框对象并没有被删除,所以需要一条语句使得关闭对话框后能够删除该对象资源: dialog.setAttribute(Qt::WA_DeleteOnClose);

5、对话框

1、消息对话框QMessageBox:
在这里插入图片描述
例如:
在这里插入图片描述
2、其它对话框

(1)、颜色对话框QColorDialog:
在这里插入图片描述
(2)、文件对话框QFileDialog:
在这里插入图片描述
(3)、字体对话框QFontDialog:

6、listWidget列表控件

1、用addItem()方法一次添加一条列表
在这里插入图片描述

在这里插入图片描述

变为水平居中:

在这里插入图片描述

在这里插入图片描述

2、用addItems()方法一次添加多条列表:
在这里插入图片描述

在这里插入图片描述
注:这种方法,不可以实现列表水平居中。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

掏一淘哆啦A梦的奇妙口袋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值