[Qt]GTK例程

1.新建qt空项目
2.———————*.pro———————–
INCLUDEPATH += /usr/include/gtk-3.0 /usr/include/at-spi2-atk/2.0 /usr/include/at-spi-2.0 /usr/include/dbus-1.0 /usr/lib/x86_64-linux-gnu/dbus-1.0/include /usr/include/gtk-3.0 /usr/include/gio-unix-2.0 /usr/include/cairo /usr/include/pango-1.0 /usr/include/harfbuzz /usr/include/pango-1.0 /usr/include/fribidi /usr/include/harfbuzz /usr/include/atk-1.0 /usr/include/cairo /usr/include/pixman-1 /usr/include/uuid /usr/include/freetype2 /usr/include/gdk-pixbuf-2.0 /usr/include/libpng16 /usr/include/x86_64-linux-gnu /usr/include/libmount /usr/include/blkid /usr/include/glib-2.0 /usr/lib/x86_64-linux-gnu/glib-2.0/include

LIBS += -pthread -pthread -lgtk-3 -lgdk-3 -lpangocairo-1.0 -lpango-1.0 -lharfbuzz -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0
SOURCES += \
main.cpp

3.————————–main.cpp——————–
#include
#include
#include
#include
#include #include
#include

// 全局变量
static gboolean server_running = FALSE;
static GList *client_threads = NULL; // 保存客户端线程信息

// 服务器结构体
typedef struct {
int server_socket;
GtkListStore *client_list; // 修改为 GtkListStore* 类型
} ServerData;

// 客户端信息结构体
typedef struct {
int socket;
pthread_t thread;
int cpu;
} ClientInfo;

// 更新UI列表显示
static gboolean update_client_list(GtkWidget *list, gpointer data) {
gtk_list_store_clear(GTK_LIST_STORE(data));
GList *node;
for (node = client_threads; node; node = node->next) {
ClientInfo *info = (ClientInfo *)node->data;
char buffer[256];
snprintf(buffer, sizeof(buffer), “Client %d on CPU %d”, info->socket, info->cpu);
GtkListStore *store = GTK_LIST_STORE(data);
GtkTreeIter iter;
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter, 0, buffer, -1);
}
return FALSE;
}

// 客户端处理线程函数
void *client_handler(void *arg) {
ClientInfo *client_info = (ClientInfo *)arg;
int client_socket = client_info->socket;

// 获取线程运行在哪个CPU
cpu_set_t cpuset;
pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
for (int cpu = 0; cpu < CPU_SETSIZE; cpu++) { if (CPU_ISSET(cpu, &cpuset)) { client_info->cpu = cpu;
break;
}
}

char buffer[256];
while (1) {
ssize_t len = recv(client_socket, buffer, sizeof(buffer) – 1, 0);
if (len <= 0) { break; } buffer[len] = '\0'; g_print("Received from client %d: %s\n", client_socket, buffer); // 回显消息 send(client_socket, buffer, len, 0); } close(client_socket); client_threads = g_list_remove(client_threads, client_info); g_idle_add((GSourceFunc)update_client_list, gtk_tree_view_get_model(GTK_TREE_VIEW(arg))); free(client_info); return NULL; } // 服务器监听线程函数 void *server_thread(void *arg) { ServerData *server_data = (ServerData *)arg; int server_socket = server_data->server_socket;

while (server_running) {
struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);
int client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &addr_len);
if (client_socket < 0) { break; } ClientInfo *client_info = g_new0(ClientInfo, 1); client_info->socket = client_socket;

pthread_create(&client_info->thread, NULL, client_handler, client_info);
client_threads = g_list_append(client_threads, client_info);

g_idle_add((GSourceFunc)update_client_list, server_data->client_list);
}
return NULL;
}

// 启动服务器
static void start_server(GtkButton *button, ServerData *data) {
if (server_running) {
return;
}
server_running = TRUE;

struct sockaddr_in server_addr;
data->server_socket = socket(AF_INET, SOCK_STREAM, 0);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(12345);

bind(data->server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr));
listen(data->server_socket, 5);

pthread_t server_tid;
pthread_create(&server_tid, NULL, server_thread, data);
gtk_button_set_label(button, “Stop Server”);
}

// 停止服务器
static void stop_server(GtkButton *button, ServerData *data) {
if (!server_running) {
return;
}
server_running = FALSE;
close(data->server_socket);
gtk_button_set_label(button, “Start Server”);
}
int main(int argc, char *argv[]) {
gtk_init(&argc, &argv);

GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), “GTK TCP Server”);
gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
g_signal_connect(window, “destroy”, G_CALLBACK(gtk_main_quit), NULL);

GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
gtk_container_add(GTK_CONTAINER(window), vbox);

GtkWidget *button = gtk_button_new_with_label(“Start Server”);
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);

GtkWidget *scrolled_win = gtk_scrolled_window_new(NULL, NULL);
gtk_box_pack_start(GTK_BOX(vbox), scrolled_win, TRUE, TRUE, 0);

// 创建 GtkListStore 用于存储客户端列表
GtkListStore *list_store = gtk_list_store_new(1, G_TYPE_STRING);

// 创建 GtkTreeView,并将 GtkListStore 设为其数据模型
GtkWidget *tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store));
gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(tree_view), -1, “Clients”, gtk_cell_renderer_text_new(), “text”, 0, NULL);

// 将 GtkTreeView 添加到滚动窗口
gtk_container_add(GTK_CONTAINER(scrolled_win), tree_view);

// 将 GtkListStore 传递给 ServerData
ServerData server_data = {0, list_store}; // 正确的类型传递
g_signal_connect(button, “clicked”, G_CALLBACK(start_server), &server_data);

gtk_widget_show_all(window);
gtk_main();

return 0;
}

[Qt] 使用qt编写简单的GTK对话框程序

(1)kit套件里的sysroot写/home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot
(2)编译链gcc 和g++选自己生成的编译链

1.新建qt空工程,在pro文件中添加

TEMPLATE = app
CONFIG += console c++11
CONFIG -= qt

# 交叉编译工具链配置
# 请根据你的交叉编译工具链调整这些设置
QMAKE_CC = /home/yue/buildroot/buildroot-2022.05/output/host/bin/aarch64-buildroot-linux-gnu-gcc

QMAKE_CXX = /home/yue/buildroot/buildroot-2022.05/output/host/bin/aarch64-buildroot-linux-gnu-g++
QMAKE_LINK = /home/yue/buildroot/buildroot-2022.05/output/host/bin/aarch64-buildroot-linux-gnu-g++
QMAKE_AR = /home/yue/buildroot/buildroot-2022.05/output/host/bin/aarch64-buildroot-linux-gnu-ar
QMAKE_OBJCOPY = /home/yue/buildroot/buildroot-2022.05/output/host/bin/aarch64-buildroot-linux-gnu-objcopy
QMAKE_STRIP = /home/yue/buildroot/buildroot-2022.05/output/host/bin/aarch64-buildroot-linux-gnu-strip

# GTK 配置
PKGCONFIG = /home/yue/buildroot/buildroot-2022.05/output/host/bin/pkg-config
PKGCONFIG_PATH =/home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib/pkgconfig
PKG_CONFIG_PATH =/home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib/pkgconfig
PKGCONFIG += gdk-pixbuf-2.0
PKGCONFIG += gtk+-3.0
PKGCONFIG += glib-2.0
PKGCONFIG += pango
PKGCONFIG += harfbuzz
PKGCONFIG += cairo
PKGCONFIG += atk
PKGCONFIG += gobject-2.0

QMAKE_LFLAGS = -L /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/lib64

