Qt学习笔记

1.Qt(音同 cute)

是一个跨平台的 C++ 开发库,主要用来开发图形用户界面(Graphical User Interface,GUI)程序,当然也可以开发不带界面的命令行(Command User Interface,CUI)程序。

2.Qt的安装

http://c.biancheng.net/view/3858.html

3.Qt的安装目录

在这里插入图片描述

4.main.cpp文件讲解

在这里插入图片描述
1~2 行:由于 main() 函数中分别定义了 QApplication 和 MainWindow 类的对象,因此需要引入 mainwindows.h 和 QApplication 头文件。mainwindow.h 文件是我们自己创建的,引入时用" "双引号括起来;QApplication 是 Qt 提供给我们的,引入时用<>括起来。
第 7 行:MainWindow 是自定义的类,继承自 QMainWindow 主窗口类,因此 MainWindow 也是一个主窗口类。w 是 MainWindow 类实例化出的对象,表示一个主窗口
第 8 行:默认情况下,Qt 提供的所有组件(控件、部件)都是隐藏的,不会自动显示。通过调用 MainWindow 类提供的 show() 方法,w 窗口就可以在程序运行后显示出来。

5.mainwindow.h文件讲解

在这里插入图片描述
初始状态下,MainWindow 类由 Q_OBJECT、构造函数和析构函数组成,这里重点介绍一下 Q_OBJECT 和构造函数:
Q_OBJECT:本质是一个已定义好的宏,所有需要“信号和槽”功能的组件都必须将 Q_OBJECT 作为 private 属性成员引入到类中。
带参的构造函数:QWidget 是所有组件的基类,借助 parent 指针,可以为当前窗口指定父窗口。

下面是 视频链接https://www.bilibili.com/video/BV1N34y1H7x7的笔记,

6 widget.h文件讲解

在这里插入图片描述

7widget.cpp文件讲解

在这里插入图片描述

8信号和槽

连接信号和槽的四种方式
注意:
1)信号与槽的参数个数和类型需要一致,至少信号的参数不能少于槽的参数。如果不匹配,会出现编译错误或运行错误。
2)使用信号和槽的类中,必须在类的定义中加入宏Q_OBJECT

1.鼠标放在组件上点击右键,选到槽,选择信号
widget.h文件中增加了:

private slots:
    void on_commitPushButton_clicked();

widget.cpp文件中增加了

void Widget::on_commitPushButton_clicked()
{
}

然后需要手动补充函数:实现获取输入框的内容,并打开输入的软件

//widget.h中:
#include<QProcess>

//widget.cpp中补充函数on_commitPushButton_clicked(),
void Widget::on_commitPushButton_clicked()
{
    //获取lineEdit数据 访问界面数据
    QString program=ui->cmdLineEdit->text();
    //创建process对象
    QProcess *myProcess = new QProcess(this);
    myProcess->start(program);
}

点击运行
2.使用connect连接信号和槽4个参数 谁发出 发出啥 谁处理 怎么处理

//按下回车键执行槽函数
connect(ui->cmdLineEdit,SIGNAL(returnPressed()),this,SLOT(on_commitPushButton_clicked()));

3.使用connect连接信号和槽4个参数 &符号 自动填充

//前提:需要去widget.h文件中声明函数名,在widget.cpp文件中实现槽函数也就是方法一种自动添加的两部分类似
void on_cancelPushButton_clicked();//widget.h
void Widget::on_cancelPushButton_clicked()//widget.cpp
{
    this->close();//关闭窗口
}
//点击取消键执行槽函数
connect(ui->cancelPushButton,&QPushButton::clicked,this,&Widget::on_cancelPushButton_clicked);

4.使用connect连接信号和槽3个参数 当操作内容较少时,不使用处理函数

//前提:QMessageBox要在widget.h文件中声明#include<QMessageBox>
//点击浏览键,弹出信息
 connect(ui->browsepushButton,&QPushButton::clicked,[this]()
    {
        QMessageBox::information(this,"信息","点击浏览");
    });

