【嵌入式】Windows10&树莓派3b+安装Qt-5教程

Windows10&树莓派3b+安装Qt-5教程

  • (一)安装Qt-5
    • (1.1)Windows10安装Qt-5教程
    • (2.1)树莓派端安装Qt-5教程
  • (二)在树莓派上完成一个简单的基于Qt的图形窗口应用程序
  • (三) 在前面实验的基础上,在树莓派上完成一个Qt+opencv图像显示,或者Qt+网络聊天的程序。
    • (3.1) Qt+opencv图像显示
    • (3.2) Qt+网络聊天的程序

目标:

  1. 在PC系统上(windows)和树莓派系统上分别安装和配置Qt5开发环境;
  2. 在树莓派上完成一个简单的基于Qt的图形窗口应用程序;
  3. 在前面实验的基础上
    3.1 在树莓派上完成一个Qt+opencv图像显示,
    3.2 Qt+网络聊天的程序。

(一)安装Qt-5

(1.1)Windows10安装Qt-5教程

(1). Qt-5.11.2下载

官网下载地址:http://download.qt.io/archive/qt/
【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第1张图片
选择qt-*.exe文件下载
【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第2张图片

(2). 配置
参考配置链接:VS2017+Qt-5配置
(3).VS2017+Qt-5创建简单ui界面
参考链接:VS2017+Qt-5编程

【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第3张图片

(2.1)树莓派端安装Qt-5教程

(1). 安装

  • 更新库文件
  • (如果树莓派已是最新版本,也可以略过下面3步,直接下载Qt-5)

sudo apt-get update
sudo apt-get upgrade
sudo rpi-update

teamviewer会更新到14.0版本出现的问题
1.当然树莓派的teamviewer不随机启动,我用putty打开远程连接,重置一下开机自启动:
$sudo /etc/init.d/xrdp start
$teamviewer --daemon start
$sudo reboot
重置完一定要重启树莓派!
2.可能会出现teamviewer连接失败问题,把PC端teamviewer更新到相应版本即可!
【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第4张图片
3.teamviewer版本更新不会更新ID号,因此根据之前的ID就可连接派啦~
【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第5张图片

  • 正式开始安装:

sudo apt-get install qt5-default

  • 出错、根据提示修改:

sudo dpkg --configure -a
【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第6张图片

  • 一波三折,继续安装:

sudo apt-get install qt5-default
【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第7张图片

sudo apt-get install qtcreator
【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第8张图片

(2). 配置

  1. 打开Qt-5:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第9张图片

  2. 打开Tools->Options
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第10张图片

  3. 配置Compilers:

  • 点击add找到gcc出现如下图框进行配置
  • 点击Browse添加GCC的位置(/usr/bin/gcc)
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第11张图片
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第12张图片
  • ABI选择arm-linux-generic-elf-32bit:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第13张图片
  1. 测试GCC和G++是否安装成功:

gcc -v
g++ -v
【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第14张图片
(如果未安装GCC和G++,百度教程安装~)

  1. 配置Kits:
  • 找到其中的Compiler,这里也要选择GCC找到其中的Compiler,这里也要选择GCC
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第15张图片
  • 将Debugger设为System GDB at/usr/bin/gdb:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第16张图片
    配置完成:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第17张图片

(二)在树莓派上完成一个简单的基于Qt的图形窗口应用程序

  1. 新建Project:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第18张图片
  2. 新建Qt窗体应用程序:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第19张图片
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第20张图片
  3. 一直next下去:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第21张图片
  4. 点击HelloQt目录下Forms进行可视化界面设置:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第22张图片
  5. 添加一个Label和Push Button;在Button上右键选择go to slot:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第23张图片
  6. 选择Clicked()信号槽(即事件):
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第24张图片
  7. 在on_pushButton_clicked()事件执行函数中添加改变label文字的语句:
void HelloQt::on_pushButton_clicked()
{
    ui->label->setText("Hello Qt!");
}

【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第25张图片

  1. 运行:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第26张图片
  2. 提示Save All:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第27张图片
  3. 遇见问题:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第28张图片
    在这里插入图片描述
  4. 运行程序:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第29张图片
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第30张图片
  5. 直接运行HelloQt:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第31张图片

(三) 在前面实验的基础上,在树莓派上完成一个Qt+opencv图像显示,或者Qt+网络聊天的程序。

(3.1) Qt+opencv图像显示

参考教程:Qt打开文件显示图片

(该博主有给5个详细Qt基于opencv处理图片的详细教程,博文链接)
【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第32张图片