# 头文件和库路径(请根据实际路径调整)
INCLUDEPATH += /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/include/gtk-3.0
INCLUDEPATH += /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/include/glib-2.0
INCLUDEPATH += /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib/glib-2.0/include
INCLUDEPATH += /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/include/pango-1.0
INCLUDEPATH += /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/include/harfbuzz
INCLUDEPATH += /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/include/cairo
INCLUDEPATH += /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/include/gdk-pixbuf-2.0
INCLUDEPATH += /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/include/atk-1.0

#在如下目录中,l代表lib缩写?
LIBS += -L /home/yue/buildroot/buildroot-2022.05/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib \
-lgtk-3 \
-lglib-2.0 \
-lpango-1.0 \
-lharfbuzz \
-lcairo \
-latk-1.0 \
-lgdk_pixbuf-2.0 \
-lgobject-2.0

# 源文件
SOURCES += main.cpp

# 输出文件
TARGET = gtk_example

2.新建cpp文件 main.cpp
#include

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

GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), “GTK Example with Qt Creator”);
gtk_window_set_default_size(GTK_WINDOW(window), 400, 200);

g_signal_connect(window, “destroy”, G_CALLBACK(gtk_main_quit), NULL);

gtk_widget_show_all(window);

gtk_main();

return 0;
}

[Qt]TcpServer 可接收多个客户端连接,每个新连接创建一个线程

———————-*.pro—————————————-
QT += network

——————–mainwindow.h———————————-
#pragma once

#include
#include “TcpServer.h”
#include

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow {
Q_OBJECT

public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

private slots:
void onStartButtonClicked();
void onStopButtonClicked();
void onSendToSelectedButtonClicked();
void onBroadcastButtonClicked();
void onClientConnected(const QString &clientInfo);
void onClientDisconnected(const QString &clientInfo);
void onClientRcvData(const QByteArray &data);
private:
Ui::MainWindow *ui;
TcpServer *server;
};
————————–TcpServer.h———————————–
#pragma once

#include
#include
#include
#include
#include

class TcpServer : public QTcpServer {
Q_OBJECT
public:
explicit TcpServer(QObject *parent = nullptr);

void startServer();
void stopServer();
void sendToClient(qintptr socketDescriptor, const QString &message);
void broadcastMessage(const QString &message);

signals:
void clientConnected(const QString &clientInfo);
void clientDisconnected(const QString &clientInfo);
void clientRcvData(const QByteArray &data);

protected:
void incomingConnection(qintptr socketDescriptor) override;

private:
QMap clientThreads;
QMap clients;
};
——————————main.cpp—————————————
#include “mainwindow.h”

#include

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

————————mainwindow.cpp————————————-

#include “mainwindow.h”
#include “ui_mainwindow.h”
#include

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

connect(ui->startButton, &QPushButton::clicked, this, &MainWindow::onStartButtonClicked);
connect(ui->stopButton, &QPushButton::clicked, this, &MainWindow::onStopButtonClicked);
connect(ui->sendToSelectedButton, &QPushButton::clicked, this, &MainWindow::onSendToSelectedButtonClicked);
connect(ui->broadcastButton, &QPushButton::clicked, this, &MainWindow::onBroadcastButtonClicked);

connect(server, &TcpServer::clientConnected, this, &MainWindow::onClientConnected);
connect(server, &TcpServer::clientDisconnected, this, &MainWindow::onClientDisconnected);
connect(server, &TcpServer::clientRcvData, this, &MainWindow::onClientRcvData);

}

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

void MainWindow::onStartButtonClicked() {
server->startServer();
}

void MainWindow::onStopButtonClicked() {
server->stopServer();
}

void MainWindow::onSendToSelectedButtonClicked()
{
QListWidgetItem *selectedItem = ui->clientListWidget->currentItem();
if (selectedItem)
{
qDebug()<text();
qintptr socketDescriptor = selectedItem->text().toInt();
server->sendToClient(socketDescriptor, ui->messageInput->toPlainText());
}
}

void MainWindow::onBroadcastButtonClicked() {
server->broadcastMessage(ui->messageInput->toPlainText());
}

void MainWindow::onClientConnected(const QString &clientInfo) {
ui->clientListWidget->addItem(clientInfo);
}

void MainWindow::onClientDisconnected(const QString &clientInfo) {
QList items = ui->clientListWidget->findItems(clientInfo, Qt::MatchExactly);
for (QListWidgetItem *item : items) {
delete ui->clientListWidget->takeItem(ui->clientListWidget->row(item));
}
}

void MainWindow::onClientRcvData(const QByteArray &data)
{
ui->textEdit->setText(“111”);
}

———————————TcpServer.cpp——————————–
#include “TcpServer.h”
#include
#include // For sched_getcpu()

TcpServer::TcpServer(QObject *parent) : QTcpServer(parent) {}

void TcpServer::startServer() {
if (!listen(QHostAddress::Any, 12345)) {
qCritical() << "Server could not start!"; } else { qDebug() << "Server started on port 12345"; } } void TcpServer::stopServer() { close(); qDeleteAll(clients); qDeleteAll(clientThreads); } void TcpServer::incomingConnection(qintptr socketDescriptor) { QThread *clientThread = new QThread; QTcpSocket *clientSocket = new QTcpSocket; clientSocket->setSocketDescriptor(socketDescriptor);
clientSocket->moveToThread(clientThread);

connect(clientThread, &QThread::started, [this,clientSocket,clientThread]()
{
connect(clientSocket, &QTcpSocket::readyRead, [this,clientSocket,clientThread]()
{
QString clientIpAddress = clientSocket->peerAddress().toString();
qDebug() << "Client connected from IP address:" << clientIpAddress; QByteArray data = clientSocket->readAll();
// Handle data
qDebug()<<"Handle data"; int cpu_id = sched_getcpu(); // 获取当前线程运行的 CPU 核编号 qDebug() << "Thread is running on CPU core:" << cpu_id; emit clientRcvData(data); }); connect(clientSocket, &QTcpSocket::disconnected, clientSocket, &QTcpSocket::deleteLater); }); connect(clientSocket, &QTcpSocket::disconnected, [this, socketDescriptor]() { clientThreads.remove(socketDescriptor); clients.remove(socketDescriptor); emit clientDisconnected(QString::number(socketDescriptor)); }); connect(clientThread, &QThread::finished, clientThread, &QThread::deleteLater); clientThreads.insert(socketDescriptor, clientThread); clients.insert(socketDescriptor, clientSocket); clientThread->start();
emit clientConnected(QString::number(socketDescriptor));
}

void TcpServer::sendToClient(qintptr socketDescriptor, const QString &message)
{
if (clients.contains(socketDescriptor))
{
clients[socketDescriptor]->write(message.toUtf8());
}
}

void TcpServer::broadcastMessage(const QString &message)
{
for (QTcpSocket *clientSocket : clients.values())
{
clientSocket->write(message.toUtf8());
}
}

——————————–*.ui——————————————————-

broadcastButton – QPushButton
sendToSelectedButton
startButton
stopButton

clientListWidget – QListWidget

messageInput – QTextEdit
textEdit

[Qt]获取当前线程运行在哪个核

#include
#include
#include // For sched_getcpu()

class MyThread : public QThread {
Q_OBJECT

protected:
void run() override {
int cpu_id = sched_getcpu(); // 获取当前线程运行的 CPU 核编号
qDebug() << "Thread is running on CPU core:" << cpu_id; // 线程的其他逻辑... } };

[Qt][Orangepi]opencv将文本转换为图片并旋转

——————–*.pro—————————–
添加
INCLUDEPATH += /home/yue/openCV/install-arm/include\
/home/yue/openCV/install-arm/include/opencv4 \
/home/yue/openCV/install-arm/include/opencv2

LIBS += /home/yue/openCV/install-arm/lib/libopencv_highgui.so \
/home/yue/openCV/install-arm/lib/libopencv_core.so \
/home/yue/openCV/install-arm/lib/libopencv_imgproc.so \
/home/yue/openCV/install-arm/lib/libopencv_imgcodecs.so

———————mainwindow.h————————-
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include

#include

#include
#include

#include
#include
#include

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

private:
Ui::MainWindow *ui;

private:
QImage cvMatToQImage(const cv::Mat& mat);
};
#endif // MAINWINDOW_H
——————-main.cpp————————————-
#include “mainwindow.h”

#include

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

—————————–mainwindow.h———————-
#include “mainwindow.h”
#include “ui_mainwindow.h”

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

cv::Mat image = cv::Mat::zeros(300, 600, CV_8UC3);

// 设置文本内容、字体、大小、颜色和厚度
std::string text = “Rotated Text”;
int fontFace = cv::FONT_HERSHEY_SIMPLEX;
double fontScale = 1.0;
int thickness = 2;
cv::Scalar color(255, 255, 255); // 白色

// 获取文本大小
int baseline = 0;
cv::Size textSize = cv::getTextSize(text, fontFace, fontScale, thickness, &baseline);

// 计算文本位置(中心对齐)
cv::Point textOrg((image.cols – textSize.width) / 2,
(image.rows + textSize.height) / 2);

// 创建旋转矩阵
double angle = 45; // 旋转角度
cv::Mat rotMat = cv::getRotationMatrix2D(textOrg, angle, 1.0);

// 绘制旋转文本
cv::putText(image, text, textOrg, fontFace, fontScale, color, thickness, cv::LINE_AA);

// 应用旋转变换
cv::warpAffine(image, image, rotMat, image.size());

// 将OpenCV图像转换为QImage
QImage qImage = cvMatToQImage(image);

// 在Qt中显示图像
ui->label->setPixmap(QPixmap::fromImage(qImage));
ui->label->show();

}

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

QImage MainWindow:: cvMatToQImage(const cv::Mat& mat)
{
if (mat.channels() == 3) {
// Convert the image to RGB
cv::Mat rgb;
cv::cvtColor(mat, rgb, cv::COLOR_BGR2RGB);
return QImage((const unsigned char*)(rgb.data),
rgb.cols, rgb.rows,
QImage::Format_RGB888);
} else {
return QImage((const unsigned char*)(mat.data),
mat.cols, mat.rows,
QImage::Format_Grayscale8);
}
}

[Qt][Orangepi]香橙派下运行qt虚拟键盘

1.缺少so文件
找到linux主机下的文件,一般在使用qt源码编译下
/opt/atk-dlrk356x-toolchain/aarch64-buildroot-linux-gnu/sysroot/opt/qt-5.15.2/lib/libQt5VirtualKeyboard.so.5
拷贝到开发板/root/lib下

2.缺什么补什么,在开发板上安装
sudo apt-get install qml-module-qtquick-controls
sudo apt-get install qml-module-qtquick-controls qml-module-qtquick-controls2 qml-module-qtquick-xmllistmodel
sudo apt-get install qml-module-qt-labs-folderlistmodel

[Qt]串口发送接收

———————mainwindow.h————————————————-
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include
#include
#include “SerialPortWorker.h”

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow {
Q_OBJECT

public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

private slots:
void onSendButtonClicked();
void onDataReceived(const QByteArray &data);
void onErrorOccurred(const QString &error);

private:
Ui::MainWindow *ui;
QThread *workerThread;
SerialPortWorker *worker;
};

#endif // MAINWINDOW_H

————————————-SerialPortWorker.h——————————
#ifndef SERIALPORTWORKER_H
#define SERIALPORTWORKER_H

#include
#include
#include

class SerialPortWorker : public QObject {
Q_OBJECT

public:
explicit SerialPortWorker(const QString &portName, QObject *parent = nullptr);
~SerialPortWorker();

public slots:
void startWork();
void sendData(const QByteArray &data);

signals:
void dataReceived(const QByteArray &data);
void errorOccurred(const QString &error);

private slots:
void handleReadyRead();

private:
QSerialPort *serialPort;
QString portName;
};

#endif // SERIALPORTWORKER_H

—————————————main.cpp————————–
#include “mainwindow.h”

#include

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

——————————-mainwindow.cpp—————————-

#include “mainwindow.h”
#include “ui_mainwindow.h”
#include
#include

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow), workerThread(new QThread), worker(nullptr)
{
ui->setupUi(this);

worker = new SerialPortWorker(“/dev/ttyUSB0”); // 使用实际串口名称
worker->moveToThread(workerThread);

connect(workerThread, &QThread::started, worker, &SerialPortWorker::startWork);
connect(worker, &SerialPortWorker::dataReceived, this, &MainWindow::onDataReceived);
connect(worker, &SerialPortWorker::errorOccurred, this, &MainWindow::onErrorOccurred);
connect(ui->sendButton, &QPushButton::clicked, this, &MainWindow::onSendButtonClicked);

workerThread->start();
}

MainWindow::~MainWindow() {
workerThread->quit();
workerThread->wait();
delete ui;
}

void MainWindow::onSendButtonClicked() {
QByteArray data = ui->dataInput->text().toUtf8();
worker->sendData(data);
}

void MainWindow::onDataReceived(const QByteArray &data) {
ui->dataOutput->append(data);
}

void MainWindow::onErrorOccurred(const QString &error) {
qDebug() << "Error:" << error; } ---------------------------------SerialPortWorker.cpp--------------------------------- #include "SerialPortWorker.h" #include

SerialPortWorker::SerialPortWorker(const QString &portName, QObject *parent)
: QObject(parent), portName(portName), serialPort(nullptr) {}

SerialPortWorker::~SerialPortWorker() {
if (serialPort && serialPort->isOpen()) {
serialPort->close();
delete serialPort;
}
}

void SerialPortWorker::startWork() {
serialPort = new QSerialPort(); // 在当前线程中创建 QSerialPort
serialPort->setPortName(portName);
serialPort->setBaudRate(QSerialPort::Baud9600);
serialPort->setDataBits(QSerialPort::Data8);
serialPort->setParity(QSerialPort::NoParity);
serialPort->setStopBits(QSerialPort::OneStop);
serialPort->setFlowControl(QSerialPort::NoFlowControl);

if (!serialPort->open(QIODevice::ReadWrite)) {
emit errorOccurred(serialPort->errorString());
return;
}

connect(serialPort, &QSerialPort::readyRead, this, &SerialPortWorker::handleReadyRead);
}

void SerialPortWorker::sendData(const QByteArray &data) {
if (serialPort && serialPort->isOpen()) {
serialPort->write(data);
}
}

void SerialPortWorker::handleReadyRead() {
QByteArray data = serialPort->readAll();
emit dataReceived(data);
}

[Qt]拖拽图片,限制在子窗口内

————————————mainwindow.h————————————
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include

#include
#include
#include
#include

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

private:
Ui::MainWindow *ui;
};

class DraggableLabel : public QLabel
{
Q_OBJECT

public:
explicit DraggableLabel(QWidget *parent = nullptr) : QLabel(parent), isDragging(false) {}

protected:
void mousePressEvent(QMouseEvent *event) override
{
if (event->button() == Qt::LeftButton) {
isDragging = true;
dragStartPosition = event->pos();
}
}

void mouseMoveEvent(QMouseEvent *event) override
{
if (isDragging) {
int dx = event->pos().x() – dragStartPosition.x();
int dy = event->pos().y() – dragStartPosition.y();

// 获取父窗口尺寸
QWidget *parentWidget = this->parentWidget();

// 计算新位置,确保不会超出父窗口边界
int newX = qMax(0, qMin(this->pos().x() + dx, parentWidget->width() – this->width()));
int newY = qMax(0, qMin(this->pos().y() + dy, parentWidget->height() – this->height()));

// 移动到新的位置
move(newX, newY);
}
}

void mouseReleaseEvent(QMouseEvent *event) override
{
if (event->button() == Qt::LeftButton) {
isDragging = false;
}
}

private:
bool isDragging;
QPoint dragStartPosition;
};

#endif // MAINWINDOW_H

————————————mainwindow.cpp——————————————————-
#include “mainwindow.h”
#include “ui_mainwindow.h”

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

QWidget *subWindow = new QWidget(this);
subWindow->setGeometry(50, 50, 1500, 800); // 设置子窗口的位置和大小
subWindow->setStyleSheet(“background-color: lightgray;”); // 设置子窗口背景色

// 创建并设置图片
QPixmap pixmap(“/home/yue/11111.jpg”);
DraggableLabel *label = new DraggableLabel(subWindow);
label->setPixmap(pixmap);
label->setGeometry(10, 10, pixmap.width(), pixmap.height()); // 设置初始位置和大小

}

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

[Qt]拖拽图片

————————mainwindow.h————————-
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include
#include
#include
#include

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

private:
Ui::MainWindow *ui;
};

class DraggableLabel : public QLabel
{
Q_OBJECT

public:
explicit DraggableLabel(QWidget *parent = nullptr) : QLabel(parent), isDragging(false) {}

protected:
void mousePressEvent(QMouseEvent *event) override
{
if (event->button() == Qt::LeftButton) {
isDragging = true;
dragStartPosition = event->pos();
}
}

void mouseMoveEvent(QMouseEvent *event) override
{
if (isDragging) {
int dx = event->pos().x() – dragStartPosition.x();
int dy = event->pos().y() – dragStartPosition.y();
move(pos().x() + dx, pos().y() + dy);
}
}

void mouseReleaseEvent(QMouseEvent *event) override
{
if (event->button() == Qt::LeftButton) {
isDragging = false;
}
}

private:
bool isDragging;
QPoint dragStartPosition;
};

#endif // MAINWINDOW_H

——————————mainwindow.cpp————————————-
#include “mainwindow.h”
#include “ui_mainwindow.h”

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

QPixmap pixmap(“/home/orangepi/11111.jpg”);
/*
ui->label->setPixmap(pixmap);

ui->label->setGeometry(50, 50, pixmap.width(), pixmap.height());

ui->label->setObjectName(“draggableLabel”);
*/

DraggableLabel *label2 = new DraggableLabel(this);

