QT实例


模拟cmd窗口

#ifndef WIDGET_H
#define WIDGET_H

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

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private slots:
	// 将槽函数放在这里
    void on_commitButton_clicked();
    void on_cancelButton_clicked();

private:
    Ui::Widget *ui;
};

#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
	// 信号与槽函数的三种连接方式
    connect(ui->comLineEdit,SIGNAL(returnPressed()),this,SLOT(on_commitButton_clicked()));

    connect(ui->comLineEdit,&QLineEdit::returnPressed,this,&Widget::on_commitButton_clicked);
        
    connect(ui->cancelButton,&QPushButton::clicked,this,&Widget::on_cancelButton_clicked);
        
    // 当槽函数的代码过少时可以考虑,这种连接方式,不需要额外的的槽函数
    connect(ui->browsButton_3,&QPushButton::clicked,[this](){
        // QMessageBox 产生弹窗,this表示当前的窗口是这个窗口的父类,需要添加#include <QMessageBox>
        QMessageBox::information(this,"左上角","内容");
    });
}

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

void Widget::on_commitButton_clicked()
{
    // 获取文本框的数据
    QString program=ui->comLineEdit->text();
    // 运行程序,需要添加#include <QProcess>
    QProcess *myProcess = new QProcess(this);
    myProcess->start(program);
}
void Widget::on_cancelButton_clicked()
{
    // 关闭窗口
    this->close();
}
#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

image-20210619183759735

计算器

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

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 设置窗口的大小,使它不会因为拖动而改变大小
    this->setMaximumSize(180,270);
    this->setMinimumSize(180,270);
    // 设置标题
    this->setWindowTitle("计算机");

    // 设置行编辑的字体和大小
    QFont f("宋体",22);
    ui->lineEdit->setFont(f);

    // 按钮贴上图片
    QIcon Icon("C:\\Users\\地表最菜\\Pictures\\Saved Pictures\\test.jpg");
    QSize IconSize(60,60);
    ui->pushButton_back->setIcon(Icon);
    ui->pushButton_back->setIconSize(IconSize);

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

    connect(ui->pushButton_0,&QPushButton::clicked,this,&Widget::clicked_Button_0);
    connect(ui->pushButton_1,&QPushButton::clicked,this,&Widget::clicked_Button_1);
    connect(ui->pushButton_2,&QPushButton::clicked,this,&Widget::clicked_Button_2);
    connect(ui->pushButton_3,&QPushButton::clicked,this,&Widget::clicked_Button_3);
    connect(ui->pushButton_4,&QPushButton::clicked,this,&Widget::clicked_Button_4);
    connect(ui->pushButton_5,&QPushButton::clicked,this,&Widget::clicked_Button_5);
    connect(ui->pushButton_6,&QPushButton::clicked,this,&Widget::clicked_Button_6);
    connect(ui->pushButton_7,&QPushButton::clicked,this,&Widget::clicked_Button_7);
    connect(ui->pushButton_8,&QPushButton::clicked,this,&Widget::clicked_Button_8);
    connect(ui->pushButton_9,&QPushButton::clicked,this,&Widget::clicked_Button_9);
    connect(ui->pushButton_muti,&QPushButton::clicked,this,&Widget::clicked_Button_muti);
    connect(ui->pushButton_reduce,&QPushButton::clicked,this,&Widget::clicked_Button_reduce);
    connect(ui->pushButton_add,&QPushButton::clicked,this,&Widget::clicked_Button_add);
    connect(ui->pushButton_div,&QPushButton::clicked,this,&Widget::clicked_Button_div);
    connect(ui->pushButton_equal,&QPushButton::clicked,this,&Widget::clicked_Button_equal);
    connect(ui->pushButton_back,&QPushButton::clicked,this,&Widget::clicked_Button_back);
    connect(ui->pushButton_Clear,&QPushButton::clicked,this,&Widget::clicked_Button_clear);
    connect(ui->pushButton_right,&QPushButton::clicked,this,&Widget::clicked_Button_right);
    connect(ui->pushButton_left,&QPushButton::clicked,this,&Widget::clicked_Button_left);
}

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

