QT在当前进程界面中嵌入其他进程的界面

最近接触到外协厂家的一套系统,这套系统的主界面由几个功能界面组成的,他的实现方式并不是将所有的功能界面设计在这一个主界面程序上,而是将各个功能界面做成单独的界面程序(单独的进程),每个程序都可以独立运行,然后通过将这几个程序嵌入到主界面中,形成一个完整的主界面。这种模块化的实现方式耦合度不高,各个模块比较独立。因为外协厂家的源码是没有开放给我们,所以从网上翻了几篇博客,对可能的实现方式有了基本的了解,虽然这种在当前进程界面中嵌入其他进程界面的应用场景可能不多,但是记录一下,作为知识储备,方便以后查用。

我使用的环境是Ubuntu12.04, QT5.5 开始之前对几个用到几个知识点交代一下。

1、QProcess:这个类用于启动外部进程,它有两种启动方式

一体式:QProcess::start 方法。外部程序启动后,将随主程序的退出而退出。 貌似要使用QProcess的close方法才可以关闭启动的外部程序。

分离式:QProcess::startDetached 方法。外部程序启动后,当主程序退出时并不退出,而是继续运行。

它不是重点这里简单介绍。

2、QWindow* QWindow::fromWinId(WId id):这是QWindow的一个方法,可以通过传入的一个窗口句柄创建一个QWindow对象,然后将它嵌入到当前进程的的界面容器中。

3、 QWidget *QWidget::createWindowContainer(QWindow *window, QWidget *parent = Q_NULLPTR, Qt::WindowFlags flags = Qt::WindowFlags()):这是QWidget的一个方法,它会创建一个QWidget窗口容器,该窗口容器被创建来作为父窗口的子窗口,并且可以在参数中设置窗体属性标志。

代码如下,这里分成两部分,child是要嵌入的子窗体进程,parent是父窗体进程。界面很简单。

这是child的代码,就是最简单的UI界面,唯一添加的一点就是将窗口的winID存到了一个文件里面,方便给parent进程读取,然后用这个ID来创建要嵌入的界面。

头文件

#ifndef CHILDWIDGET_H
#define CHILDWIDGET_H

#include <QWidget>

namespace Ui {
class ChildWidget;
}

class ChildWidget : public QWidget
{
    Q_OBJECT

public:
    explicit ChildWidget(QWidget *parent = 0);
    ~ChildWidget();

private:
    Ui::ChildWidget *ui;
};

#endif // CHILDWIDGET_H
#include "childwidget.h"
#include "ui_childwidget.h"
#include <QDebug>
#include <QSettings>

ChildWidget::ChildWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ChildWidget)
{
    ui->setupUi(this);
    QSettings* settings = new QSettings("/ID.ini",QSettings::IniFormat);
    settings->setValue("T3",this->winId());
}

ChildWidget::~ChildWidget()
{
    delete ui;
}
#include "childwidget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    ChildWidget w;
    w.show();

    return a.exec();
}

                                                  

下面时parent进程的代码

首先是头文件

#ifndef PARENTWIDGET_H
#define PARENTWIDGET_H

#include <QWidget>

namespace Ui {
class ParentWidget;
}

class ParentWidget : public QWidget
{
    Q_OBJECT

public:
    explicit ParentWidget(QWidget *parent = 0);
    ~ParentWidget();

private:
    Ui::ParentWidget *ui;
    QWidget *childWidget;

};

#endif // PARENTWIDGET_H

下面是源文件,在构造方法中,我们先通过QProcess启动了child进程,然后再读取child进程写到文件中的winID,利用这个winID创建要嵌入的窗体,然后放到窗体容器中,最后在放到窗体布局中。

#include "parentwidget.h"
#include "ui_parentwidget.h"
#include <QWindow>
#include <QSettings>
#include <QProcess>
ParentWidget::ParentWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ParentWidget),
    childWidget(NULL)
{
    ui->setupUi(this);
    QProcess* caller = new QProcess(this);//创建对象
    caller->start("/root/qt-windows-composition-example-master/child/child");//启动notepaid
    sleep(1);
    QSettings* settings = new QSettings("/ID.ini",QSettings::IniFormat);
    int childWidgetWinId = settings->value("T3").toInt();; //get from debug output
    QWindow *childWindow = QWindow::fromWinId(childWidgetWinId);
    childWidget = QWidget::createWindowContainer(childWindow, this, Qt::Widget );
    childWidget->setMinimumSize(100,100);
    ui->verticalLayout_2->addWidget(childWidget,1,0);
}

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

下面是主函数

#include "parentwidget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    ParentWidget w;
    w.show();

    return a.exec();
}

这是parent的界面

启动parent进程,运行效果如图

这种方式虽然有耦合度低的好处,但是也有一定的缺陷,大量使用会影响程序的整体性能,在Qt的帮助文档中有明确说明:

  • Using many window container instances in a QWidget-based application can greatly hurt the overall performance of the application.

译:在基于QWidget的应用中使用大量的window窗口容器实例,会在很大程度上影响应用程序的整体性能。

  • 12
    点赞
  • 76
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值