(3.1.1)Qt+OpenCV构建二维图像处理界面
环境:树莓派3b+、 opencv-3.4.1、 Qt-5

目标:从菜单栏打开系统文件目录、选择图片显示、保存
【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第33张图片

  • 新建Qt窗体应用程序:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第34张图片

  • 命名项目为ImageProcessSystem:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第35张图片
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第36张图片

  • 没做任何更改,next:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第37张图片

  • 创建完成:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第38张图片

  • 自定义Mat2QImage函数,用于显示文件查找页面和图片显示页面,具体代码见源码

  • 配置 .pro文件,配置opencv库:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第39张图片

#参考路径:
INCLUDEPATH   += \home\pi\opencv-3.4.1\include \
                \home\pi\opencv-3.4.1\include\opencv \
                \home\pi\opencv-3.4.1\include\opencv2
                
LIBS += -L /usr/local/lib/ -lopencv_highgui -lopencv_core -lopencv_imgproc \
           -lopencv_video -lopencv_videoio -lopencv_imgcodecs -lpthread

LIBS位置非常重要,一般调试出错都是LIBS配置出错!
是在/usr/local/lib中的地址,不是你安装opencv的路径下,切记切记!!!!
【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第40张图片

  • qmake一下:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第41张图片
  • 创建ui
    从Widget Box中拖一个graphicsView到窗体中,用于图片展示:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第42张图片
    双击Type Here输入File->点击回车->保存为菜单栏第一项:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第43张图片
    双击File下的TypeHere->输入Open->回车->保存为子目录Open;重复创建子目录Save、Recover:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第44张图片
    双击窗体下方可修改对象的Name,Text等:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第45张图片
  • 在下方控件name处的action_Open:右键选择go to slot->选择triggered()进入代码编辑:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第46张图片
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第47张图片
    双击triggered()后会创建如下函数,添加一个openfile的源码
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第48张图片
    重复上面步骤添加action_Save&&action_Recover的triggered()函数,具体代码见源码

源码
ImageProgressSystem.pro

#-------------------------------------------------
#
# Project created by QtCreator 2018-11-27T02:36:05
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = ImageProcessingSystem
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += main.cpp\
        mainwindow.cpp

HEADERS  += mainwindow.h

FORMS    += mainwindow.ui

INCLUDEPATH   += \usr\local\include \
                \usr\local\include\opencv \
                \usr\local\include\opencv2

LIBS += -L /usr/local/lib/ -lopencv_highgui -lopencv_core -lopencv_imgproc \
                          -lopencv_video -lopencv_videoio -lopencv_imgcodecs -lpthread

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
#include 
#include 
using namespace cv;

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    QImage Mat2QImage(Mat& mat);//

private:
    Ui::MainWindow *ui;

public:
    Mat src,dst;
    QImage dstImg;
private slots:
    void on_action_Open_triggered();
    void on_action_Save_triggered();
    void on_action_Recover_triggered();
};
#endif // MAINWINDOW_H

mainwindow.cpp

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

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

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

QImage MainWindow::Mat2QImage(Mat &mat){
    if(mat.type()==CV_8UC1)
    {
        QImage image(mat.cols,mat.rows,QImage::Format_Indexed8);
        image.setColorCount(256);
        for(int i=0;i<256;i++){
            image.setColor(i,qRgb(i,i,i));
        }
        uchar *pSrc=mat.data;
        for(int row=0;row<mat.rows;row++){
            uchar *pDest=image.scanLine(row);
            memcpy(pDest,pSrc,mat.cols);
            pSrc +=mat.step;
        }
        return image;
    }else if(mat.type()==CV_8UC3){
        const uchar *pSrc=(const uchar*)mat.data;
        QImage image(pSrc,mat.cols,mat.rows,mat.step,QImage::Format_RGB888);
        return image.rgbSwapped();
    }else if(mat.type()==CV_8UC4){
        const uchar *pSrc=(const uchar*)mat.data;
        QImage image(pSrc,mat.cols,mat.rows,mat.step,QImage::Format_ARGB32);
        return image.copy();
    }else{
        return QImage();
    }
}

void MainWindow::on_action_Open_triggered()
{
    QString fileName=QFileDialog::getOpenFileName(this,"Open",".","Image files(*.bmp *.jpg *.png)");
    src=imread(fileName.toStdString());
    dst=src.clone();
    dstImg=Mat2QImage(dst);
    QGraphicsScene *scene = new QGraphicsScene;
    scene->addPixmap(QPixmap::fromImage(dstImg));
    ui->graphicsView->setScene(scene);
    ui->graphicsView->show();
}