void Widget::clicked_Button_0()
{
    expression+='0';
    // 设置行编辑的输出
    ui->lineEdit->setText(expression);
}
void Widget::clicked_Button_1()
{
    expression+='1';
    ui->lineEdit->setText(expression);
}
void Widget::clicked_Button_2()
{
    expression+='2';
    ui->lineEdit->setText(expression);
}
void Widget::clicked_Button_3()
{
    expression+='3';
    ui->lineEdit->setText(expression);
}
void Widget::clicked_Button_4()
{
    expression+='4';
    ui->lineEdit->setText(expression);
}
void Widget::clicked_Button_5()
{
    expression+='5';
    ui->lineEdit->setText(expression);
}
void Widget::clicked_Button_6()
{
    expression+='6';
    ui->lineEdit->setText(expression);
}
void Widget::clicked_Button_7()
{
    expression+='7';
    ui->lineEdit->setText(expression);
}
void Widget::clicked_Button_8()
{
    expression+='8';
    ui->lineEdit->setText(expression);
}
void Widget::clicked_Button_9()
{
    expression+='9';
    ui->lineEdit->setText(expression);
}
void Widget::clicked_Button_muti()
{
    expression+='*';
    ui->lineEdit->setText(expression);
}
void Widget::clicked_Button_reduce()
{
    expression+='-';
    ui->lineEdit->setText(expression);
}
void Widget::clicked_Button_add()
{
    expression+='+';
    ui->lineEdit->setText(expression);
}
void Widget::clicked_Button_div()
{
    expression+='/';
    ui->lineEdit->setText(expression);
}
void Widget::clicked_Button_equal()
{
    expression.clear();
    ui->lineEdit->clear();
    expression+="我也不知道,懒得写了";
    ui->lineEdit->setText(expression);
}
void Widget::clicked_Button_right()
{
    expression+=')';
    ui->lineEdit->setText(expression);
}
void Widget::clicked_Button_left()
{
    expression+='(';
    ui->lineEdit->setText(expression);
}
void Widget::clicked_Button_back()
{
    // 删除最后一位
    expression.chop(1);
    ui->lineEdit->setText(expression);
}
void Widget::clicked_Button_clear()
{
    expression.clear();
    ui->lineEdit->clear();
}
#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    // 解决设计时大小与运行之后大小相差太大的缺陷
    if(QT_VERSION>=QT_VERSION_CHECK(5,6,0))
            QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

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

private slots:
    void clicked_Button_0();
    void clicked_Button_1();
    void clicked_Button_2();
    void clicked_Button_3();
    void clicked_Button_4();
    void clicked_Button_5();
    void clicked_Button_6();
    void clicked_Button_7();
    void clicked_Button_8();
    void clicked_Button_9();
    void clicked_Button_add();
    void clicked_Button_reduce();
    void clicked_Button_muti();
    void clicked_Button_div();
    void clicked_Button_equal();
    void clicked_Button_back();
    void clicked_Button_clear();
    void clicked_Button_right();
    void clicked_Button_left();
private:
    Ui::Widget *ui;
    QString expression;
};

#endif // WIDGET_H

image-20210619221525939

基于定时器与图片的相册

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

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    connect(ui->pushButton_start,&QPushButton::clicked,this,&Widget::pushButton_start_clicked);
    connect(ui->pushButton_stop,&QPushButton::clicked,this,&Widget::pushButton_stop_clicked);

    // 显示图片
    QPixmap pic("C:\\Users\\地表最菜\\Pictures\\Saved Pictures\\pic (1).png");
    ui->label->setPixmap(pic);
    namekey=2;
}

