QT学习大法

1.软件下载

下载地址

https://blog.csdn.net/weixin_42214237/article/details/131997396
安装使用教程

2 新建工程

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

(2)选择分类

QMAINWINDOW

带菜单栏
在这里插入图片描述

QWIGET

不带菜单栏
在这里插入图片描述

QDIALOG

对话框

(3)选择工具库
在这里插入图片描述
(4)选择编译工具
qmake才会产生 .pro文件
在这里插入图片描述

3.信号与槽

打开槽函数:
(1)右键控件,转到槽
(2)连接函数

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

    //连接信号与槽:谁发出信号,什么信号,谁处理,怎么处理
    connect(ui->lineEdit,SIGNAL(returnPressed()),this,SLOT(on_commitButton_clicked()));




}

(3)第二种连接函数写法
取地址法

connect(ui->cancelButton,&QPushButton::clicked,this, &Widget::on_cancelButton_clicked);

(4)基于lamda的连接函数

connect(ui->browseButton,&QPushButton::clicked,[this]()
    {
        QMessageBox::information(this,"信息","点击浏览");
    });

4.使用子线程

(1) .h文件添加包
#include
(2)创建process对象,并根据进程名执行

//创建process对象
    QProcess *myProcess = new QProcess(this);
    myProcess->start(program);  //运行一个子进程,根据进程名

5 实战:计算器实现

使用栈,添加头文件

#include<QStack>

使用

QStack<char> stk;
stack.push('a');

6 定时器

(1)QObject: startTimer killTimer

xx.cpp

 myTimerid =this->startTimer(TIMEOUT);//开启定时器,返回当前定时器编号
this->killTimer(myTimerid);//关闭定时器
//定时器事件定义
void Widget::timerEvent(QTimerEvent *event)
{
    if(event->timerId()!=myTimerid){
        return;
    }
    xxx
}

xx.h

声明虚函数

 virtual void timerEvent(QTimerEvent *event);  //定时器结束时触发的事件虚函数

(2)QTimer:

xx.cpp

timer = new QTimer;  //初始化定时器
timer->start(TIMEOUT);  //开启定时器,参数为定时时长(ms)
timer->stop();//结束定时

触发函数

void Widget::timeoutSlot()
{
    xxx
}
//连接器:定时器时间结束信号与处理槽
connect(timer,&QTimer::timeout,this,&Widget::timeoutSlot);
QTimer::singleShot(1000,this,SLOT(timeoutSlot())); //单次计时

xxx.h

private:
    Ui::Widget *ui;
    QTimer *timer;  //指针对象
    int picID;
    //槽函数的固定写法
private slots:
    void on_startBT_clicked();
    void timeoutSlot();


    void on_endBt_clicked();

    void on_pushButton_clicked();

7.图片显示

(1)

	QImage img;
   img.load("F:\\qtProject\\pic\\0.jpg");
   ui->label->setPixmap(QPixmap::fromImage(img));

(2)

QPixmap pix("E:\\Desktop\\pic\\0.jpg");
ui->label->setPixmap(pix);

8. QMainWindow 和 文件操作

在这里插入图片描述
编辑窗口占满全屏
在这里插入图片描述

编辑菜单栏:&操作可以添加快捷键,使用 alt+字母选中
在这里插入图片描述

窗体预览

alt+shift+R

窗体菜单层次

菜单栏 > 菜单 > 动作
在这里插入图片描述

文件操作

9 . 事件

在这里插入图片描述
event是事件的总入口
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

内部函数是斜体
在这里插入图片描述

xx.h中声明事件函数

void keyPressEvent(QKeyEvent *k);  //声明键盘事件虚函数
void mousePressEvent(QMouseEvent *m);  //声明鼠标事件虚函数

xx.cpp中定义事件函数

// 重写事件虚函数
void MainWindow::keyPressEvent(QKeyEvent *k)
{
    if (k->modifiers() == Qt::ControlModifier && k->key()== Qt::Key_S)  //ctrl+s
    {
        //QMessageBox::information(this,"提示","键盘生效");
        saveFileSlot();
    }
}

void MainWindow::mousePressEvent(QMouseEvent *m)
{
    QPoint pt = m->pos();  //获取鼠标位置
    qDebug()<<pt;

    if(m->button() == Qt::LeftButton)  //左键被按下
    {
        qDebug()<<"左键被按下";
    }
    else if(m->button() ==Qt::RightButton)
    {
        qDebug()<<"右键被按下";
    }
}

设置自动补全

10.TCP

LINUX TCP模型
在这里插入图片描述

添加网络库

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
客服端发起的一次连接:

socket->connectToHost(QHostAddress(ip), port.toShort());

服务端发起的永久连接:

QTcpSocket *socket = server->nextPendingConnection();

发送与接收消息

发送数据

	QString text = ui->lineEdit->text();
    QByteArray ba;
    ba.append(text);

    socket->write(ba);   //发送  QByteArray类型 的数据

接收数据

绑定接收信号与槽

connect(socket,&QTcpSocket::readyRead,this,&Chat::receivInfoSlot);

槽函数进行接收

ui->receiveEdit->setText(QString(socket->readAll()));

11.窗口跳转在这里插入图片描述

12.多线程

(1) 首先创建线程类,继承QThread
在这里插入图片描述
在这里插入图片描述

(2).h文件中加上 Q_OBJECT对象
在这里插入图片描述
(3)线程类中重写 run() 函数,处理实际的业务

(4)调用函数中开启线程

	mythread *t = new mythread(socket); //创建线程对象
    t->start();  //开始线程

无法单独运行QT生成的exe文件

在环境变量中添加qt程序的安装路径
在这里插入图片描述

13.自定义信号

ui对象只能在当前类中操作,其他类无法操作

在需要自定义信号的类中声明信号(函数)

signals:
    void sendToWidget(QByteArray b);  //自定义的信号,信号可以带参数

使用emit关键字发出信号

emit sendToWidget(ba);  //发送信号

在接受信号的类中就可以信号与槽了
其中,对象就是声明了信号的对象,信号类型就是信号函数,槽函数可以定义为有参函数,接受信号中的参数

connect(t,&mythread::sendToWidget,this,&Widget::threadSlot);//信号与槽

14. 数据库

mysql数据库的安装

navicat安装

首先需要添加sql外部库
在这里插入图片描述

解决报错:QMYSQL driver not loadedQSqlDatabase: available drivers xxx

==>链 接 点 这 里

配置文件

[mysql.pro]
TARGET = qsqlmysql

HEADERS += $$PWD/qsql_mysql_p.h

SOURCES += $$PWD/qsql_mysql.cpp $$PWD/main.cpp

#QMAKE_USE += mysql

OTHER_FILES += mysql.json

PLUGIN_CLASS_NAME = QMYSQLDriverPlugin
include(../qsqldriverbase.pri)

INCLUDEPATH += "C:/Program Files/MySQL\MySQL Server 5.7/include"

LIBS += "C:/Program Files/MySQL/MySQL Server 5.7/lib/libmysql.lib"

DESTDIR = D:\Qt\5.15.2\Src\qtbase\src\plugins\sqldrivers\mysql\lib\
[qsqldriverbase.pri]
QT  = core core-private sql-private

# For QMAKE_USE in the parent projects.
#include($$shadowed($$PWD)/qtsqldrivers-config.pri)
include(./configure.pri)


PLUGIN_TYPE = sqldrivers
load(qt_plugin)

DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII

15. QTableView

在这里插入图片描述

16. QCustomPlot使用

教程
下载链接

17. 结构体的互引用

链接

18. 项目移植到新电脑后注意事项

(1)项目路径不能有中文
(2)构建路径设置
在这里插入图片描述

19. 关于QPainterPath的一个问题

在QT 5.13之前的版本,QPainterPath类没有 clear( ) 函数;可以考虑使用 path = QPainterPath() 方式代替。

20. 鼠标单击、双击问题解决

在一个函数中,如果给全局变量赋值后,在本次执行过程中,定时器的槽函数对这个全局变量的修改不会被该函数获取到;

void slotTimeout(){
	flag = false;
}