void MainWindow::on_action_Save_triggered(){
    QString fileName=QFileDialog::getOpenFileName(this,"Save",".","Image files(*.bmp *.jpg *.png)");
    imwrite(fileName.toStdString(),dst);
}

void MainWindow::on_action_Recover_triggered(){
    dstImg=Mat2QImage(src);
    QGraphicsScene *scene=new QGraphicsScene;
    scene->addPixmap(QPixmap::fromImage(dstImg));
    ui->graphicsView->setScene(scene);
    ui->graphicsView->show();
}

main.cpp

#include "mainwindow.h"
#include 

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

    return a.exec();
}
  • 运行程序:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第49张图片
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第50张图片
    点击File下拉目录Open
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第51张图片
    选择一张图片展示:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第52张图片
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第53张图片
    大功告成!还可以对图片进行opencv库的高级操作,教程链接点这儿~

(3.2) Qt+网络聊天的程序

参考教程:Qt-基于TCP聊天室
聊天室分为server端和client端,

server端:

  1. 监听所有client端,登录提示登录用户的ID;
  2. 输入端口号,可查看该端口用户对话。

client端:

  1. 创建个人ID,用于登录和识别;
  2. 输入服务器地址,登录服务器;
  3. 多个client端输入相同端口号,可监听消息,达到对话目的。

大致界面设计如下:
【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第54张图片

(3.2.1)server端Qt界面设计
(a)创建项目

  1. 树莓派3b+ Qt-5新建Qt窗体应用程序,命名为chat_test
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第55张图片
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第56张图片
  2. 命名tcpserver:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第57张图片
  3. 在项目chat_test右键、分别新建tcpclientsocket.h和tcpclientsocket.cpp;dialog.h和dialog.cpp:【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第58张图片
    创建完成如下图:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第59张图片
    (b)代码扩充
  • chat_test.pro:
QT       += network

【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第60张图片

  • dialog.h
#ifndef TCPSERVER_H
#define TCPSERVER_H

#include 
#include 
#include 
#include 
#include 
#include 
#include "tcpserver.h"

class TcpServer : public QDialog
{
    Q_OBJECT

public:
    TcpServer(QWidget *parent = 0,Qt::WindowFlags f=0);
    ~TcpServer();
private:
    QListWidget *ContentListWidget;
    QLabel *PortLabel;
    QLineEdit *PortLineEdit;
    QPushButton *CreateBtn;
    QGridLayout *mainLayout;
    int port;
    Server *server;
public slots:
    void slotCreateServer();
    void updateServer(QString,int);  //更新服务器上的信息显示
};

#endif // TCPSERVER_H
  • tcpclientsocket.h
#ifndef TCPCLIENTSOCKET_H
#define TCPCLIENTSOCKET_H

#include 
#include 

//用于与客户端通信
class TcpClientSocket : public QTcpSocket
{
    Q_OBJECT
public:
    TcpClientSocket(QObject *parent=0);
signals:
    void updateClients(QString,int);
    void disconnected(int);
protected slots:
    void dataReceived();
    void slotDisconnected();
};

#endif // TCPCLIENTSOCKET_H
  • tcpserver.h
#ifndef SERVER_H
#define SERVER_H

#include 
#include 
#include "tcpclientsocket.h"

//TCP服务器,监听指定端口的TCP连接
class Server : public QTcpServer
{
    Q_OBJECT
public:
    Server(QObject *parent=0,int port=0);
    QList<TcpClientSocket*> tcpClientSocketList;
signals:
    void updateServer(QString,int);
public slots:
    void updateClients(QString,int);
    void slotDisconnected(int);
protected:
    void incomingConnection(int socketDescriptor);
};

#endif // SERVER_H
  • dialog.cpp
#include "dialog.h"

TcpServer::TcpServer(QWidget *parent,Qt::WindowFlags f)
    : QDialog(parent,f)
{
    setWindowTitle(tr("TCP Server"));

    ContentListWidget = new QListWidget;

    PortLabel = new QLabel(tr("端口:"));
    PortLineEdit = new QLineEdit;

    CreateBtn = new QPushButton(tr("创建聊天室"));

    mainLayout = new QGridLayout(this);
    mainLayout->addWidget(ContentListWidget,0,0,1,2);
    mainLayout->addWidget(PortLabel,1,0);
    mainLayout->addWidget(PortLineEdit,1,1);
    mainLayout->addWidget(CreateBtn,2,0,1,2);

    port=1234;
    PortLineEdit->setText(QString::number(port));

    connect(CreateBtn, SIGNAL(clicked()), this, SLOT(slotCreateServer()));
}