Widget::~Widget()
{
    delete ui;
}
void Widget::pushButton_start_clicked()
{
    // 开启定时器,返回定时器编号
    // 当时间到了发出信号调用timerEvent,之后又循环计时间
    mytimerid=this->startTimer(TIMEOUT);
}
void Widget::timerEvent(QTimerEvent *event)
{
    if(event->timerId()!=mytimerid){
        return;
    }
    
    // 拼接图片的路径
    QString picname("C:\\Users\\地表最菜\\Pictures\\Saved Pictures\\pic (");
    // 将数字转换为QString
    picname+=QString::number(namekey);
    picname+=").png";
    
    // 让标签显示图片
    QPixmap pic(picname);
    ui->label->setPixmap(pic);

    namekey++;
    if(namekey>=12)
        namekey=1;
}
void Widget::pushButton_stop_clicked()
{
    // 关闭定时器
    this->killTimer(mytimerid);
}
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QPixmap>
#include <QTimer>

#define TIMEOUT 2*1000

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    virtual void timerEvent(QTimerEvent *event);
    ~Widget();

private slots:
    void pushButton_start_clicked();
    void pushButton_stop_clicked();

private:
    Ui::Widget *ui;
    int namekey;
    int mytimerid;
};

#endif // WIDGET_H
#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{

    if(QT_VERSION>=QT_VERSION_CHECK(5,6,0))
            QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

image-20210620160028193

image-20210620160257251

必须要勾上scaledContents,让图片自适应标签,否则图片会出现只会显示部分的情况

其它方式展示图片与定时器的功能

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTimer>

#define TIMEOUT 2*1000
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

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

private slots:
    void pushButton_start_clicked();
    void pushButton_stop_clicked();
    void pushButton_signal_clicked();
    void myTimerEvent();

private:
    Ui::Widget *ui;
    int picId;
    QTimer *timer;
};

#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    timer=new QTimer;
    connect(timer,&QTimer::timeout,this,&Widget::myTimerEvent);
    connect(ui->pushButton_start,&QPushButton::clicked,this,&Widget::pushButton_start_clicked);
    connect(ui->pushButton_stop,&QPushButton::clicked,this,&Widget::pushButton_stop_clicked);
    connect(ui->pushButton_signal,&QPushButton::clicked,this,&Widget::pushButton_signal_clicked);
    picId=2;

    QImage img;
    img.load("C:\\Users\\地表最菜\\Pictures\\Saved Pictures\\pic (1).png");
    ui->label->setPixmap(QPixmap::fromImage(img));
}

Widget::~Widget()
{
    delete ui;
}
void Widget::pushButton_start_clicked()
{
    timer->start(TIMEOUT);
}
void Widget::myTimerEvent()
{
    // 文件路径名拼接
    QString imgname("C:\\Users\\地表最菜\\Pictures\\Saved Pictures\\pic (");
    imgname+=QString::number(picId);
    imgname+=").png";

    // 图片显示
    QImage img;
    img.load(imgname);
    ui->label->setPixmap(QPixmap::fromImage(img));

    picId++;
    if(picId>=12)
        picId=1;
}
void Widget::pushButton_stop_clicked()
{
    timer->stop();
}
void Widget::pushButton_signal_clicked()
{
    // 单次定时
    QTimer::singleShot(TIMEOUT,this,&Widget::myTimerEvent);
}
#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

image-20210620165623799

image-20210620165709131

文件操作

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFileDialog>
#include <QMessageBox>
#include <QDebug>
namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
private slots:
    void open_file();
    void save_file();
    void new_file();
};