总结widget.cpp文件:

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

//构造函数
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    //connect连接信号和操 谁发出 发出啥 谁处理 怎么处理
    connect(ui->cmdLineEdit,SIGNAL(returnPressed()),this,SLOT(on_commitPushButton_clicked()));
    //&符号
    connect(ui->cancelPushButton,&QPushButton::clicked,this,&Widget::on_cancelPushButton_clicked);
    //不使用槽函数
    connect(ui->browsepushButton,&QPushButton::clicked,[this]()
    {
        QMessageBox::information(this,"信息","点击浏览");
    });
}
//析构函数
Widget::~Widget()
{
    delete ui;
}

void Widget::on_commitPushButton_clicked()
{
    //获取lineEdit数据 访问界面数据
    QString program=ui->cmdLineEdit->text();
    //创建process对象
    QProcess *myProcess = new QProcess(this);
    myProcess->start(program);
}
void Widget::on_cancelPushButton_clicked()
{
    this->close();//关闭窗口
}



9四则运算计算器的实现

1)网格的应用
2)信号和槽
3)在按钮上放图片,改变按钮背景颜色

//wedget.cpp
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    //按钮上放图片
    QIcon con("E:\\22cqqCode\\QtCode\\calculate\\1.png");
    ui->backButton->setIcon(con);

    //改变按钮的背景色
    ui->equalButton->setStyleSheet("background:blue");
}

4)QString 和char *的转换

//把QString转换成char *
QByteArray byteArray;
byteArray.append(expression);//QString->QByteArray
strcpy(opt,byteArray.data());//QByteArray->QString

5)栈的应用QStack 用stack实现四则运算https://blog.csdn.net/qq_63844103/article/details/123875163

void Widget::on_equalButton_clicked()
{
    QStack<int> s_num;
    QStack<char> s_opt;

    char opt[128]={0};
    int i=0,tmp=0,num1,num2;
    //把QString转换成char *
    QByteArray byteArray;
    byteArray.append(expression);//QString->QByteArray
    strcpy(opt,byteArray.data());//QByteArray->QString

    /*四则运算用栈实现
     * 将中缀表达式转为后缀表达式->计算后缀表达式
     * 1.数字(直接入栈s_num)
     * 2.运算符(s_opt栈空直接入栈,非空若当前运算符大于s_opt栈顶的优先级才可入栈)
     * 3.'('(直接入栈s_opt)
     * 4.')'(一直弹出栈顶元素,直到遇到'(',将其弹出后,继续遍历字符串)
     * 5.遍历结束,依次弹出栈内元素
     * 从s_opt中每弹出一个运算符(除左括号外),就要从s_num中弹出两个数字参与运算,并将结果放回s_num中
     */
    while(opt[i]!='\0'||s_opt.isEmpty()!=true){
        if(opt[i]>='0'&&opt[i]<='9'){//数字
            tmp=tmp*10+opt[i]-'0';
            i++;
            if(opt[i]<'0'||opt[i]>'9'){
                s_num.push(tmp);
                tmp=0;
            }
        }
        else{//运算符
            if(s_opt.isEmpty()==true||Priority(opt[i])>Priority(s_opt.top())||
                    (s_opt.top()=='(' && opt[i]!=')')){
                s_opt.push(opt[i]);
                i++;
                continue;
            }//将运算符入栈
            if(s_opt.top()=='('&&opt[i]==')'){
                s_opt.pop();
                i++;
                continue;
            }//将运算符'('出栈
            if(Priority(opt[i])<=Priority(s_opt.top())||(opt[i]==')'&&s_opt.top()!='(')
                    ||(opt[i]=='\0'&&s_opt.isEmpty()!=true)){
                num2=s_num.pop();
                num1=s_num.pop();
                switch (s_opt.pop()) {
                    case '+':
                        s_num.push(num1+num2);
                        break;
                    case '-':
                        s_num.push(num1-num2);
                        break;
                    case '*':
                        s_num.push(num1*num2);
                        break;
                    case '/':
                        s_num.push(num1/num2);
                        break;
                    default:
                        break;
                }
            }//将其他运算符出栈,并弹出两个元素进行计算
        }
    }
    ui->showLineEdit->setText(QString::number(s_num.top()));
    expression.clear();
}