TcpServer::~TcpServer()
{

}

void TcpServer::slotCreateServer()
{
    server = new Server(this, port);
    connect(server, SIGNAL(updateServer(QString, int)), this, SLOT(updateServer(QString, int)));

    CreateBtn->setEnabled(false);
}

void TcpServer::updateServer(QString msg, int length)
{
    ContentListWidget->addItem(msg.left(length));
}
  • tcpclientsocket.cpp
#include "tcpclientsocket.h"

TcpClientSocket::TcpClientSocket(QObject *parent)
{
                    connect(this,SIGNAL(readyRead()),this,SLOT(dataReceived()));
    connect(this,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));
}

void TcpClientSocket::dataReceived()
{
    while(bytesAvailable()>0)
    {
        int length = bytesAvailable();
        char buf[1024];
        read(buf,length);

        QString msg=buf;
        emit updateClients(msg, length);
    }
}

void TcpClientSocket::slotDisconnected()
{
    emit disconnected(this->socketDescriptor());
}
  • tcpserver.cpp
#include "tcpserver.h"

Server::Server(QObject *parent,int port)
    :QTcpServer(parent)
{
    listen(QHostAddress::Any,port);
}

//出现一个新的连接时触发
void Server::incomingConnection(int socketDescriptor)
{
    TcpClientSocket *tcpClientSocket = new TcpClientSocket(this);
    connect(tcpClientSocket, SIGNAL(updateClients(QString,int)), this, SLOT(updateClients(QString,int)));
    connect(tcpClientSocket, SIGNAL(disconnected(int)), this, SLOT(slotDisconnected(int)));

    tcpClientSocket->setSocketDescriptor(socketDescriptor);

    tcpClientSocketList.append(tcpClientSocket);
}

//将任意客户端发来的信息进行广播
void Server::updateClients(QString msg,int length)
{
    emit updateServer(msg,length);
    for(int i=0; i<tcpClientSocketList.count(); i++)
    {
        QTcpSocket *item = tcpClientSocketList.at(i);
        if(item->write(msg.toLatin1(),length) != length)
        {
            continue;
        }
    }
}

//将断开连接的TcpSocket对象删除
void Server::slotDisconnected(int descriptor)
{
    for(int i=0;i<tcpClientSocketList.count();i++)
    {
        QTcpSocket *item = tcpClientSocketList.at(i);
        if(item->socketDescriptor()==descriptor)
        {
            tcpClientSocketList.removeAt(i);
            return;
        }
    }
    return;
}
  • main.cpp
#include "tcpclientsocket.h"
#include "tcpserver.h"
#include "dialog.h"
#include 

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    TcpServer w;
    w.show();
    return a.exec();
}

( c ) 调试代码

运行加载比较慢,请耐心等待:
在这里插入图片描述
在这里插入图片描述
运行后,chat_test项目同目录下生成build-chat_test-Deskto-Debug文件夹:
【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第61张图片
进入文件夹,点击chat_test可执行文件:
【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第62张图片
【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第63张图片
(3.2.2)server端Qt界面设计
(a)创建项目

  1. 命名为TcpClient:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第64张图片
  2. 命名:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第65张图片
    创建完成如下图:
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第66张图片
    (b)源码
  • TcpClient.pro:
QT       += network

【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第67张图片

  • tcpClient.h
#ifndef TCPCLIENT_H
#define TCPCLIENT_H

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

class TcpClient : public QDialog
{
    Q_OBJECT

public:
    TcpClient(QWidget *parent = 0,Qt::WindowFlags f=0);
    ~TcpClient();
private:
    QListWidget *contentListWidget;
    QLineEdit *sendLineEdit;
    QPushButton *sendBtn;
    QLabel *userNameLabel;
    QLineEdit *userNameLineEdit;
    QLabel *serverIPLabel;
    QLineEdit *serverIPLineEdit;
    QLabel *portLabel;
    QLineEdit *portLineEdit;
    QPushButton *enterBtn;
    QGridLayout *mainLayout;
    bool status;
    int port;
    QHostAddress *serverIP;
    QString userName;
    QTcpSocket *tcpSocket;
public slots:
    void slotEnter();
    void slotConnected();
    void slotDisconnected();
    void dataReceived();
    void slotSend();
};

#endif // TCPCLIENT_H
  • tcpclient.cpp
#include "tcpclient.h"
#include 
#include 