#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->action_new,&QAction::triggered,this,&MainWindow::new_file);
    connect(ui->action_open,&QAction::triggered,this,&MainWindow::open_file);
    connect(ui->action_save,&QAction::triggered,this,&MainWindow::save_file);
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::new_file()
{
    // 清空内容
    ui->textEdit->clear();
    // 修改窗口文字
    this->setWindowTitle("新建一个文件");
}
void MainWindow::open_file()
{
    // 选择文件,并且返回文件的路径,如果点击取消则会返回空,需要添加#include <QFileDialog>
    // applicationFilePath获取当前进程的路径,默认路径
    // .txt限制文件的类型,如果不写则代表所有的类型
    QString fileName = QFileDialog::getOpenFileName(this, "打开一个文件",
                                QApplication::applicationFilePath(),"*.txt");
    if(fileName.isEmpty()){
        // 警告窗口,需要添加QMessageBox头文件
        QMessageBox::warning(this,"警告","请选择一个文件");
    }else{
        // 在调试信息输出文件的名字
        qDebug() << fileName;
        // 打开文件,并且以只读方式打开
        QFile file(fileName);
        file.open(QIODevice::ReadOnly);
        // 读取文件,注意返回类型是QByteArray
        QByteArray data=file.readAll();
        // 修改textEdit里面的内容
        ui->textEdit->setText(QString(data));
        // 注意关闭文件
        file.close();
    }
}
void MainWindow::save_file()
{
    // 打开要保存的路径,并且返回路径,如果不写第四个参数则代表所有的文件
    QString fileName=QFileDialog::getSaveFileName(this,"保存文件",
                                        QApplication::applicationFilePath());
    if(fileName.isEmpty()){
        QMessageBox::warning(this,"警告","请选择一个文件");
    }else{
        QFile file(fileName);
        file.open(QIODevice::WriteOnly);
        // 获取textEdit里面的内容,返回的是QString
        QString data=ui->textEdit->toPlainText();
        // 将QString转换为QByteArray
        QByteArray bytedata;
        bytedata.append(data);
        file.write(bytedata);
        file.close();
    }
}
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

image-20210620193508066

image-20210620193519914

image-20210620193548573

注意UI时要加上&符号,让用户可以通过键盘来实现点击操作

image-20210620194024050

消息基础

application能够知道哪个窗口在哪个位置,能知道应该由哪个窗口来接收消息,这个窗口会调用自己的消息处理函数

窗口的event()函数处理所有经过窗口的消息

消息处理函数是虚函数,使用要进行重载

常见的QT事件类型如下:

  • 键盘事件:按键按下和松开
  • 鼠标事件:鼠标移动,鼠标按键的按下和松开
  • 拖放事件:用鼠标进行拖放
  • 滚轮事件:鼠标滚轮滚动
  • 绘屏事件:重绘屏幕的某些部分
  • 定时事件:定时器到时
  • 焦点事件:键盘焦点移动
  • 进入和离开事件:鼠标移动widget之内,或是移出
  • 移动事件:widget的位置改变
  • 大小改变事件:widget的大小改变
  • 显示和隐藏事件:widget显示和隐藏
  • 窗口事件:窗口是否为当前窗口

QT将系统产生的消息转化为QT事件,QT事件被封装为对象,所有的QT事件均继承抽象类QEvent,用于描述内部或外部发生的动作,任意的QObject对象都具备处理QT事件的能力。

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFileDialog>
#include <QMessageBox>
#include <QDebug>
#include <QMouseEvent>
#include <QKeyEvent>
namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    // 重载键盘事件
    virtual void keyPressEvent(QKeyEvent *k);
    // 重载鼠标事件
    virtual void mousePressEvent(QMouseEvent *m);
    ~MainWindow();


private:
    Ui::MainWindow *ui;
private slots:
    void open_file();
    void save_file();
    void new_file();
};

