繁体   English   中英

在qt应用程序中执行qt应用程序

[英]Executing a qt application inside qt application

我正在尝试将几个qt应用程序嵌入到另一个只能用作容器的应用程序中。 (我正在使用linux)

让我们调用应用程序容器容器和一个执行的表单容器实用程序

容器中我有一个QTabWidget,在这个QTabWidget里面我有一个带有一个叫做utility1Widget的小部件的Tab。

我想在utility1Widget中看到该实用程序的GUI。

编辑2 :最初的方法是错误的,我把它放在这里以供将来参考,但一个有效的实现在我的分离答案中。

我试过没有成功获取实用程序窗口小部件的WId并在实用程序的开始时间将其作为arg发送,例如:

utility.cpp

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    int containerWinId;
    QWidget *parent=NULL;
    if(argc==2) {
        containerWinId=atoi(argv[1]);
        parent = QWidget::find(containerWinId);
    }

    MarinaWindowClient w(parent);

    w.show();
    printf("Starting client window. Do you see something?\r\n");
    fflush(stdout);
    return a.exec();
}

因此,utility1Widget为空,但实用程序GUI不会出现在任何地方。

实用程序进程以这种方式从容器启动:

mainContainer.cpp

marinaContainer::mainContainer(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::mainContainer)
{
    ui->setupUi(this);
    WId myWinId=ui->utility1Widget->winId();
    char cmd[1000];
    sprintf(cmd," %d",myWinId);
    QProcess *myProcess = new QProcess(this);
    myProcess->start("utility1", QStringList(cmd));

    printf("Client started\r\n");
    fflush(stdout);
}

谢谢!!!!

编辑1我添加了父变量来检查查找函数的结果,它是NULL,所以我遇到的第一个问题是我无法从实用程序获取容器窗口小部件ID。

好。 这是我过去常常实现的方式。

正如评论中所提到的,对于Qt 5.x,您必须在容器中使用两个函数QWidget :: createWindowContainerQWindow :: fromWinId(WId id) 但是调用函数的时机也很重要,以下实现是唯一适合我的实现,其他实现是空窗口或重复和错误的窗口。

假设在容器应用程序中有一个垂直布局,我将把我的嵌入式应用程序放在该布局中。

在容器main.cpp中

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    mainContainer w;
    char cmd[1000];

    QProcess *myProcess1 = new QProcess();
    myProcess1->start("utility");
    char buff[500];
    buff[0]=0;
    myProcess1->waitForStarted();
    myProcess1->waitForReadyRead();

    myProcess1->read(buff,100);
    unsigned long long id1=atoll(buff);
    fflush(stdout);
    w.embedApps(id1);
    myProcess1->write("continue\r\n");
    w.show();
    a.exec();
    myProcess1->kill();
    return 0;
}

在mainContainer窗口中,添加像这样的embedApps函数

void marinaContainer::embedApps(WId id1, WId id2)
{
    QWindow *qw = QWindow::fromWinId(id1);
    QWidget *w1= QWidget::createWindowContainer(qw,this);
    ui->verticalLayout->addWidget(w1);
}

最后在实用程序中。 main.cpp中

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    utilityMainWindow w;
    printf("%lld\r\n",w.winId());
    fflush(stdout);
    char trash[100];
    //We wait until container was created and say 'ok, coninue'
    scanf("%99s",trash);
    w.show();
    return a.exec();
}

您可以使用其他方法在父进程和子进程之间进行通信,但这个方法足以用于此演示。

希望能帮助到你! 请享用。

这是一项非常复杂的任务,据我所知,没有完美的解决方案。 我建议看那些已经存在的东西。 例如, ROS rqt在这一思路中提供了一些东西,虽然它主要基于PyQt ,需要第三方框架(即ROS),并且特别是在运行应用程序的进程管理方面存在问题。 这是一个完整的解决方案(据我迄今为止设法找到了一些东西)。

我参与了一个项目,我开发了一个项目(使用ROS rqt )一个过程监控工具(用于启动,停止和监控通过ROS执行的进程状态,例如roslaunchrosrun ,还有独立的应用程序),这些工具必须从设置中自动生成文件并具有进程状态还原功能。 无论您是运行后台进程还是将应用程序转换为普通小部件并将其添加到Qt应用程序,最后都可以使用。 它基本上是在启动“控制中心”时尽可能地恢复过程的状态。 我根据我正在运行的进程使用了​​PID文件和一些额外的信息(当然都是自动生成的)。 如果您希望运行已启动的外部进程而不是作为子进程(即您终止主应用程序并且所有其他进程都被终止)并且希望允许主应用程序重新控制其在其中启动的进程,则此功能非常有用最后一次。 除了这个简洁的功能,我基本上创建了一个基于应用程序类型的小衍生物的通用接口,然后使用rqt框架将rqt附加到UI。 这绝对不是一件容易的事。

为了使事情变得简单,我建议你将你想要“嵌入”的各种应用程序转换为自包含的QWidget (或QObject其他衍生物)类,并以正常的Qt方式嵌入(即添加小部件)到父QWidget )。 如果您想让窗口小部件以更自然的桌面方式移动(单击,拖动,甚至旋转),您可以在其中使用QGraphicsSceneQGraphicsProxyWidget 以下是我对此主题的回复 ,其中一个屏幕截图在下面重新发布,以便您可以了解我在说什么:

在此输入图像描述

它并不完全是您正在寻找的,但您仍然可以使场景中的每个代理窗口小部件实际控制后台进程并公开其一些功能。 它也比你要求的要容易得多。 我正在空闲时间处理一个关于图像处理应用程序的个人项目(我相信我已经在上面链接的帖子中提到了这个),我使用这种方法,因为应用程序应该显示并允许以基于节点的方式控制事物,其中每个节点基本上是特定类型的窗口小部件,并提供改变数据流(如果它在视觉上和逻辑层面上连接到产生数据的其他节点)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM