第七章:Qt 实践
在深入了解 Qt 框架的各个模块之后,本章将通过几个实际案例,展示如何将 Qt 的强大功能应用于真实项目开发中。我们将结合界面设计、信号与槽机制、网络通信和数据处理等内容,探索 Qt 在桌面应用程序开发中的实际应用。
7.1 案例一:简单的文本编辑器
7.1.1 项目目标
构建一个支持文本编辑、保存和打开文件的简易文本编辑器,学习 QMainWindow
、菜单栏和文件操作的使用。
7.1.2 主要功能
- 打开文件: 通过文件对话框选择文件并加载内容。
- 保存文件: 将编辑内容写入到文件。
- 编辑功能: 提供基本的文本编辑功能。
7.1.3 核心代码
cpp
#include <QApplication>
#include <QMainWindow>
#include <QTextEdit>
#include <QMenuBar>
#include <QFileDialog>
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
class TextEditor : public QMainWindow {
Q_OBJECT
private:
QTextEdit *editor;
public:
TextEditor() {
editor = new QTextEdit(this);
setCentralWidget(editor);
QMenu *fileMenu = menuBar()->addMenu("File");
QAction *openAction = fileMenu->addAction("Open");
QAction *saveAction = fileMenu->addAction("Save");
QAction *exitAction = fileMenu->addAction("Exit");
connect(openAction, &QAction::triggered, this, &TextEditor::openFile);
connect(saveAction, &QAction::triggered, this, &TextEditor::saveFile);
connect(exitAction, &QAction::triggered, this, &QMainWindow::close);
}
private slots:
void openFile() {
QString fileName = QFileDialog::getOpenFileName(this, "Open File");
if (fileName.isEmpty()) return;
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QMessageBox::warning(this, "Error", "Could not open file");
return;
}
QTextStream in(&file);
editor->setText(in.readAll());
file.close();
}
void saveFile() {
QString fileName = QFileDialog::getSaveFileName(this, "Save File");
if (fileName.isEmpty()) return;
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QMessageBox::warning(this, "Error", "Could not save file");
return;
}
QTextStream out(&file);
out << editor->toPlainText();
file.close();
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
TextEditor editor;
editor.setWindowTitle("Simple Text Editor");
editor.resize(800, 600);
editor.show();
return app.exec();
}
7.1.4 功能亮点
- 使用
QTextEdit
提供文本编辑功能。 - 文件打开和保存通过
QFileDialog
和QFile
实现。 - 菜单栏通过
QMenuBar
和QAction
构建。
7.2 案例二:网络聊天应用
7.2.1 项目目标
构建一个局域网内实时聊天应用,学习使用 QTcpServer
和 QTcpSocket
进行通信。
7.2.2 主要功能
- 服务器端: 接收并转发客户端消息。
- 客户端: 连接服务器并发送消息。
7.2.3 核心代码
服务器端
cpp
#include <QApplication>
#include <QTcpServer>
#include <QTcpSocket>
#include <QDebug>
class ChatServer : public QTcpServer {
Q_OBJECT
private:
QList<QTcpSocket *> clients;
protected:
void incomingConnection(qintptr socketDescriptor) override {
QTcpSocket *client = new QTcpSocket(this);
client->setSocketDescriptor(socketDescriptor);
clients << client;
connect(client, &QTcpSocket::readyRead, [=]() {
QByteArray data = client->readAll();
for (QTcpSocket *other : clients) {
if (other != client) other->write(data);
}
});
connect(client, &QTcpSocket::disconnected, [=]() {
clients.removeAll(client);
client->deleteLater();
});
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
ChatServer server;
if (server.listen(QHostAddress::Any, 12345)) {
qDebug() << "Server is running on port 12345";
} else {
qDebug() << "Server failed to start";
}
return app.exec();
}
客户端
cpp
#include <QApplication>
#include <QTcpSocket>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QTextBrowser>
#include <QPushButton>
class ChatClient : public QWidget {
Q_OBJECT
private:
QTcpSocket *socket;
QTextBrowser *chatDisplay;
QLineEdit *messageInput;
public:
ChatClient() {
socket = new QTcpSocket(this);
chatDisplay = new QTextBrowser(this);
messageInput = new QLineEdit(this);
QPushButton *sendButton = new QPushButton("Send", this);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(chatDisplay);
layout->addWidget(messageInput);
layout->addWidget(sendButton);
connect(sendButton, &QPushButton::clicked, this, &ChatClient::sendMessage);
connect(socket, &QTcpSocket::readyRead, this, &ChatClient::receiveMessage);
socket->connectToHost("127.0.0.1", 12345);
}
private slots:
void sendMessage() {
QString message = messageInput->text();
if (!message.isEmpty()) {
socket->write(message.toUtf8());
messageInput->clear();
}
}
void receiveMessage() {
QByteArray data = socket->readAll();
chatDisplay->append(QString::fromUtf8(data));
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
ChatClient client;
client.setWindowTitle("Chat Client");
client.resize(400, 300);
client.show();
return app.exec();
}
7.2.4 功能亮点
- 服务器端管理多个客户端连接,支持消息广播。
- 客户端实现简单的聊天界面,通过信号槽实现消息收发。
7.3 案例三:图片浏览器
7.3.1 项目目标
开发一个简单的图片浏览器,支持加载本地图片文件并显示,学习 QGraphicsView
的使用。
7.3.2 核心代码
cpp
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <QFileDialog>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
class ImageViewer : public QWidget {
Q_OBJECT
private:
QGraphicsView *view;
QGraphicsScene *scene;
public:
ImageViewer() {
view = new QGraphicsView(this);
scene = new QGraphicsScene(this);
view->setScene(scene);
QPushButton *loadButton = new QPushButton("Load Image", this);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(view);
layout->addWidget(loadButton);
connect(loadButton, &QPushButton::clicked, this, &ImageViewer::loadImage);
}
private slots:
void loadImage() {
QString fileName = QFileDialog::getOpenFileName(this, "Open Image", "", "Images (*.png *.jpg *.bmp)");
if (!fileName.isEmpty()) {
scene->clear();
QPixmap pixmap(fileName);
scene->addPixmap(pixmap);
view->fitInView(scene->itemsBoundingRect(), Qt::KeepAspectRatio);
}
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
ImageViewer viewer;
viewer.setWindowTitle("Image Viewer");
viewer.resize(800, 600);
viewer.show();
return app.exec();
}
7.3.3 功能亮点
- 使用
QGraphicsView
和QGraphicsScene
显示图片。 - 提供简单的文件加载功能。
7.4 小结
本章通过多个案例展示了 Qt 在实际开发中的应用,包括文本编辑器、网络聊天应用和图片浏览器。这些项目涵盖了 Qt 的多个模块和技术,帮助开发者将理论知识转化为实践能力。