#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->action_new,&QAction::triggered,this,&MainWindow::new_file);
    connect(ui->action_open,&QAction::triggered,this,&MainWindow::open_file);
    connect(ui->action_save,&QAction::triggered,this,&MainWindow::save_file);
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::new_file()
{
    // 清空内容
    ui->textEdit->clear();
    // 修改窗口文字
    this->setWindowTitle("新建一个文件");
}
void MainWindow::open_file()
{
    // 选择文件,并且返回文件的路径,如果点击取消则会返回空,需要添加#include <QFileDialog>
    // applicationFilePath获取当前进程的路径,默认路径
    // .txt限制文件的类型,如果不写则代表所有的类型
    QString fileName = QFileDialog::getOpenFileName(this, "打开一个文件",
                                QApplication::applicationFilePath(),"*.txt");
    if(fileName.isEmpty()){
        // 警告窗口,需要添加QMessageBox头文件
        QMessageBox::warning(this,"警告","请选择一个文件");
    }else{
        // 在调试信息输出文件的名字
        qDebug() << fileName;
        // 打开文件,并且以只读方式打开
        QFile file(fileName);
        file.open(QIODevice::ReadOnly);
        // 读取文件,注意返回类型是QByteArray
        QByteArray data=file.readAll();
        // 修改textEdit里面的内容
        ui->textEdit->setText(QString(data));
        // 注意关闭文件
        file.close();
    }
}
void MainWindow::save_file()
{
    // 打开要保存的路径,并且返回路径,如果不写第四个参数则代表所有的文件
    QString fileName=QFileDialog::getSaveFileName(this,"保存文件",
                                        QApplication::applicationFilePath());
    if(fileName.isEmpty()){
        QMessageBox::warning(this,"警告","请选择一个文件");
    }else{
        QFile file(fileName);
        file.open(QIODevice::WriteOnly);
        // 获取textEdit里面的内容,返回的是QString
        QString data=ui->textEdit->toPlainText();
        // 将QString转换为QByteArray
        QByteArray bytedata;
        bytedata.append(data);
        file.write(bytedata);
        file.close();
    }
}
void MainWindow::keyPressEvent(QKeyEvent *k)
{
    // 实现ctrl+s保存文件
    // 需要添加头文件,#include <QMouseEvent>
    // 可以通过帮助搜素查找函数和宏
    // modifiers查看热键是否被按下,key代表普通键是否被按下
    if(k->modifiers()==Qt::ControlModifier&&k->key()==Qt::Key_S){
        save_file();
    }
}
void MainWindow::mousePressEvent(QMouseEvent *m)
{
    // 需要添加头文件,#include <QKeyEvent>
    // pos函数返回坐标
    qDebug()<<m->pos();
    if(m->button()==Qt::LeftButton){
        qDebug()<<"按下左键";
    }else if(m->button()==Qt::RightButton){
        qDebug()<<"按下右键";
    }
}

客户端

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpSocket>
#include <QMessageBox>
#include <QHostAddress>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private slots:
    void buttonCommitClicked(void);
    void buttonCancelClicked(void);

private:
    Ui::Widget *ui;
    QTcpSocket *socket;
};

#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    connect(ui->pushButton_Commit,&QPushButton::clicked,this,&Widget::buttonCommitClicked);
    connect(ui->pushButton_Cancel,&QPushButton::clicked,this,&Widget::buttonCancelClicked);
    // 初始化socket
    socket=new QTcpSocket;
}

Widget::~Widget()
{
    delete ui;
}
void Widget::buttonCommitClicked(void)
{
    // 获取ip和端口号
    QString ip=ui->lineEdit_Ip->text();
    QString port=ui->lineEdit_Port->text();

    // 连接服务器
    socket->connectToHost(QHostAddress(ip),port.toShort());

    // 连接状态提醒
    connect(socket,&QTcpSocket::connected,[this](){
        QMessageBox::information(this,"连接提示","连接成功");
    });
    connect(socket,&QTcpSocket::disconnected,[this](){
        QMessageBox::warning(this,"连接提示","连接失败");
    });

}
void Widget::buttonCancelClicked(void)
{
    this->close();
}
#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

注意:必须修改.pro工程文件,在第七行QT末尾加上network

image-20210623190529323

image-20210623190554262

服务器

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostAddress>
#define PORT 8000
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private slots:
    void newConnectHander(void);


private:
    Ui::Widget *ui;
    QTcpServer *server;
};

#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"

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

    // 进入监听状态
    // 需要QHostAddress和QTcpServer头文件
    server->listen(QHostAddress::AnyIPv4,PORT);

    // 当出现连接时运行函数
    connect(server,&QTcpServer::newConnection,this,&Widget::newConnectHander);
}

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

