NX二次开发 调用Qt界面

前言:

NX调用Qt界面是可行的,相对麻烦些

注意:

1. NX软件本身内置了QT库,所以调用第三方QT开发时,必须保证版本统一,否则会报错:

后面重新测试,QT5.12.0,QT5.12.7都是可行的,QT环境通过环境变量

set QT_PLUGIN_PATH=%WORK_DIR%\plugins 设置,QT官方解释:

https://doc.qt.io/qt-6/deployment-plugins.html

2. 项目类型不是NX项目,而是创建Qt Widgets Application 项目,然后配置NX相关环境配置,

(也可以建立普通的C++ 项目,然后把NX和QT相关头文件库包含进去,QT项目容易出错)

3. 关于QT dll打包,和QT exe程序打包是不一样的,

不能用windeployqt命令来收集

不能用windeployqt命令来收集

不能用windeployqt命令来收集

收集的dll和QT bin目录下的dll是不一样的!!!如果收集的dll不对,后续环境变量的设置都是无效的,必须从bin目录下拷贝dll。

环境:

Win10,VS2017,NX1899,Qt5.12.X

项目搭建设置使用:

1.使用VS2017创建项目,注意是创建Qt项目,不是NX项目。一直下一步即可

2. 项目属性配置:

 (1)设置类型改成动态库dll(MFC的使用和字符集没有测试过,使用的默认值)

(2)设置 附加包含目录、附加库目录、附加依赖项

 注意:有时候虽然配置成dll,但仍然生成exe文件,此时需要强制更改输出文件

3. 编码   

 参考链接: https://github.com/Alexpux/qt-solutions/archive/refs/heads/master.zip

(1)从GitHub项目上摘取 qmfcapp.h  qmfcapp.cpp  qwinwidget.h   qwinwidget.cpp,添加到项目

(2)打开main.cpp文件,删除main函数,添加NX 入口函数:ufusr、ufusr_ask_unload:

#include <qmfcapp.h>
#include <qwinwidget.h>
#include <QMessageBox>
#include <afx.h>
#include <afxwin.h>
#include <Windows.h>
#include <QtGui.h>
#include <uf.h>
#include <uf_ui.h>

BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID  lpvReserved)
{
    static bool ownApplication = FALSE;

    //内部创建application实例
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        ownApplication = QMfcApp::pluginInstance(hInstance);

        //qApp 相关设置
    }

    //退出的时候delete qApp;
    if (dwReason == DLL_PROCESS_DETACH && ownApplication)
    {
        delete qApp;
    }

    return TRUE;
}

extern "C" DllExport void  ufusr(char *param, int *retcod, int param_len)
{
    if (UF_initialize())
    {
        return;
    }

    HWND hwnd = (HWND)UF_UI_get_default_parent();
    QWinWidget* parent = new QWinWidget(hwnd);

    //这里必须是指针,否则无效
    //QtGui gui(qWinWidget);
    //gui.activateWindow();
    //gui.show();
    QtGui* gui = new QtGui(parent);
    gui->activateWindow();
    gui->show();

    UF_terminate();
}

extern "C" DllExport int ufusr_ask_unload()
{
    return (UF_UNLOAD_UG_TERMINATE);
}

需要注意的是:将父窗口转成这个类QWinWidget,然后作为parent 传入自定义对话框类中。

不能将自定义对话框直接继承QWinWidget

其他测试代码:

 QtGui.hpp

#pragma once

#include <QtWidgets/QMainWindow>
#include <qwinwidget.h>
#include <QWidget>
#include <QLabel>
#include <QGridLayout>
#include <QLineEdit>
#include <QCheckBox>
#include <QDialog>
#include <QPushButton>


class QtGui : public QDialog
{
    Q_OBJECT

public:
    QtGui(QWidget* parent);

public slots:
    void CreateBlock();

private:
    QLabel* m_lengthLabel;
    QLineEdit* m_lengthLineEdit;
    QLabel* m_widthLabel;
    QLineEdit* m_widthLineEdit;
    QLabel* m_heightLabel;
    QLineEdit* m_heightLineEdit;
    QPushButton* m_createBlock;
    QGridLayout* m_mainLayout;

};

