首页 > 技术文章 > 在qt界面中调用matlab engine并嵌入Matlab cmd Window

mosquitoam 2019-04-23 19:21 原文

环境:win10+QT(编译器:MSVC 2017 64-bit)+Matlab 2016a 64-bit

先上效果图:
在这里插入图片描述
在这里插入图片描述
主体思路如下(参考:https://blog.csdn.net/humanking7/article/details/86040954,做了些简化)
在这里插入图片描述

主要操作

涉及到的操作主要有:

  1. qt下启动线程操作;
  2. qt下调用matlab engine 的配置;
  3. qt嵌入外部程序的窗口;
  4. qt调用windows api;

多线程Qthread: https://blog.csdn.net/naibozhuan3744/article/details/81174681
qt下调用matlab engine的配置 http://blog.sina.com.cn/s/blog_89a45b020102vrr8.html
窗口的嵌入 https://blog.csdn.net/u013394556/article/details/78534833 https://blog.csdn.net/r5014/article/details/79286444
windows api 的调用 https://blog.csdn.net/ys_073/article/details/7770693>

代码和解释

UseMatlab.pro

#-------------------------------------------------
#
# Project created by QtCreator 2019-04-22T16:00:00
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = UseMatlab
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

CONFIG += c++11

SOURCES += \
        main.cpp \
        mainwindow.cpp \
    usematlabthread.cpp

HEADERS += \
        mainwindow.h \
    usematlabthread.h

FORMS += \
        mainwindow.ui

#添加matlab类库
INCLUDEPATH +=$$quote(D:\Program Files\MATLAB\R2016a\extern\include)       #matlab的extrern路径,有空格所以要用$$quote()
LIBS +=$$quote(D:\Program Files\MATLAB\R2016a\extern\lib\win64\microsoft\libeng.lib)
LIBS +=$$quote(D:\Program Files\MATLAB\R2016a\extern\lib\win64\microsoft\libmat.lib)
LIBS +=$$quote(D:\Program Files\MATLAB\R2016a\extern\lib\win64\microsoft\libmx.lib)
LIBS +=$$quote(D:\Program Files\MATLAB\R2016a\extern\lib\win64\microsoft\libmex.lib)

#添加windows库
LIBS +=User32.LIB

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

这里要注意的是添加matlab类库和windows库

usematlabthread.h

#ifndef USEMATLABTHREAD_H
#define USEMATLABTHREAD_H

//qt开启线程相关
#include <QThread>
#include <QMutex>
#include <QDebug>

//matlab相关
#include "engine.h"
#include "mat.h"

class UseMatlabThread: public QThread
{
    Q_OBJECT  //注意,没有Q_OBJECT没办法添加 signals

public:
    explicit UseMatlabThread(QObject *parent=nullptr);

    void closeThread();

signals:
    void detach_cmd();

protected:
    virtual void run();//新线程的执行的函数

public:
    volatile bool isStop; //易失变量?,需要用volatiale声明?,可以用于控制线程的开关


};

#endif // USEMATLABTHREAD_H

usematlabthread.cpp

#include "usematlabthread.h"

UseMatlabThread::UseMatlabThread(QObject *parent):QThread (parent)
{
    isStop=false;
}

void UseMatlabThread::closeThread()
{
    isStop=true;
}

void UseMatlabThread::run()
{
    Engine *Matlab;

    //open engine
    if (!(Matlab = engOpen("\0")))
    {
        qDebug()<<"Can't start MATLAB engine";
        return ;
    }


    emit detach_cmd();

    while(1)
    {
        if(isStop)
        {
            //close engine
            engClose(Matlab);
            return;
        }
        qDebug()<<"use Matlab Engine"<<QThread::currentThreadId();
        sleep(1);
    }
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QWindow>
#include <Windows.h>

#include "usematlabthread.h"  //用于启动matlab engine
#include "matlabcmddlg.h"     //用于将matlab engine嵌入对话框

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:

    void openME();
    void closeME();
    //void beginME();
    void finishME();

    void detach_mcmd();

private:
    Ui::MainWindow *ui;

    UseMatlabThread *thread1;

    MatlabCmdDlg *M_dialog1;
};

//#pragma execution_chaeacter_set("utf-8")

#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);

    thread1=new UseMatlabThread;

    connect(ui->pushButton_openME,SIGNAL(clicked()),this,SLOT(openME()));
    connect(ui->pushButton_closeME,SIGNAL(clicked()),this,SLOT(closeME()));

    connect(thread1,SIGNAL(detach_cmd()),this,SLOT(detach_mcmd()));
    connect(thread1,SIGNAL(finished()),this,SLOT(finishME()));


}

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

void MainWindow::detach_mcmd()
{
    WId wid=(WId)FindWindow(NULL, L"MATLAB Command Window");

    //WId wid=(WId)FindWindow(L"Edit", NULL);
    //wid=(WId)FindWindow(nullptr,nullptr);

   qDebug()<<"cmd win id"<<wid<<endl;
   QWindow * m_window=QWindow::fromWinId(wid);

   QWidget *m_widget;
   m_widget = QWidget::createWindowContainer(m_window, this->ui->widget_cmd);


   m_widget->setMinimumSize(841,111);
   m_widget->setMaximumSize(16777215,16777215);
   m_widget->show();

}


void MainWindow::openME()
{
    thread1->start();
    thread1->isStop=false;
    qDebug()<<"主线程 id"<<QThread::currentThreadId();
}

void MainWindow::closeME()
{
    thread1->closeThread();
    thread1->wait();
}


void MainWindow::finishME()
{
    qDebug()<<"finish";
}

推荐阅读