void Widget::newConnectHander(void)
{
    // 建立TCP连接
    // 需要QTcpSocket头文件
    QTcpSocket *s=server->nextPendingConnection();

    // 获取客户端的IP地址
    // 将QHostAddress类型转换为QString类型
    ui->lineEdit_IP->setText(s->peerAddress().toString());

    // 获取客户端的端口号,端口号很有可能与服务器端口号不一样
    // 将数字类型转换为QString类型
    ui->lineEdit_PORT->setText(QString::number(s->peerPort()));
}
#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

image-20210623190836006

注意:必须修改.pro工程文件,在第七行QT末尾加上network

在TCP客户端基础实现信息传输

#ifndef CHAT_H
#define CHAT_H

#include <QWidget>
#include <QTcpSocket>

namespace Ui {
class Chat;
}

class Chat : public QWidget
{
    Q_OBJECT

public:
    explicit Chat(QTcpSocket* socket,QWidget *parent = 0);
    ~Chat();
private slots:
    void sendMessage(void);
    void recvMessage(void);
    void clearMessage(void);

private:
    Ui::Chat *ui;
    QTcpSocket *socket;
};

#endif // CHAT_H
#include <QTcpSocket>
#include <QMessageBox>
#include <QHostAddress>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private slots:
    void buttonCommitClicked(void);
    void buttonCancelClicked(void);

private:
    Ui::Widget *ui;
    QTcpSocket *socket;
};

#endif // WIDGET_H
#include "chat.h"
#include "ui_chat.h"

Chat::Chat(QTcpSocket *socket, QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Chat)
{
    ui->setupUi(this);
    this->socket=socket;
    // 服务器发送数据到客户端,客户端会产生readyRead信号
    connect(socket,&QTcpSocket::readyRead,this,&Chat::recvMessage);

    connect(ui->pushButtonSend,&QPushButton::clicked,this,&Chat::sendMessage);
    connect(ui->pushButtonClear,&QPushButton::clicked,this,&Chat::clearMessage);
}

Chat::~Chat()
{
    delete ui;
}
void Chat::recvMessage()
{
    // 将QByteArray类型转换为QString
    // 读出数据
    ui->lineEditRecv->setText(QString(socket->readAll()));
}
void Chat::sendMessage()
{
    QByteArray data;
    // 将QString转换为QByteArray类型
    data.append(ui->lineEditSend->text());
    // 写数据
    socket->write(data);
    ui->lineEditSend->clear();
}
void Chat::clearMessage()
{
    ui->lineEditRecv->clear();
}
#include "widget.h"
#include "ui_widget.h"
#include "chat.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    connect(ui->pushButton_Commit,&QPushButton::clicked,this,&Widget::buttonCommitClicked);
    connect(ui->pushButton_Cancel,&QPushButton::clicked,this,&Widget::buttonCancelClicked);
    // 初始化socket
    socket=new QTcpSocket;
}

Widget::~Widget()
{
    delete ui;
}
void Widget::buttonCommitClicked(void)
{
    // 获取ip和端口号
    QString ip=ui->lineEdit_Ip->text();
    QString port=ui->lineEdit_Port->text();

    // 连接服务器
    socket->connectToHost(QHostAddress(ip),port.toShort());

    // 连接状态提醒
    connect(socket,&QTcpSocket::connected,[this](){
        QMessageBox::information(this,"连接提示","连接成功");
        // 注意这里必须使用堆空间,如果使用栈空间当函数运行完毕会被释放
        Chat *c=new Chat(socket);
        // 展示窗口
        c->show();
        // 隐藏现在这个窗口
        this->hide();
    });
    connect(socket,&QTcpSocket::disconnected,[this](){
        QMessageBox::warning(this,"连接提示","连接失败");
    });

}
void Widget::buttonCancelClicked(void)
{
    this->close();
}
#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

image-20210623202851406

image-20210623202913173

TCP服务器基础上实现信息传输

#ifndef CHATSERVER_H
#define CHATSERVER_H

#include <QWidget>
#include <QTcpSocket>

namespace Ui {
class ChatServer;
}

class ChatServer : public QWidget
{
    Q_OBJECT

public:
    explicit ChatServer(QTcpSocket *socket, QWidget *parent = 0);
    ~ChatServer();
private slots:
    void SendMessage(void);
    void RecvMessage(void);
    void ClearMessage(void);

private:
    Ui::ChatServer *ui;
    QTcpSocket *socket;

};

#endif // CHATSERVER_H
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostAddress>
#define PORT 8000
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private slots:
    void newConnectHander(void);


private:
    Ui::Widget *ui;
    QTcpServer *server;
};

#endif // WIDGET_H
#include "chatserver.h"
#include "ui_chatserver.h"

ChatServer::ChatServer(QTcpSocket *socket, QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ChatServer)
{
    ui->setupUi(this);
    this->socket=socket;
    connect(socket,&QTcpSocket::readyRead,this,&ChatServer::RecvMessage);
    connect(ui->pushButtonSend,&QPushButton::clicked,this,&ChatServer::SendMessage);
    connect(ui->pushButtonClear,&QPushButton::clicked,this,&ChatServer::ClearMessage);
}

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

void ChatServer::RecvMessage()
{
    // 获取信号的发送者
    QTcpSocket *s=(QTcpSocket *)sender();
    ui->lineEditRecv->setText(QString(s->readAll()));
}
void ChatServer::SendMessage()
{
    QByteArray data;
    data.append(ui->lineEditSend->text());
    socket->write(data);
    ui->lineEditSend->clear();
}
void ChatServer::ClearMessage()
{
    ui->lineEditRecv->clear();
}
#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}
#include "widget.h"
#include "ui_widget.h"
#include "chatserver.h"

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

    // 进入监听状态
    // 需要QHostAddress和QTcpServer头文件
    server->listen(QHostAddress::AnyIPv4,PORT);

    // 当出现连接时运行函数
    connect(server,&QTcpServer::newConnection,this,&Widget::newConnectHander);
}

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

void Widget::newConnectHander(void)
{
    // 建立TCP连接
    // 需要QTcpSocket头文件
    QTcpSocket *s=server->nextPendingConnection();

    // 获取客户端的IP地址
    // 将QHostAddress类型转换为QString类型
    ui->lineEdit_IP->setText(s->peerAddress().toString());

    // 获取客户端的端口号,端口号很有可能与服务器端口号不一样
    // 将数字类型转换为QString类型
    ui->lineEdit_PORT->setText(QString::number(s->peerPort()));

    ChatServer *chat=new ChatServer(s);
    chat->show();
}

创建新窗口的操作与在TCP客户端基础实现信息传输是一样的

image-20210623203243186

多线程和自定义信号

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QObject>
#include <QThread>
#include <QTcpSocket>

class myThread:public QThread
{
    Q_OBJECT
public:
    myThread(QTcpSocket *socket);
    // 线程运行函数
    void run();
private slots:
    void handleData(void);

signals:
    // 创建信号
    void sendData(QByteArray data);
private:
    QTcpSocket *socket;
};

#endif // MYTHREAD_H
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>

#define PORT 8000

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private slots:
    void newConnectHander(void);
    void handData(QByteArray data);

private:
    Ui::Widget *ui;
    QTcpServer *server;
};

#endif // WIDGET_H
#include "mythread.h"

myThread::myThread(QTcpSocket *socket)
{
    // 接收socket
    this->socket=socket;
}

void myThread::run()
{
    // 当有可读事件时用handleData函数处理
    connect(socket,&QTcpSocket::readyRead,this,&myThread::handleData);
}
void myThread::handleData()
{
    QByteArray data;
    data=socket->readAll();
    // 发送信号,不能通过传参的方式对ui进行修改,ui只能自己类可以进行修改
    emit sendData(data);
}
#include "widget.h"
#include "ui_widget.h"
#include "mythread.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    server=new QTcpServer;
    server->listen(QHostAddress::AnyIPv4,PORT);
    connect(server,&QTcpServer::newConnection,this,&Widget::newConnectHander);
}

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