label2->setPixmap(pixmap);

label2->setGeometry(50, 50, pixmap.width(), pixmap.height());

}

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

[Qt]创建线程

——–mainwindow.h———————–
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include

#include
#include
#include
#include
#include

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class Work1 ;
class Work2 ;

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

private:
Ui::MainWindow *ui;

private:
Work1 *worker1;
Work2 *worker2;

QThread workerThread1;
QThread workerThread2;
};

class Work1:public QObject
{
Q_OBJECT
bool isCanRun;
public slots:
void doWork1(void)
{
isCanRun = true;
while (1)
{
if (!isCanRun)
{
break;
}
QThread::sleep(2);
qDebug() << "Work1"; } } signals: void resultemit1(); public : void stopWork() { qDebug()<< "break thread"<setupUi(this);

worker1 = new Work1;
worker2 = new Work2;

worker1->moveToThread(&workerThread1);
worker2->moveToThread(&workerThread2);

QObject::connect(&workerThread1, &QThread::started, worker1, &Work1::doWork1);
QObject::connect(&workerThread2, &QThread::started, worker2, &Work2::doWork2);

workerThread1.start();
workerThread2.start();

connect(&workerThread1, SIGNAL(finished()),worker1, SLOT(deleteLater()));
connect(&workerThread1, SIGNAL(finished()),&workerThread1, SLOT(deleteLater()));

connect(&workerThread2, SIGNAL(finished()),worker2, SLOT(deleteLater()));
connect(&workerThread2, SIGNAL(finished()),&workerThread2, SLOT(deleteLater()));
}

MainWindow::~MainWindow()
{
delete ui;

worker1->stopWork();
worker2->stopWork();
workerThread1.quit();
workerThread2.quit();

if (workerThread1.wait(5000)) {
qDebug()<<"thread end"<