int Widget:: Priority(char ch){//优先级函数
    switch (ch) {
        case '(': return 3;
        case '*':
        case '/': return 2;
        case '+':
        case '-': return 1;
        default:
            return 0;
    }
}

10QObject定时器 startTimer killTimer 事件函数QTimerEvent

1)在label标签上放图片方法一

QPixmap pix("E:\\22cqqCode\\QtCode\\objectTimer\\1.jpeg");
ui->label->setPixmap(pix);

2)用QObject定时器实现图片1秒钟切换一次
在这里插入图片描述
总结widget.cpp文件:

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

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
	//放图片
    pixId=2;
    QPixmap pix("E:\\22cqqCode\\QtCode\\objectTimer\\1.jpeg");
    ui->label->setPixmap(pix);
}

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

void Widget::on_startButton_clicked()
{
    //开启定时器,返回定时器编号
    myTimerId = this->startTimer(TIMEOUT);
}
void Widget::timerEvent(QTimerEvent *event)
{
    if(event->timerId()!=myTimerId)
        return ;

    //更新图片
    QString path("E:\\22cqqCode\\QtCode\\objectTimer\\");
    path+=QString::number(pixId);
    path+=".jpeg";
    QPixmap pix(path);
    ui->label->setPixmap(pix);
    pixId++;
    if(6==pixId) pixId=1;
}
void Widget::on_stopButton_clicked()
{
    this->killTimer(myTimerId);
}

QObject定时器主要是三个函数,开始startTimer,触发事件,结束killTimer

11QTimer定时器

1)在label标签上放图片方法二

QImage img;
img.load("E:\\22cqqCode\\QtCode\\objectTimer\\1.jpeg");
ui->label->setPixmap(QPixmap::fromImage(img));

2)用QTimer定时器实现图片1秒钟切换一次;
用QTimer定时器实现图片1秒钟切换,只切换一次
widget.h文件中的槽函数和成员变量
在这里插入图片描述
总结widget.cpp文件:

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

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    timer=new QTimer;//指针初始化
    //放图片
    QImage img;
    img.load("E:\\22cqqCode\\QtCode\\objectTimer\\1.jpeg");
    ui->label->setPixmap(QPixmap::fromImage(img));
    pixId=2;
    //定时器时间到,发出timeout信号
    connect(timer,&QTimer::timeout,this,&Widget::timeoutSlot);
}

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

void Widget::on_startButton_clicked()
{
    timer->start(TIMEOUT);//开始定时器,时间为TIMEOUT=1000ms
}
void Widget::timeoutSlot()
{
    QString path;
    path="E:\\22cqqCode\\QtCode\\objectTimer\\";
    path+=QString::number(pixId);
    path+=".jpeg";
    QImage img;
    img.load(path);
    ui->label->setPixmap(QPixmap::fromImage(img));
    pixId++;
    if(pixId==6) pixId=1;
}
void Widget::on_endButton_clicked()
{
    timer->stop();//结束
}
void Widget::on_singleButton_clicked()
{
    QTimer::singleShot(1000,this,SLOT(timeoutSlot()));//单次执行超时触发函数
}

12文件操作(QMainWindow),简易记事本(新建,打开,另存为,ctrl+s键盘事件)

1)QMainWindow菜单栏
在这里插入图片描述

2)通过connect连接信号和槽

connect(ui->newAction,&QAction::triggered,this,&MainWindow::newActionSlot);
connect(ui->openAction,&QAction::triggered,this,&MainWindow::openActionSlot);
connect(ui->saveAction,&QAction::triggered,this,&MainWindow::saveActionSlot);

3)读文件和写文件

//读文件
QString fileName=QFileDialog::getOpenFileName(this,"选择一个文件",
                                 QCoreApplication::applicationFilePath(),"*.cpp");
//写文件                                
QString fileName=QFileDialog::getSaveFileName(this,"选择一个文件",
                                QCoreApplication::applicationFilePath());                                 

4)鼠标事件QMouseEvent,键盘事件QKeyEvent,ctrl+S实现保存
在这里插入图片描述

总结widget.cpp文件:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //被单击的时候触发事件
    connect(ui->newAction,&QAction::triggered,this,&MainWindow::newActionSlot);
    connect(ui->openAction,&QAction::triggered,this,&MainWindow::openActionSlot);
    connect(ui->saveAction,&QAction::triggered,this,&MainWindow::saveActionSlot);
}

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

void MainWindow::newActionSlot()
{
    ui->textEdit->clear();
    this->setWindowTitle("新建文本文档.txt");
}
void MainWindow::openActionSlot()
{
    QString fileName=QFileDialog::getOpenFileName(this,"选择一个文件",
                                 QCoreApplication::applicationFilePath());
    if(fileName.isEmpty()){
        QMessageBox::warning(this,"警告","请选择一个文件");
    }
    else{
        //打印
        qDebug()<<fileName;
        QFile file(fileName);
        file.open(QIODevice::ReadOnly);
        QByteArray ba=file.readAll();
        ui->textEdit->setText(QString(ba));
        file.close();
    }
}
void MainWindow::saveActionSlot()
{
    QString fileName=QFileDialog::getSaveFileName(this,"选择一个文件",
                                QCoreApplication::applicationFilePath());
    if(fileName.isEmpty()){
        QMessageBox::warning(this,"警告","请选择一个文件");
    }
    else{
        QFile file(fileName);
        file.open(QIODevice::WriteOnly);
        QByteArray ba;
        ba.append(ui->textEdit->toPlainText());
        file.write(ba);
        file.close();
    }
}
void MainWindow::keyPressEvent(QKeyEvent *k)
{
    if(k->modifiers()==Qt::ControlModifier&&k->key()==Qt::Key_S){
        saveActionSlot();
    }
}
void MainWindow::mousePressEvent(QMouseEvent *m)
{
    QPoint pt=m->pos();
    qDebug()<<pt;
    if(m->button()==Qt::LeftButton){
        qDebug()<<"左键被按下";
    }
    if(m->button()==Qt::RightButton){
        qDebug()<<"右键被按下";
    }
}


13TCP客户端和TCP服务器,Qt启动新窗口

1)TCP服务器 socket bind listen accept send/recv
TCP客户端 socket connect send/recv

服务器和客户端的ui界面
在这里插入图片描述

涉及到网络操作需要在工程文件中添加network
在这里插入图片描述
2)客户端发出连接, 连接成功发出connected,连接断开发出disconnected信号
在这里插入图片描述
3)服务器监听ip地址和端口号
在这里插入图片描述
4)客户端向服务器发送信息,创建新的窗口
在这里插入图片描述在这里插入图片描述
修改槽函数,连接成功的时候出现聊天界面
在这里插入图片描述
chat.cpp文件中的发送按钮触发的槽函数
在这里插入图片描述

总结,

  1. 客户端需要有聊天窗口,当连接成功时,创建新的窗口,也要将socket对象传过去
  2. 聊天窗口的信号与槽操作,将聊天内容通过socket->write写入
  3. 服务器端通过sender()函数获取信号的发出者socket,然后通过socket->readAll读出发送的信息
//服务器收到客户端发送的信息,socket发出readyread信号
connect(socket,&QTcpSocket::readyRead,this,&Widget::clientInfoSlot);

void Widget::clientInfoSlot()
{
    //获取信号的发出者
    QTcpSocket *s=qobject_cast<QTcpSocket *>(sender());//强制类型转换
    ui->mainLineEdit->setText(QString( s->readAll()));
}

14多线程 QThread

服务器端使用多线程
mythread.h文件

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>
#include <QTcpSocket>
#include <QDebug>