void Widget::newConnectHander(void)
{
    QTcpSocket *s=server->nextPendingConnection();
    ui->lineEditIp->setText(s->peerAddress().toString());
    ui->lineEditPort->setText(QString::number(s->peerPort()));

    myThread *thread=new myThread(s);
    // 开始线程
    thread->start();

    // 处理thread发出来的sendData信号
    connect(thread,&myThread::sendData,this,&Widget::handData);
}

void Widget::handData(QByteArray data)
{
    ui->lineEditShow->setText(QString(data));
}
#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

ui只能在自己类才可以进行修改

连接MYSQL数据库

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QSqlDatabase>
#include <QMessageBox>
#include <QSqlQuery>
#include <QDebug>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private slots:
    void insertButton(void);
    void cancelButton(void);

private:
    Ui::Widget *ui;
};

#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 加载mysql驱动
    QSqlDatabase base=QSqlDatabase::addDatabase("QMYSQL");

    base.setHostName("47.108.71.9");
    base.setDatabaseName("dyl");
    base.setUserName("DYL");
    base.setPassword("199911");

    // open成功返回true,失败返回false
    if(base.open()){
        QMessageBox::information(this,"连接提示","连接成功");
    }else{
        QMessageBox::warning(this,"连接提示","连接失败");
    }
    connect(ui->pushButtonCheck,&QPushButton::clicked,this,&Widget::cancelButton);
    connect(ui->pushButtonInsert,&QPushButton::clicked,this,&Widget::insertButton);
}

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

void Widget::insertButton()
{
    QString id=ui->lineEditId->text();
    QString name=ui->lineEditName->text();
    QString sex=ui->lineEditSex->text();
    QString birth=ui->lineEditBirthday->text();
    QString sclass=ui->lineEditClass->text();

    QString command=QString("insert into student values('%1','%2','%3','%4','%5');").arg(id).arg(name).arg(sex).arg(birth).arg(sclass);

    // 操作数据库的对象,需要头文件
    QSqlQuery data;
    if(data.exec(command)){
        QMessageBox::information(this,"插入提示","插入成功");
    }else{
        QMessageBox::warning(this,"插入提示","插入失败");
    }
}

void Widget::cancelButton()
{
    QSqlQuery data;
    QString command("select * from student;");
    
    data.exec(command);
    while(data.next()){
        qDebug()<<data.value(0);
        qDebug()<<data.value(1);
        qDebug()<<data.value(2);
        qDebug()<<data.value(3);
        qDebug()<<data.value(4);
    }
}
#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

注意:需要在工程文件.pro下加入sql,而且必须在qc的lib库中加入libmysql.dll文件,不然无法加载驱动

image-20210625200335598

使用模型显示数据库表

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QSqlDatabase>
#include <QMessageBox>
#include <QSqlTableModel>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private slots:
    void checkButton(void);

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

#endif // WIDGET_H
#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");

    db.setHostName("47.108.71.9");
    db.setDatabaseName("dyl");
    db.setUserName("DYL");
    db.setPassword("199911");

    if(db.open()){
        QMessageBox::information(this,"连接提示","连接成功");
        
        view=new QSqlTableModel;
        // 模型与表进行关联
        view->setTable("student");
        // 模型与界面进行关联
        ui->tableView->setModel(view);

        connect(ui->checkButton,&QPushButton::clicked,this,&Widget::checkButton);
    }else{
        QMessageBox::warning(this,"连接提示","连接失败");
    }
}

Widget::~Widget()
{
    delete ui;
}
void Widget::checkButton()
{
    // 显示出表
    view->select();
}
#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

image-20210625203515935

image-20210625203807823


文章作者: dyl
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 dyl !
 上一篇
C++ lamdba表达式 C++ lamdba表达式
本文讲解lamdba表达式基本语法,本文对于初学C++萌新而言十分友好,lamdba表达式在C++使用广泛,掌握lambda表达式对于灵活使用C++非常重要
2023-12-10 dyl
下一篇 
MYSQL命令行 MYSQL命令行
本文章记录MYSQL的基本命令行操作,对于新手较友好,本文章来自于博主在各个网站搜索汇总,具有一定的参考价值
2023-12-10 dyl
  目录