void func1(){
	cout<<flag;   //  第二次进入函数时可以获取到全局变量的更该
	flag = true;   //对全局变量flag赋值
	timer->start(10);  //开启定时器,槽函数会对flag修改
	cout<<flag;   //但本次执行时 flag的值还是true; 

}

鼠标的
单击事件: void mousePressEvent(QMouseEvent *e);
双击事件: void mouseDoubleClickEvent(QMouseEvent *event);
在同时出现时会发现冲突,因为双击必然首先发生了单击,导致两个事件都会触发,与设计意图不符。

使用QTimer定时函数进行区分,在设定时间内发生了两次点击则执行双击事件,发生了一次点击则执行单击事件;

// [.h文件]
#ifndef CWINBUTTON_H
#define CWINBUTTON_H

#include <QPushButton>
#include <QTimer>

class CWinButton : public QPushButton
{
    Q_OBJECT
public:
    explicit CWinButton(QWidget *pParent=nullptr);

private slots:
    void slotTimerTimeOut();
    void clicked();

private:
    int m_nClickTimes;
    QTimer m_cTimer;
};

#endif // CWINBUTTON_H
// [.cpp文件]
#include "cwinbutton.h"
#include <QDebug>

CWinButton::CWinButton(QWidget *pParent):QPushButton(pParent)
{
    m_nClickTimes = 0;
    connect(&m_cTimer,SIGNAL(timeout()),this,SLOT(slotTimerTimeOut()));
    connect(this,SIGNAL(clicked(bool)),this,SLOT(clicked()));
}

void CWinButton::slotTimerTimeOut()
{
    qDebug()<<"CWinButton::slotTimerTimeOut"<<endl;
    m_cTimer.stop();
    if(1==m_nClickTimes){
        qDebug()<<"click event"<<endl;
        //TODO Click respond.
    }else if(2==m_nClickTimes){
        qDebug()<<"double click event"<<endl;
        //TODO Double click respond.
    }
    m_nClickTimes=0;
}

void CWinButton::clicked()
{
    qDebug()<<"CWinButton::clicked"<<endl;
    m_nClickTimes++;
    m_cTimer.start();
}

参考自 该博主文章 ;

21. SIGSEGV错误

错误提示如图:
使用debug定位时,有时能定位到具体的错误位置;有时只能定位到错误点所在的函数;
在这里插入图片描述

SIGSEGV 是一个常见的运行时错误信号;
表示程序试图访问一个无效的内存地址,通常是访问了未分配的内存、访问已释放的内存或访问越界的数组元素。如访问空指针、数组越界、非法内存操作等。

避免措施:

  • 数组定义时,留意数组边界并留下冗余地址;
int status[MAX_SIZE+5][MAX_SIZE+5];
  • 结构体/类定义时,通过构造体进行初始化赋值,避免访问空地址。
struct MapData{
    int x;   // 行、列
    int y;
    double up[3];  // up的x,y,cost
    double down[3];
    double left[3];
    double right[3];
    QByteArray name;
    //结构体的构造函数,用于初始化赋值
    MapData(){
        x= -1;
        y = -1;
        std::fill(up,up+3,-1);
        std::fill(down,down+3,-1);
        std::fill(left,left+3,-1);
        std::fill(right,right+3,-1);
        name="";
    }
};

涉及内存操作时,留意是否访问无效内存;

M_Data mapdata[MAX_SIZE+5][MAX_SIZE+5];
xxx

//在内存地址中,复制结构体数组mapdata给temp。 当mapdata中存在未赋值的结构体对象时,报错。
memcpy(temp,mapdata,sizeof(mapdata));  

22.由于结构体中使用了QByteArray数据,导致程序崩溃

原因未知

23. ui界面自动生成connect函数的机制

ui界面编译后会生成ui_xxx.h文件,在文件中执行 connectSlotsByName()函数,这个函数将控件与槽函数隐式连接起来

不同的控件类有其固定的信号(函数),通过转到槽的方式将这些信号与槽函数(通过命名的方式)隐式连接。
如:

[signal] void QAbstractItemView::pressed(const QModelIndex &index)

void on_listView_pressed(const QModelIndex &index);

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

24. toolbutton显示问题

设置以下才能显示字体
在这里插入图片描述

snap7通信

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值