QtGui.cpp

#pragma execution_character_set("utf-8")
#include "QtGui.h"
#include <uf_modl.h>

QtGui::QtGui(QWidget* parent) :QDialog(parent)
{
    m_lengthLabel = new QLabel(tr("长度:"));
    m_lengthLineEdit = new QLineEdit;

    m_widthLabel = new QLabel(tr("宽度:"));
    m_widthLineEdit = new QLineEdit;

    m_heightLabel = new QLabel(tr("高度:"));
    m_heightLineEdit = new QLineEdit;

    m_createBlock = new QPushButton(tr("创建块"));

    m_mainLayout = new QGridLayout(this);
    m_mainLayout->setMargin(15);
    m_mainLayout->setSpacing(10);

    m_mainLayout->addWidget(m_lengthLabel, 0, 0);
    m_mainLayout->addWidget(m_lengthLineEdit, 0, 1);
    m_mainLayout->addWidget(m_widthLabel, 1, 0);
    m_mainLayout->addWidget(m_widthLineEdit, 1, 1);
    m_mainLayout->addWidget(m_heightLabel, 2, 0);
    m_mainLayout->addWidget(m_heightLineEdit, 2, 1);
    m_mainLayout->addWidget(m_createBlock, 3, 0);
    m_mainLayout->setSizeConstraint(QLayout::SetFixedSize);

    connect(m_createBlock, &QPushButton::clicked, this, &QtGui::CreateBlock);
}

void QtGui::CreateBlock()
{
    std::string length = m_lengthLineEdit->text().toStdString();
    std::string width = m_widthLineEdit->text().toStdString();
    std::string height = m_heightLineEdit->text().toStdString();

    double corner[3] = { 0.0 };
    char* size[3] = { const_cast<char*>(length.c_str()),
                              const_cast<char*>(width.c_str()),
                              const_cast<char*>(height.c_str())
                             };

    tag_t blockFeat = NULL_TAG;
    UF_MODL_create_block(UF_FEATURE_SIGN::UF_NULLSIGN, NULL_TAG, corner, size, &blockFeat);
    UF_MODL_update();
}

 (3)示例:创建一个块 

4. 收集依赖的dll

开发时配置QT环境到PATH中,启动VS编译运行都是OK的

@echo off
set WORK_DIR=D:\MyProject\Qt\Qt_NX\QtClassLibrary1
set "UGII_BASE_DIR=C:\Program Files\Siemens\NX1899"
set VS2017_EXE="C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\devenv.exe"
set QTDIR=C:\Qt\Qt5.12.7\5.12.7\msvc2017_64

rem 
set PATH=%UGII_ROOT_DIR%;%UGII_UGRAF_DIR%;%PATH%;%QTDIR%\bin;
set UGII_DISPLAY_DEBUG=1

%VS2017_EXE%  %WORK_DIR%\QtClassLibrary1.sln

但按照之前的用windeployqt命令来收集好dll之后会报错,只要运行NX界面上的属性、信息功能或者调用API UF_UI_write_listing_window() 功就会崩溃......

尝试过set QT_QPA_PLATFORM_PLUGIN_PATH到 dll所在文件夹也不行,各种报错:

 

最后从把所有bin文件夹下的内容拷贝到dll所在目录,然后NX中调用这个dll,再把拷贝的文件全部删除,看哪些dll被占用,发现:

 

然后只保留这三个dll文件,就可以了 !!!

(编译的dll是Release版本,如果是Debug,依赖的三个dll要加d)

5. 部署到其他电脑使用

本来以为收集3个dll就结束了,然后把软件包拷贝到其他电脑上使用,结果报错:

百度搜了下:可以参考链接:

https://blog.csdn.net/qq_43903004/article/details/113878306

https://blog.csdn.net/qq_51606180/article/details/120384845

set QT_PLUGIN_PATH=%WORK_DIR%\plugins 或
set QT_QPA_PLATFORM_PLUGIN_PATH=%WORK_DIR%\plugins\platforms

运行成功,还是得通过报错信息上找原因。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值