新增大窗口播放视频按键,窗口大小根据解码视频分辨率自动调整,关掉大窗口回到原来位置播放视频
This commit is contained in:
parent
4bd2d7eab5
commit
9a49eab4af
|
@ -4,6 +4,7 @@
|
||||||
FFmpegDecoder::FFmpegDecoder(QObject* parent) :
|
FFmpegDecoder::FFmpegDecoder(QObject* parent) :
|
||||||
QThread(parent),
|
QThread(parent),
|
||||||
videoLabel(nullptr),
|
videoLabel(nullptr),
|
||||||
|
resolutionEdit(nullptr),
|
||||||
abort(false),
|
abort(false),
|
||||||
restart(false),
|
restart(false),
|
||||||
formatContext(nullptr),
|
formatContext(nullptr),
|
||||||
|
@ -33,32 +34,49 @@ FFmpegDecoder::~FFmpegDecoder()
|
||||||
|
|
||||||
void FFmpegDecoder::processVideo(int itemIndex)
|
void FFmpegDecoder::processVideo(int itemIndex)
|
||||||
{
|
{
|
||||||
#if 1
|
QLabel* originalLabel = this->videoLabel;
|
||||||
int width = 720;
|
if ((FocusWindowWidth != 0) && (FocusWindowHeight != 0)) {
|
||||||
int height = 1280;
|
qDebug() << "------ processVideo";
|
||||||
#elif 1
|
FocusWindowDialog* dialog = nullptr;
|
||||||
int width = 640;
|
if (FocusWindowWidth * 16 == FocusWindowHeight * 9) {
|
||||||
int height = 480;
|
dialog = new FocusWindowDialog(nullptr, QSize(540, 960));
|
||||||
|
}
|
||||||
|
else if (FocusWindowWidth * 9 == FocusWindowHeight * 16) {
|
||||||
|
dialog = new FocusWindowDialog(nullptr, QSize(960, 540));
|
||||||
|
}
|
||||||
|
else if (FocusWindowWidth * 4 == FocusWindowHeight * 3) {
|
||||||
|
dialog = new FocusWindowDialog(nullptr, QSize(480, 640));
|
||||||
|
}
|
||||||
|
else if (FocusWindowWidth * 3 == FocusWindowHeight * 4) {
|
||||||
|
dialog = new FocusWindowDialog(nullptr, QSize(640, 480));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
qDebug() << "------ Other scaled resolutions use 480x640";
|
||||||
|
dialog = new FocusWindowDialog(nullptr, QSize(480, 640));
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
// 将视频显示的 QLabel 切换为对话框内的 videoDisplayLabel
|
||||||
|
this->videoLabel = dialog->videoDisplayLabel;
|
||||||
|
if ((dialog->exec() == QDialog::Accepted) || (dialog->exec() == QDialog::Rejected)) {
|
||||||
|
this->videoLabel = originalLabel;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
int width = 480;
|
mutex.lock();
|
||||||
int height = 640;
|
this->videoLabelTemp = dialog->videoDisplayLabel; // 更新临时标签
|
||||||
|
this->videoLabelChanged = true; // 设置标志位,表示标签已更改
|
||||||
|
mutex.unlock();
|
||||||
|
|
||||||
|
if ((dialog->exec() == QDialog::Accepted) || (dialog->exec() == QDialog::Rejected)) {
|
||||||
|
mutex.lock();
|
||||||
|
this->videoLabelTemp = originalLabel; // 还原回原始标签
|
||||||
|
this->videoLabelChanged = true; // 设置标志位
|
||||||
|
mutex.unlock();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
qDebug() << "------ processVideo";
|
delete dialog;
|
||||||
if (width * 16 == height * 9) {
|
|
||||||
FocusWindowDialog* dialog = new FocusWindowDialog(nullptr, QSize(540, 960));
|
|
||||||
dialog->exec();
|
|
||||||
}
|
}
|
||||||
else if (width * 9 == height * 16) {
|
else {
|
||||||
FocusWindowDialog* dialog = new FocusWindowDialog(nullptr, QSize(960, 540));
|
qDebug() << "------ Please wait for the video to be decoded and rendered before clicking";
|
||||||
dialog->exec();
|
|
||||||
}
|
|
||||||
else if (width * 4 == height * 3) {
|
|
||||||
FocusWindowDialog* dialog = new FocusWindowDialog(nullptr, QSize(480, 640));
|
|
||||||
dialog->exec();
|
|
||||||
}
|
|
||||||
else if (width * 3 == height * 4) {
|
|
||||||
FocusWindowDialog* dialog = new FocusWindowDialog(nullptr, QSize(640, 480));
|
|
||||||
dialog->exec();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +112,7 @@ void FFmpegDecoder::run()
|
||||||
{
|
{
|
||||||
QFile file(filePath);
|
QFile file(filePath);
|
||||||
qint64 fileSize = 0;
|
qint64 fileSize = 0;
|
||||||
|
QLabel* currentVideoLabel = videoLabel;
|
||||||
while (!isInterruptionRequested()) {
|
while (!isInterruptionRequested()) {
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
while (!restart && !abort) {
|
while (!restart && !abort) {
|
||||||
|
@ -105,7 +123,7 @@ void FFmpegDecoder::run()
|
||||||
qDebug() << "Decoder thread aborting";
|
qDebug() << "Decoder thread aborting";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
QLabel* currentVideoLabel = videoLabel;
|
/*QLabel* currentVideoLabel = videoLabel;*/
|
||||||
QSize labelSize = currentVideoLabel->size();
|
QSize labelSize = currentVideoLabel->size();
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
|
|
||||||
|
@ -153,9 +171,18 @@ void FFmpegDecoder::run()
|
||||||
qWarning() << "Error during decoding";
|
qWarning() << "Error during decoding";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
mutex.lock();
|
||||||
|
if (videoLabelChanged) {
|
||||||
|
currentVideoLabel = videoLabelTemp; // 更新 currentVideoLabel
|
||||||
|
videoLabelChanged = false; // 重置标志位
|
||||||
|
labelSize = currentVideoLabel->size();
|
||||||
|
}
|
||||||
|
mutex.unlock();
|
||||||
|
|
||||||
QImage img = avFrameToQImage(frame);
|
QImage img = avFrameToQImage(frame);
|
||||||
QImage scaledImage = img.scaled(labelSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
QImage scaledImage = img.scaled(labelSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||||
currentVideoLabel->setPixmap(QPixmap::fromImage(scaledImage));
|
//currentVideoLabel->setPixmap(QPixmap::fromImage(scaledImage));
|
||||||
|
QMetaObject::invokeMethod(currentVideoLabel, "setPixmap", Qt::QueuedConnection, Q_ARG(QPixmap, QPixmap::fromImage(scaledImage)));
|
||||||
QThread::msleep(10); // Simulate 25 FPS frame rate
|
QThread::msleep(10); // Simulate 25 FPS frame rate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,12 +293,18 @@ QImage FFmpegDecoder::avFrameToQImage(AVFrame* frame)
|
||||||
{
|
{
|
||||||
int width = frame->width;
|
int width = frame->width;
|
||||||
int height = frame->height;
|
int height = frame->height;
|
||||||
|
// 这里注意切换镜头后是否改变分辨率去改变 isGotResolution
|
||||||
|
if (!isGotResolution && (width != 0) && (height != 0)) {
|
||||||
|
isGotResolution = true;
|
||||||
|
FocusWindowWidth = width;
|
||||||
|
FocusWindowHeight = height;
|
||||||
|
}
|
||||||
QString resolutionText = QString::number(width) + " x " + QString::number(height);
|
QString resolutionText = QString::number(width) + " x " + QString::number(height);
|
||||||
resolutionEdit->setText(resolutionText);
|
//resolutionEdit->setText(resolutionText);
|
||||||
|
QMetaObject::invokeMethod(resolutionEdit, "setText", Qt::QueuedConnection, Q_ARG(QString, resolutionText));
|
||||||
//qDebug() << "H264 video resolution: Width =" << frame->width << ", Height =" << frame->height;
|
//qDebug() << "H264 video resolution: Width =" << frame->width << ", Height =" << frame->height;
|
||||||
|
|
||||||
AVPixelFormat pixFmt = (AVPixelFormat)frame->format;
|
AVPixelFormat pixFmt = (AVPixelFormat)frame->format;
|
||||||
|
|
||||||
if (!swsContext) {
|
if (!swsContext) {
|
||||||
swsContext = sws_getContext(width, height, pixFmt, width, height, AV_PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr);
|
swsContext = sws_getContext(width, height, pixFmt, width, height, AV_PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr);
|
||||||
if (!swsContext) {
|
if (!swsContext) {
|
||||||
|
|
|
@ -56,9 +56,12 @@ private:
|
||||||
QWaitCondition condition;
|
QWaitCondition condition;
|
||||||
QString filePath;
|
QString filePath;
|
||||||
QLabel* videoLabel;
|
QLabel* videoLabel;
|
||||||
QLineEdit* resolutionEdit;
|
QLabel* videoLabelTemp; // 临时存储新标签
|
||||||
|
QLineEdit* resolutionEdit;
|
||||||
|
bool videoLabelChanged = false;
|
||||||
bool abort;
|
bool abort;
|
||||||
bool restart;
|
bool restart;
|
||||||
|
bool isGotResolution = false;
|
||||||
|
|
||||||
AVFormatContext* formatContext;
|
AVFormatContext* formatContext;
|
||||||
AVCodecContext* codecContext;
|
AVCodecContext* codecContext;
|
||||||
|
@ -66,9 +69,10 @@ private:
|
||||||
AVPacket* packet;
|
AVPacket* packet;
|
||||||
SwsContext* swsContext;
|
SwsContext* swsContext;
|
||||||
int videoStreamIndex;
|
int videoStreamIndex;
|
||||||
|
int FocusWindowWidth = 0;
|
||||||
|
int FocusWindowHeight = 0;
|
||||||
|
|
||||||
RingBuffer* ringBuffer;
|
RingBuffer* ringBuffer;
|
||||||
//QLabel* singleFrameLabel; // 用于解码单帧的标签
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FFMPEGDECODER_H
|
#endif // FFMPEGDECODER_H
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// FocusWindow.h
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
@ -8,12 +9,13 @@ class FocusWindowDialog : public QDialog
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
QLabel* videoDisplayLabel;
|
||||||
FocusWindowDialog(QWidget* parent = nullptr, const QSize& labelSize = QSize(480, 640)) : QDialog(parent)
|
FocusWindowDialog(QWidget* parent = nullptr, const QSize& labelSize = QSize(480, 640)) : QDialog(parent)
|
||||||
{
|
{
|
||||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||||
QLabel* label = new QLabel("1111 This is a new window opened by clicking the new button.", this);
|
videoDisplayLabel = new QLabel(this);
|
||||||
label->setFixedSize(labelSize); // 设置QLabel的固定大小
|
videoDisplayLabel->setFixedSize(labelSize); // 设置QLabel的固定大小
|
||||||
layout->addWidget(label);
|
layout->addWidget(videoDisplayLabel);
|
||||||
|
|
||||||
QPushButton* closeButton = new QPushButton("Close", this);
|
QPushButton* closeButton = new QPushButton("Close", this);
|
||||||
layout->addWidget(closeButton);
|
layout->addWidget(closeButton);
|
||||||
|
|
|
@ -45,14 +45,10 @@ ClientHandler::ClientHandler(QJsonArray frontBoardOneClickTest, QJsonArray front
|
||||||
void ClientHandler::initialize(QTcpSocket* socket)
|
void ClientHandler::initialize(QTcpSocket* socket)
|
||||||
{
|
{
|
||||||
this->socket = socket;
|
this->socket = socket;
|
||||||
|
connect(socket, &QTcpSocket::readyRead, this, &ClientHandler::onDataReceived);
|
||||||
// 连接信号槽,将其放在同一线程中处理
|
|
||||||
connect(socket, &QTcpSocket::readyRead, this, &ClientHandler::onDataReceived);
|
|
||||||
connect(socket, &QTcpSocket::disconnected, this, &ClientHandler::onDisconnected);
|
connect(socket, &QTcpSocket::disconnected, this, &ClientHandler::onDisconnected);
|
||||||
|
|
||||||
// 其他的 socket 操作都将在这个线程中进行
|
// 其他的 socket 操作都将在这个线程中进行
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ClientHandler::~ClientHandler()
|
ClientHandler::~ClientHandler()
|
||||||
|
|
|
@ -118,6 +118,7 @@ signals:
|
||||||
void startReadTimer(int client_Id);
|
void startReadTimer(int client_Id);
|
||||||
void stopReadTimer(int client_Id);
|
void stopReadTimer(int client_Id);
|
||||||
void sendDataToSomeClient(int client_Id, const QByteArray& data);
|
void sendDataToSomeClient(int client_Id, const QByteArray& data);
|
||||||
|
void openFocusWindowRequested(int itemIndex);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
#if !TEST_TCP_MOVE_TO_MAIN
|
#if !TEST_TCP_MOVE_TO_MAIN
|
||||||
|
|
|
@ -20,8 +20,7 @@ DataHandler::DataHandler(QLabel* videoLabel, QLineEdit* VideoResolutionEdit, QSi
|
||||||
backBoardFuncConfig(backBoardFuncConfig), backBoardDevInfoJson(backBoardDevInfoJson),
|
backBoardFuncConfig(backBoardFuncConfig), backBoardDevInfoJson(backBoardDevInfoJson),
|
||||||
backBoardUuidJson(backBoardUuidJson), getPicJson(getPicJson), getVideoJson(getVideoJson),
|
backBoardUuidJson(backBoardUuidJson), getPicJson(getPicJson), getVideoJson(getVideoJson),
|
||||||
buffer(new QByteArray()), picBuffer(new QByteArray()),
|
buffer(new QByteArray()), picBuffer(new QByteArray()),
|
||||||
ffmpegDecoder(new FFmpegDecoder()) // 初始化FFmpeg解码器
|
ffmpegDecoder(new FFmpegDecoder()) // 初始化FFmpeg解码器
|
||||||
|
|
||||||
{
|
{
|
||||||
ffmpegDecoder->initialize(); // 初始化解码器
|
ffmpegDecoder->initialize(); // 初始化解码器
|
||||||
clearAllRecvData();
|
clearAllRecvData();
|
||||||
|
@ -46,7 +45,6 @@ DataHandler::~DataHandler()
|
||||||
void DataHandler::handleOpenFocusWindow(int itemIndex)
|
void DataHandler::handleOpenFocusWindow(int itemIndex)
|
||||||
{
|
{
|
||||||
if (ffmpegDecoder) {
|
if (ffmpegDecoder) {
|
||||||
qDebug() << "------- handleOpenFocusWindow";
|
|
||||||
ffmpegDecoder->processVideo(itemIndex); // 调用 FFmpegDecoder 的处理函数
|
ffmpegDecoder->processVideo(itemIndex); // 调用 FFmpegDecoder 的处理函数
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,7 +75,6 @@ void DataHandler::showVideo(const QString& client, const QByteArray& valData)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!valData.isEmpty()) {
|
if (!valData.isEmpty()) {
|
||||||
file.write(valData);
|
file.write(valData);
|
||||||
file.flush(); // 刷新文件缓冲区
|
file.flush(); // 刷新文件缓冲区
|
||||||
|
@ -111,9 +108,9 @@ void DataHandler::clearAllRecvData() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理接收到的数据
|
// 处理接收到的数据
|
||||||
void DataHandler::handleData(const QString& client, const QByteArray& recvData, int msg_id,
|
void DataHandler::handleData(const QString& client, const QByteArray& recvData, int msg_id,
|
||||||
int currentRecvItemIndex, int currentRecvFuncItemIndex,
|
int currentRecvItemIndex, int currentRecvFuncItemIndex, const QString& itemData,
|
||||||
const QString& itemData, const QString& funcItemData, const QJsonArray& jsonArray, int itemJsonIndex)
|
const QString& funcItemData, const QJsonArray& jsonArray, int itemJsonIndex)
|
||||||
{
|
{
|
||||||
//qDebug() << "Data received from" << client << ":" << recvData;
|
//qDebug() << "Data received from" << client << ":" << recvData;
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -158,10 +155,8 @@ void DataHandler::handleData(const QString& client, const QByteArray& recvData,
|
||||||
//QByteArray data = buffer->mid(10, dataSize);
|
//QByteArray data = buffer->mid(10, dataSize);
|
||||||
QString hexString = QString::fromUtf8(data.toHex().data());
|
QString hexString = QString::fromUtf8(data.toHex().data());
|
||||||
QByteArray actual_data = hexStringToByteArray(hexString);
|
QByteArray actual_data = hexStringToByteArray(hexString);
|
||||||
//qDebug() << "---Received hexString:" << hexString;
|
|
||||||
buffer->remove(0, totalSize); // 移除已处理的数据
|
buffer->remove(0, totalSize); // 移除已处理的数据
|
||||||
if(msg_id != 0x0040 && msg_id != START_VIDEO && msg_id != GET_IMG) {
|
if(msg_id != 0x0040 && msg_id != START_VIDEO && msg_id != GET_IMG) {
|
||||||
//if (msg_id != 0x0040) {
|
|
||||||
qDebug() << "--- msg_id:" << msg_id;
|
qDebug() << "--- msg_id:" << msg_id;
|
||||||
qDebug() << "--- clientLastMsgId.value(client, 0):" << clientLastMsgId.value(client, 0);
|
qDebug() << "--- clientLastMsgId.value(client, 0):" << clientLastMsgId.value(client, 0);
|
||||||
// 同一个client仅当 msg_id 不连续为 0x11/0x21 或第一次处理时才执行 emit statusUpdated
|
// 同一个client仅当 msg_id 不连续为 0x11/0x21 或第一次处理时才执行 emit statusUpdated
|
||||||
|
@ -186,7 +181,6 @@ void DataHandler::handleData(const QString& client, const QByteArray& recvData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DataHandler::initializeMsgIdToCmdMap() {
|
void DataHandler::initializeMsgIdToCmdMap() {
|
||||||
msgIdToCmdMap[GET_FRONT_V851_VERSION] = "GET_FRONT_V851_VERSION";
|
msgIdToCmdMap[GET_FRONT_V851_VERSION] = "GET_FRONT_V851_VERSION";
|
||||||
msgIdToCmdMap[GET_FRONT_MCU_VERSION] = "GET_FRONT_MCU_VERSION";
|
msgIdToCmdMap[GET_FRONT_MCU_VERSION] = "GET_FRONT_MCU_VERSION";
|
||||||
|
|
|
@ -40,12 +40,11 @@ public:
|
||||||
QJsonArray backBoardDevInfoJson, QJsonArray backBoardUuidJson,
|
QJsonArray backBoardDevInfoJson, QJsonArray backBoardUuidJson,
|
||||||
QJsonArray getPicJson, QJsonArray getVideoJson, QObject* parent = nullptr);
|
QJsonArray getPicJson, QJsonArray getVideoJson, QObject* parent = nullptr);
|
||||||
~DataHandler();
|
~DataHandler();
|
||||||
|
void handleOpenFocusWindow(int itemIndex);
|
||||||
public slots:
|
public slots:
|
||||||
void handleData(const QString& client, const QByteArray& data, int msg_id, int currentRecvItemIndex,
|
void handleData(const QString& client, const QByteArray& data, int msg_id, int currentRecvItemIndex,
|
||||||
int currentRecvFuncItemIndex, const QString& itemData, const QString& funcItemData,
|
int currentRecvFuncItemIndex, const QString& itemData, const QString& funcItemData,
|
||||||
const QJsonArray& jsonArray, int itemJsonIndex);
|
const QJsonArray& jsonArray, int itemJsonIndex);
|
||||||
void handleOpenFocusWindow(int itemIndex);
|
|
||||||
signals:
|
signals:
|
||||||
void statusUpdated(const QString& clientAddress, int currentItemIndex, int currentFuncItemIndex,
|
void statusUpdated(const QString& clientAddress, int currentItemIndex, int currentFuncItemIndex,
|
||||||
bool success, const QString& currentItemLabel, const QString& currentFuncItemLabel,
|
bool success, const QString& currentItemLabel, const QString& currentFuncItemLabel,
|
||||||
|
|
|
@ -96,26 +96,20 @@ MainWidget::MainWidget(QWidget* parent) :
|
||||||
frontBoardDevInfoJson, frontBoardLicenseJson,
|
frontBoardDevInfoJson, frontBoardLicenseJson,
|
||||||
backBoardOneClickTest, backBoardTest, backBoardFuncConfig, backBoardDevInfoJson,
|
backBoardOneClickTest, backBoardTest, backBoardFuncConfig, backBoardDevInfoJson,
|
||||||
backBoardUuidJson, getPicJson, getVideoJson, clientId, isBackBoardOrAllBoard, nullptr);
|
backBoardUuidJson, getPicJson, getVideoJson, clientId, isBackBoardOrAllBoard, nullptr);
|
||||||
/*
|
// 一定要先取消父对象
|
||||||
* 一定要先取消父对象,否则报错:QObject::moveToThread: Cannot move objects with a parent
|
|
||||||
* 父对象负责管理子对象的生命周期,如果子对象被移动到其他线程,可能会导致线程安全问题或不一致的对象状态
|
|
||||||
*/
|
|
||||||
socket->setParent(nullptr);
|
socket->setParent(nullptr);
|
||||||
// 将 socket 移动到新的线程中
|
// 将 socket 移动到新的线程中
|
||||||
socket->moveToThread(thread);
|
socket->moveToThread(thread);
|
||||||
// 将 socket 传递到 handler
|
// 将 socket 传递到 handler
|
||||||
handler->initialize(socket);
|
handler->initialize(socket);
|
||||||
#endif
|
#endif
|
||||||
// 将 ClientHandler 移到线程池中的线程
|
|
||||||
handler->moveToThread(thread);
|
|
||||||
|
|
||||||
// 创建 DataHandler 对象并连接信号
|
|
||||||
DataHandler* dataHandler = new DataHandler(videoLabel, VideoResolutionEdit, leftLens_imageLabel->size(), &devInfoLineEdits,
|
DataHandler* dataHandler = new DataHandler(videoLabel, VideoResolutionEdit, leftLens_imageLabel->size(), &devInfoLineEdits,
|
||||||
frontBoardOneClickTest, frontBoardTest, frontBoardFuncConfig,
|
frontBoardOneClickTest, frontBoardTest, frontBoardFuncConfig,
|
||||||
frontBoardDevInfoJson, frontBoardLicenseJson,
|
frontBoardDevInfoJson, frontBoardLicenseJson,
|
||||||
backBoardOneClickTest, backBoardTest, backBoardFuncConfig, backBoardDevInfoJson,
|
backBoardOneClickTest, backBoardTest, backBoardFuncConfig, backBoardDevInfoJson,
|
||||||
backBoardUuidJson, getPicJson, getVideoJson, nullptr);
|
backBoardUuidJson, getPicJson, getVideoJson, nullptr);
|
||||||
// 将 DataHandler 移到线程池中的线程
|
// 将 ClientHandler 和 DataHandler 移到线程池中的线程
|
||||||
|
handler->moveToThread(thread);
|
||||||
dataHandler->moveToThread(thread);
|
dataHandler->moveToThread(thread);
|
||||||
#if TEST_TCP_MOVE_TO_MAIN
|
#if TEST_TCP_MOVE_TO_MAIN
|
||||||
// 将sendData信号连接到主线程中的槽上
|
// 将sendData信号连接到主线程中的槽上
|
||||||
|
@ -157,7 +151,7 @@ MainWidget::MainWidget(QWidget* parent) :
|
||||||
connect(handler, &ClientHandler::selectClientDisconnected, this, &MainWidget::onDisconnectClient);
|
connect(handler, &ClientHandler::selectClientDisconnected, this, &MainWidget::onDisconnectClient);
|
||||||
|
|
||||||
dataHandlers[clientId] = dataHandler;
|
dataHandlers[clientId] = dataHandler;
|
||||||
connect(handler, &ClientHandler::dataReceived, dataHandler, &DataHandler::handleData);
|
connect(handler, &ClientHandler::dataReceived, dataHandler, &DataHandler::handleData);
|
||||||
connect(dataHandler, &DataHandler::statusUpdated, this, &MainWidget::onStatusUpdated);
|
connect(dataHandler, &DataHandler::statusUpdated, this, &MainWidget::onStatusUpdated);
|
||||||
// 当线程结束时删除 handler
|
// 当线程结束时删除 handler
|
||||||
connect(thread, &QThread::finished, this, [=]() {
|
connect(thread, &QThread::finished, this, [=]() {
|
||||||
|
@ -403,7 +397,7 @@ void MainWidget::setupUI()
|
||||||
|
|
||||||
// 前板
|
// 前板
|
||||||
QGroupBox* frontDeviceInfoGroupBox = createFrontDeviceInfoGroupBox();
|
QGroupBox* frontDeviceInfoGroupBox = createFrontDeviceInfoGroupBox();
|
||||||
QGroupBox* frontLicenseGroupBox = createLicenseGroupBox();
|
QGroupBox* frontLicenseGroupBox = createLicenseGroupBox();
|
||||||
|
|
||||||
QHBoxLayout* frontGroupBoxLayout = new QHBoxLayout;
|
QHBoxLayout* frontGroupBoxLayout = new QHBoxLayout;
|
||||||
frontGroupBoxLayout->addWidget(frontDeviceInfoGroupBox, 1);
|
frontGroupBoxLayout->addWidget(frontDeviceInfoGroupBox, 1);
|
||||||
|
@ -411,20 +405,20 @@ void MainWidget::setupUI()
|
||||||
|
|
||||||
QTabWidget* frontTabWidget = new QTabWidget(this);
|
QTabWidget* frontTabWidget = new QTabWidget(this);
|
||||||
frontTabWidget->setFixedSize(900, 315);
|
frontTabWidget->setFixedSize(900, 315);
|
||||||
QWidget* frontFunctionTestTab = createFunctionTestTab(frontBoardTest, "frontBoardTest");
|
QWidget* frontFunctionTestTab = createFunctionTestTab(frontBoardTest, "frontBoardTest");
|
||||||
QWidget* frontFunctionConfigTab = createFunctionConfigTab(frontBoardFuncConfig, "frontBoardFuncConfig");
|
QWidget* frontFunctionConfigTab = createFunctionConfigTab(frontBoardFuncConfig, "frontBoardFuncConfig");
|
||||||
frontTabWidget->addTab(frontFunctionTestTab, "前板测试项");
|
frontTabWidget->addTab(frontFunctionTestTab, "前板测试项");
|
||||||
frontTabWidget->addTab(frontFunctionConfigTab, "前板配置项");
|
frontTabWidget->addTab(frontFunctionConfigTab, "前板配置项");
|
||||||
|
|
||||||
QTabWidget* mainTabWidget = new QTabWidget(this);
|
QTabWidget* mainTabWidget = new QTabWidget(this);
|
||||||
QWidget* frontDevAreaTab = new QWidget(this);
|
QWidget* frontDevAreaTab = new QWidget(this);
|
||||||
QVBoxLayout* frontDevLayout = new QVBoxLayout(frontDevAreaTab);
|
QVBoxLayout* frontDevLayout = new QVBoxLayout(frontDevAreaTab);
|
||||||
frontDevLayout->addLayout(frontGroupBoxLayout);
|
frontDevLayout->addLayout(frontGroupBoxLayout);
|
||||||
frontDevLayout->addWidget(frontTabWidget, 2, Qt::AlignTop | Qt::AlignLeft);
|
frontDevLayout->addWidget(frontTabWidget, 2, Qt::AlignTop | Qt::AlignLeft);
|
||||||
mainTabWidget->addTab(frontDevAreaTab, "前 板");
|
mainTabWidget->addTab(frontDevAreaTab, "前 板");
|
||||||
|
|
||||||
// 后板
|
// 后板
|
||||||
QGroupBox* backDeviceInfoGroupBox1 = createBackDeviceInfoGroupBox();
|
QGroupBox* backDeviceInfoGroupBox1 = createBackDeviceInfoGroupBox();
|
||||||
QGroupBox* BackConnectServerGroupBox = createBackConnectServerGroupBox();
|
QGroupBox* BackConnectServerGroupBox = createBackConnectServerGroupBox();
|
||||||
|
|
||||||
QHBoxLayout* backGroupBoxLayout = new QHBoxLayout;
|
QHBoxLayout* backGroupBoxLayout = new QHBoxLayout;
|
||||||
|
@ -433,25 +427,25 @@ void MainWidget::setupUI()
|
||||||
|
|
||||||
QTabWidget* backTabWidget = new QTabWidget(this);
|
QTabWidget* backTabWidget = new QTabWidget(this);
|
||||||
backTabWidget->setFixedSize(900, 315);
|
backTabWidget->setFixedSize(900, 315);
|
||||||
QWidget* backFunctionTestTab = createFunctionTestTab(backBoardTest, "backBoardTest");
|
QWidget* backFunctionTestTab = createFunctionTestTab(backBoardTest, "backBoardTest");
|
||||||
QWidget* backFunctionConfigTab = createFunctionConfigTab(backBoardFuncConfig, "backBoardFuncConfig");
|
QWidget* backFunctionConfigTab = createFunctionConfigTab(backBoardFuncConfig, "backBoardFuncConfig");
|
||||||
backTabWidget->addTab(backFunctionTestTab, "后板测试项");
|
backTabWidget->addTab(backFunctionTestTab, "后板测试项");
|
||||||
backTabWidget->addTab(backFunctionConfigTab, "后板配置项");
|
backTabWidget->addTab(backFunctionConfigTab, "后板配置项");
|
||||||
|
|
||||||
QWidget* backDevAreaTab = new QWidget(this);
|
QWidget* backDevAreaTab = new QWidget(this);
|
||||||
QVBoxLayout* backDevLayout = new QVBoxLayout(backDevAreaTab);
|
QVBoxLayout* backDevLayout = new QVBoxLayout(backDevAreaTab);
|
||||||
backDevLayout->addLayout(backGroupBoxLayout);
|
backDevLayout->addLayout(backGroupBoxLayout);
|
||||||
backDevLayout->addWidget(backTabWidget, 2, Qt::AlignTop | Qt::AlignLeft);
|
backDevLayout->addWidget(backTabWidget, 2, Qt::AlignTop | Qt::AlignLeft);
|
||||||
mainTabWidget->addTab(backDevAreaTab, "后 板");
|
mainTabWidget->addTab(backDevAreaTab, "后 板");
|
||||||
|
|
||||||
// 整机
|
// 整机
|
||||||
QWidget* allDevAreaTab = new QWidget(this);
|
QWidget* allDevAreaTab = new QWidget(this);
|
||||||
QVBoxLayout* allDevLayout = new QVBoxLayout(allDevAreaTab);
|
QVBoxLayout* allDevLayout = new QVBoxLayout(allDevAreaTab);
|
||||||
mainTabWidget->addTab(allDevAreaTab, "整 机");
|
mainTabWidget->addTab(allDevAreaTab, "整 机");
|
||||||
|
|
||||||
QTabWidget* tabWidget_media = new QTabWidget(this);
|
QTabWidget* tabWidget_media = new QTabWidget(this);
|
||||||
QWidget* imageDisplayTab = createImageDisplayTab();
|
QWidget* imageDisplayTab = createImageDisplayTab();
|
||||||
QWidget* videoDisplayTab = createVideoDisplayTab();
|
QWidget* videoDisplayTab = createVideoDisplayTab();
|
||||||
tabWidget_media->addTab(imageDisplayTab, "图像显示区");
|
tabWidget_media->addTab(imageDisplayTab, "图像显示区");
|
||||||
tabWidget_media->addTab(videoDisplayTab, "视频显示区");
|
tabWidget_media->addTab(videoDisplayTab, "视频显示区");
|
||||||
|
|
||||||
|
@ -464,15 +458,15 @@ void MainWidget::setupUI()
|
||||||
mainLayout->addLayout(rightVerticalLayout, 3);
|
mainLayout->addLayout(rightVerticalLayout, 3);
|
||||||
|
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
setWindowTitle("SL100 工厂产测工具 - V0.0.4");
|
setWindowTitle("SL100 工厂产测工具 - V0.0.5");
|
||||||
resize(1340, 900);
|
resize(1340, 900);
|
||||||
|
|
||||||
connect(startServerButton, &QPushButton::clicked, this, &MainWidget::onStartServerClicked);
|
connect(startServerButton, &QPushButton::clicked, this, &MainWidget::onStartServerClicked);
|
||||||
connect(sendAllButton, &QPushButton::clicked, this, &MainWidget::onSendAllClicked);
|
connect(sendAllButton, &QPushButton::clicked, this, &MainWidget::onSendAllClicked);
|
||||||
connect(statusListWidget, &QListWidget::itemChanged, this, &MainWidget::scrollToBottom);
|
connect(statusListWidget, &QListWidget::itemChanged, this, &MainWidget::scrollToBottom);
|
||||||
connect(selectFileButton, &QPushButton::clicked, this, &MainWidget::onSelectFileButtonClicked);
|
connect(selectFileButton, &QPushButton::clicked, this, &MainWidget::onSelectFileButtonClicked);
|
||||||
connect(clearLogButton, &QPushButton::clicked, this, &MainWidget::onclearLogButtonClicked);
|
connect(clearLogButton, &QPushButton::clicked, this, &MainWidget::onclearLogButtonClicked);
|
||||||
connect(saveCheckBox, &QCheckBox::stateChanged, this, &MainWidget::onSaveCheckBoxStateChanged);
|
connect(saveCheckBox, &QCheckBox::stateChanged, this, &MainWidget::onSaveCheckBoxStateChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 服务器响应
|
// 服务器响应
|
||||||
|
@ -1290,7 +1284,11 @@ void MainWidget::onOpenFocusWindowClicked()
|
||||||
if (itemIndex == FOCUS_WINDOWS_BUTTON) {
|
if (itemIndex == FOCUS_WINDOWS_BUTTON) {
|
||||||
for (ClientHandler* handler : clients) {
|
for (ClientHandler* handler : clients) {
|
||||||
if (handler->getClientId() == handler->preVideoClientId) {
|
if (handler->getClientId() == handler->preVideoClientId) {
|
||||||
emit openFocusWindowRequested(itemIndex); // 发送信号
|
DataHandler* dataHandler = dataHandlers[handler->getClientId()];
|
||||||
|
if (dataHandler) {
|
||||||
|
dataHandler->handleOpenFocusWindow(itemIndex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,7 +153,7 @@ private:
|
||||||
void onDisconnectClient(int clientId);
|
void onDisconnectClient(int clientId);
|
||||||
void setupTimerForThreadPoolInfo();
|
void setupTimerForThreadPoolInfo();
|
||||||
void sendDataToClient(int clientId, const QByteArray& data);
|
void sendDataToClient(int clientId, const QByteArray& data);
|
||||||
//void FactoryToolSendPostFactoryInfotoHttpServer();
|
// 与服务器的接口
|
||||||
void FactoryToolSendPostTestToHttpServer();
|
void FactoryToolSendPostTestToHttpServer();
|
||||||
void FactoryToolSendPostLicenseToHttpServer(const QString& hardware_info, const QString& license_info);
|
void FactoryToolSendPostLicenseToHttpServer(const QString& hardware_info, const QString& license_info);
|
||||||
void FactoryToolSendPostComfirmToHttpServer(const QString& mac_addr, const QString& uuid);
|
void FactoryToolSendPostComfirmToHttpServer(const QString& mac_addr, const QString& uuid);
|
||||||
|
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
File diff suppressed because one or more lines are too long
10
README.md
10
README.md
|
@ -3,17 +3,13 @@
|
||||||
遇到问题:
|
遇到问题:
|
||||||
2024.09.01
|
2024.09.01
|
||||||
1. 运行报错:QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread
|
1. 运行报错:QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread
|
||||||
问题分析:主线程创建了 QTcpSocket,这个QTcpSocket的读写操作必须在主线程中执行,不能将QTcpSocket对象
|
问题分析:主线程创建了 QTcpSocket,这个QTcpSocket的读写操作必须在主线程中执行,不能将QTcpSocket对象通过新建的对象传参后到新建对象中对QTcpSocket进行读写操作,所有的QTcpSocket 的操作都在与它关联的线程中执行。
|
||||||
通过新建的对象传参后到新建对象中对QTcpSocket进行读写操作,所有的QTcpSocket 的操作都在与它关
|
|
||||||
联的线程中执行。
|
|
||||||
问题解决:1. 在主线程中创建 QTcpSocket 并获取连接:
|
问题解决:1. 在主线程中创建 QTcpSocket 并获取连接:
|
||||||
继续在主线程中使用 server->nextPendingConnection() 来获取客户端连接。
|
继续在主线程中使用 server->nextPendingConnection() 来获取客户端连接。
|
||||||
|
|
||||||
2. 将 QTcpSocket 移动到 ClientHandler 所属的新线程:
|
2. 将 QTcpSocket 移动到 ClientHandler 所属的新线程:
|
||||||
在将 QTcpSocket 传递给 ClientHandler 之前,将 QTcpSocket 移动到新线程中,确保它在新线程
|
在将 QTcpSocket 传递给 ClientHandler 之前,将 QTcpSocket 移动到新线程中,确保它在新线程中被使用。
|
||||||
中被使用。
|
这里注意不能将有父对象的QTcpSocket 移动到新线程中,因为父对象负责管理子对象的生命周期,如果子对象被移动到其他线程,可能会导致线程安全问题或不一致的对象状态。
|
||||||
这里注意不能将有父对象的QTcpSocket 移动到新线程中,因为父对象负责管理子对象的生命周期,
|
|
||||||
如果子对象被移动到其他线程,可能会导致线程安全问题或不一致的对象状态。
|
|
||||||
运行报错:QObject::moveToThread: Cannot move objects with a parent
|
运行报错:QObject::moveToThread: Cannot move objects with a parent
|
||||||
解决方法:如果 QTcpSocket 已经有父对象,你需要先将其父对象设置为 nullptr,再移动到新的线程。
|
解决方法:如果 QTcpSocket 已经有父对象,你需要先将其父对象设置为 nullptr,再移动到新的线程。
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue