在基于图像处理的开发中,Halcon作为功能强大的图像处理库,经常需要与Qt结合,以便通过Qt提供的UI功能更好地显示和交互。本文将讲解如何在Qt中集成Halcon窗口,并通过子线程实现Halcon图像的显示,保证主线程的流畅运行。
工程代码下载链接
通过网盘分享的文件:HALCON窗口依附Qt控件
链接: https://pan.baidu.com/s/1gNWCTpha9-vsYPHEX0R_vQ?pwd=jkcf 提取码: jkcf
一、Halcon窗口与Qt控件的结合原理
在Qt中,QGraphicsView
等控件用于显示图像。而Halcon可以通过窗口句柄将其窗口嵌入到Qt控件中。通过将Halcon窗口与Qt控件绑定,我们既能使用Qt的交互功能,又能发挥Halcon的强大图像处理能力。为了提升程序性能,Halcon窗口的操作可以放到子线程中执行,避免阻塞主线程。
二、项目初始化与Halcon库的配置
在Qt中使用Halcon库时,首先需要配置.pro
文件,添加Halcon库的路径:
1. 修改.pro
文件
# 配置头文件路径
INCLUDEPATH += "./libary/hdevelop/include"
INCLUDEPATH += "./libary/hdevelop/include/halconcpp"
# 配置库文件路径
LIBS += "./libary/hdevelop/lib/halconcpp.lib"
其中:
INCLUDEPATH
指定 Halcon 头文件的路径。LIBS
指定 Halcon 动态库的路径。
2. 全局窗口句柄声明
为了管理Halcon窗口,声明一个全局变量:
#include "HalconCpp.h"
HalconCpp::HTuple m_window; // 全局窗口句柄
三、分离线程逻辑:创建一个线程类
在复杂的程序中,将线程逻辑独立出来是一种更好的设计方式。我们通过创建一个专门的线程类,处理Halcon图像的显示逻辑。
1. 线程类定义
新建线程类 ThreadedWorker
,继承自 QThread
:
ThreadedWorker.h
#ifndef THREADEDWORKER_H
#define THREADEDWORKER_H
#include <QThread>
#include "HalconCpp.h"
class ThreadedWorker : public QThread
{
Q_OBJECT
public:
explicit ThreadedWorker(HalconCpp::HTuple window, QObject* parent = nullptr);
~ThreadedWorker();
protected:
void run() override;
private:
HalconCpp::HTuple m_window; // Halcon窗口句柄
};
#endif // THREADEDWORKER_H
ThreadedWorker.cpp
#include "ThreadedWorker.h"
ThreadedWorker::ThreadedWorker(HalconCpp::HTuple window, QObject* parent)
: QThread(parent), m_window(window)
{
}
ThreadedWorker::~ThreadedWorker()
{
if (isRunning()) {
quit();
wait();
}
}
void ThreadedWorker::run()
{
try {
// 设置Halcon窗口的显示区域
HalconCpp::SetPart(m_window, 0, 0, 1023, 1023);
// 清空窗口并显示图像
HalconCpp::ClearWindow(m_window);
HalconCpp::HObject hv_Image;
HalconCpp::GenImageConst(&hv_Image, "byte", 1024, 1024); // 生成测试图像
HalconCpp::DispObj(hv_Image, m_window); // 在窗口中显示图像
} catch (HalconCpp::HException& ex) {
qWarning("Halcon exception: %s", ex.ErrorText().Text());
}
}
run()
是线程的主函数,负责设置Halcon窗口并显示图像。- Halcon操作(如
SetPart
、ClearWindow
和DispObj
)都集中在此线程中,避免阻塞主线程。
四、主窗口中调用线程类
在主窗口类中,我们完成Halcon窗口的初始化,并创建和启动线程。
1. 主窗口类定义
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "HalconCpp.h"
#include "ThreadedWorker.h"
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;
HalconCpp::HTuple m_window; // Halcon窗口句柄
ThreadedWorker* worker; // 线程对象
};
#endif // MAINWINDOW_H
2. 主窗口实现
MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 初始化Halcon窗口
HalconCpp::OpenWindow(0, 0, 500, 500, static_cast<Hlong>(ui->graphicsView->winId()), "", "", &m_window);
HalconCpp::SetColored(m_window, 12); // 设置窗口颜色
HalconCpp::SetHcppInterfaceStringEncodingIsUtf8(true); // 启用UTF-8编码
// 创建线程对象
worker = new ThreadedWorker(m_window, this);
// 启动线程
worker->start();
}
MainWindow::~MainWindow()
{
// 关闭线程
if (worker) {
worker->quit();
worker->wait();
delete worker;
}
delete ui;
}
五、运行效果
主线程的职责
- 初始化Halcon窗口,将其与
QGraphicsView
控件绑定。 - 创建并启动线程对象。
- 初始化Halcon窗口,将其与
子线程的职责
- 设置Halcon窗口的显示区域。
- 在Halcon窗口中显示测试图像。
运行程序后,Halcon窗口会嵌入到Qt的GraphicsView
控件中,显示测试图像,同时主线程保持流畅运行。
六、设计优点
解耦性
将线程逻辑与主窗口分离,使代码结构清晰,易于维护和扩展。性能优化
通过子线程执行Halcon操作,避免阻塞主线程,提高UI的响应速度。易于扩展
若需增加其他图像处理功能,可直接在ThreadedWorker
类中添加,不影响主窗口逻辑。