TcpClient::TcpClient(QWidget *parent,Qt::WindowFlags f)
    : QDialog(parent,f)
{
    setWindowTitle(tr("TCP Client"));

    contentListWidget = new QListWidget;

    sendLineEdit = new QLineEdit;
    sendBtn = new QPushButton(tr("发送"));

    userNameLabel = new QLabel(tr("用户名:"));
    userNameLineEdit = new QLineEdit;

    serverIPLabel = new QLabel(tr("服务器地址:"));
    serverIPLineEdit = new QLineEdit;

    portLabel = new QLabel(tr("端口:"));
    portLineEdit = new QLineEdit;

    enterBtn= new QPushButton(tr("进入聊天室"));

    mainLayout = new QGridLayout(this);
    mainLayout->addWidget(contentListWidget,0,0,1,2);
    mainLayout->addWidget(sendLineEdit,1,0);
    mainLayout->addWidget(sendBtn,1,1);
    mainLayout->addWidget(userNameLabel,2,0);
    mainLayout->addWidget(userNameLineEdit,2,1);
    mainLayout->addWidget(serverIPLabel,3,0);
    mainLayout->addWidget(serverIPLineEdit,3,1);
    mainLayout->addWidget(portLabel,4,0);
    mainLayout->addWidget(portLineEdit,4,1);
    mainLayout->addWidget(enterBtn,5,0,1,2);

    status = false;

    port = 1234;
    portLineEdit->setText(QString::number(port));

    serverIP =new QHostAddress();

    connect(enterBtn,SIGNAL(clicked()),this,SLOT(slotEnter()));
    connect(sendBtn,SIGNAL(clicked()),this,SLOT(slotSend()));

    sendBtn->setEnabled(false);
}

TcpClient::~TcpClient()
{

}

void TcpClient::slotEnter()
{
    if(!status)
    {
        QString ip = serverIPLineEdit->text();
        if(!serverIP->setAddress(ip))
        {
            QMessageBox::information(this,tr("error"),tr("server ip address error!"));
            return;
        }

        if(userNameLineEdit->text()=="")
        {
            QMessageBox::information(this,tr("error"),tr("User name error!"));
            return;
        }

        userName=userNameLineEdit->text();

        tcpSocket = new QTcpSocket(this);
        connect(tcpSocket,SIGNAL(connected()),this,SLOT(slotConnected()));
        connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));
        connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(dataReceived()));

        tcpSocket->connectToHost(*serverIP,port);

        status=true;
    }
    else
    {
        int length=0;
        QString msg=userName+tr(":Leave Chat Room");
        if((length=tcpSocket->write(msg.toLatin1(),msg.length()))!=msg. length())
        {
            return;
        }

        tcpSocket->disconnectFromHost();

        status=false;
    }
}

void TcpClient::slotConnected()
{
    sendBtn->setEnabled(true);
    enterBtn->setText(tr("离开"));

    int length=0;
    QString msg=userName+tr(":Enter Chat Room");
    if((length=tcpSocket->write(msg.toLatin1(),msg.length()))!=msg.length())
    {
        return;
    }
}

void TcpClient::slotSend()
{
    if(sendLineEdit->text()=="")
    {
        return ;
    }

    QString msg=userName+":"+sendLineEdit->text();

    tcpSocket->write(msg.toLatin1(),msg.length());
    sendLineEdit->clear();
}

void TcpClient::slotDisconnected()
{
    sendBtn->setEnabled(false);
    enterBtn->setText(tr("进入聊天室"));
}

void TcpClient::dataReceived()
{
    while(tcpSocket->bytesAvailable()>0)
    {
        QByteArray datagram;
        datagram.resize(tcpSocket->bytesAvailable());

        tcpSocket->read(datagram.data(),datagram.size());

        QString msg=datagram.data();
        contentListWidget->addItem(msg.left(datagram.size()));
    }
}
  • main.cpp
#include "tcpclient.h"
#include 

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

    return a.exec();
}

( c )调试代码
运行后,chat_test项目同目录下生成build-TcpClient-Desktop-Debug文件夹:
【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第68张图片
进入目录,点击运行TcpClient可执行文件:
【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第69张图片
【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第70张图片
(3.2.2)server端与client端交互式聊天测试

运行server端(chat_test可执行文件),创建聊天室1234
运行client端(tcpclient可执行文件),输入:

  1. 用户名
  2. 聊天室服务器地址:127.0.0.1 //本机测试
  3. 端口号(相同端口号即可聊天,如下图示:)
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第71张图片
    【嵌入式】Windows10&树莓派3b+安装Qt-5教程_第72张图片

大功告成!

你可能感兴趣的:(嵌入式,嵌入式开发学习)