class myThread : public QThread
{
    Q_OBJECT
public:
    explicit myThread(QTcpSocket *s);
    void run();//线程处理函数
signals:

public slots:
    void clientInfoSlot();

private:
    QTcpSocket *socket;
};


#endif // MYTHREAD_H

mythread.cpp文件

#include "mythread.h"

myThread::myThread(QTcpSocket *s)
{
    socket=s;
}
void myThread::run()
{
    //处理客户端
    connect(socket,&QTcpSocket::readyRead,this,&myThread::clientInfoSlot);
}
//无法通过ui打印在界面上 ,不能在其他类里面操作界面
void myThread::clientInfoSlot()
{
    QByteArray ba=socket->readAll();
    qDebug()<<QString(ba);//信息显示在服务器的输出端
}

在widget.cpp文件中连接成功的槽函数中启动线程
在这里插入图片描述

缺陷是:不能在其他类里面操作界面,也就是无法在mythread中操作ui界面,使得客户端发送的信息能够显示在服务器界面上
解决:下面的自定义信号,然后通过emit关键字发送信号

15自定义信号Signals

实现将对象t中的内容发送到对象w中显示出来
mythread.h文件中添加自定义信号
在这里插入图片描述
mythread.cpp文件中需要修改部分
在这里插入图片描述
widget.cpp构造函数中修改部分以及threadSlot(QByteArray b)函数
在这里插入图片描述

数据的显示是服务器后台的线程收到信息,线程通过信号把数据发送到窗口,窗口通过控件显示数据

16MySQL数据库

1)涉及到数据库操作需要在工程文件中添加sql
在这里插入图片描述
2)widget.cpp文件中数据库连接的操作

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

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

    //连接数据库
    db=QSqlDatabase::addDatabase("QMYSQL");//加载MySQL数据库驱动
    db.setDatabaseName("mydatabase");//数据库名
    db.setPort(3306);//端口号
    db.setHostName("localhost");//主机名
    db.setUserName("root");//用户名
    db.setPassword("root");//用户密码
    if(db.open())
    {
        QMessageBox::information(this,"连接提示","连接成功");
    }
    else
    {
        QMessageBox::warning(this,"连接提示","连接失败");
    }

}

Widget::~Widget()
{
    delete ui;
}
//查询
void Widget::on_selectButton_clicked()
{
    QSqlQuery query;
    query.exec("select * from student;");//query.exec执行
    while (query.next()) {//query.next指向结果集的下一条记录
        qDebug()<<query.value(0)<<query.value(1)<<query.value(2);//query.value
    }
}
//插入
void Widget::on_insertButton_clicked()
{
    QString id=ui->idLineEdit->text();
    QString name=ui->nameLineEdit->text();
    QString birth=ui->birthLineEdit->text();
    QString sql=QString("insert into student values(%1,'%2','%3');").arg(id).arg(name).arg(birth);
    QSqlQuery query;
    if(query.exec(sql))
    {
        QMessageBox::information(this,"插入提示","插入成功");
    }
    else {
        QMessageBox::warning(this,"插入提示","插入失败");
    }
}

3)在这里插入图片描述

17 QTableView控件

1)QTableView
在这里插入图片描述

2)widget.h文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QMessageBox>
#include <QSqlDatabase>
#include <QSqlTableModel>
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

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

private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;
    QSqlTableModel *m;
};

#endif // WIDGET_H

3)widget.cpp文件

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

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    QSqlDatabase db=QSqlDatabase::addDatabase("QMYSQL");//加载MySQL数据库驱动
    db.setDatabaseName("mydatabase");
    db.setPort(3306);
    db.setHostName("localhost");
    db.setUserName("root");
    db.setPassword("root");
    if(db.open())
    {
        QMessageBox::information(this,"连接提示","连接成功");

        m=new QSqlTableModel(this);
        m->setTable("student");//与表连接
        ui->tableView->setModel(m);
    }
    else
    {
        QMessageBox::warning(this,"连接提示","连接失败");
    }
}

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

void Widget::on_pushButton_clicked()
{
    m->select();
}

4)关键
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值