简体   繁体   中英

Executing a qt application inside qt application

I'm trying to embed several qt applications inside another one that only work as container. (I'm using linux)

Lets call to the application container container and the one executed form container utility

In the container I have a QTabWidget, and inside this QTabWidget I have a Tab with a widget called utility1Widget.

I want to see the GUI of the utility inside utility1Widget.

Edit2 : The initial approach was wrong, I let it here for future references but a working implementation is in my separated answer.

I have try without success get the WId of utility1Widget and to send it as arg at the start time of utility , something like:

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();
}

As result the utility1Widget is empty but the utility GUI does not appear anywhere.

The utility process is launched from container in this way:

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

Thanks!!!!

Edit 1 I have added parent variable to inspect the result of find function, and it is NULL, so the first problem that I have is that I can't get container widget id, from utility.

Ok. this is the way that I've used to achieved.

As mentioned in the comments, for Qt 5.x you must use two function QWidget::createWindowContainer and QWindow::fromWinId(WId id) in the container. But also is important the timing when you call the functions, the following implementation is the only one that works for me, other ones get empty windows or duplicated and buggy windows.

Suppose that in the container app have a vertical layout I will put my embedded app in that layout.

In the container 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;
}

in the mainContainer window, add the embedApps function like this one

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

and finally in the utility app. 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();
}

You can use another methods to comunícate between the parent and child process but this one is enough for this demo.

Hope it helps! Enjoy.

This is a very complex task and as far as I know there is no perfect solution. I would suggest looking at stuff that is already out there. For example the ROS rqt offers something in this line of thought though it's mostly based on PyQt , requires third party framework (that is - ROS) and is buggy especially in terms of process management of the running applications. This is as a complete solution as it gets (as far as I have managed to find something until now).

I have worked on a project where I developed (using ROS rqt ) a process monitoring tool (for starting, stoping and monitoring the state of processes executed through ROS such as roslaunch or rosrun but also standalone applications) which had to automatically generate from a settings file and also have a process state restore function. The last is something that you might want to use no matter if you run background processes or convert your applications into normal widgets and add those to a Qt application. It's basically restoring the state of the process as much as possible upon starting your "control center". I used PID files with some extra info in each depending on the process I was running (all automatically generated of course). This is useful if you want to run the started external processes not as child processes (that is you kill the main app and all other processes are killed to) and want to allow your main app to regain control over the processes it has started during its last run. Excluding this neat feature I basically created a common interface with little derivatives based on the application type and then attached those to the UI using the rqt framework. It was definitely not an easy task.

In order to make things easier I would suggest that you convert the various applications you want to "embed" into self-contained QWidget (or some other derivative of QObject ) classes and embed those in the normal Qt-way (that is add the widgets to a parent QWidget ). If you want to have the widgets move around in a more natural desktop-ish way (click, drag, even rotate) you can use QGraphicsScene with QGraphicsProxyWidget s in it. Here is a reply of mine on this topic with one of the screenshots reposted below so that you can get a feel of what I'm talking about:

在此输入图像描述

It is not exactly what you are looking for but you can still make each proxy widget in the scene actually control a background process and expose some of its functionality. It's also much easier than what you are asking for. I'm currently working on a personal project in my free time on an application for image processing (I do believe I've mentioned this in the post I have linked above) where I use this methodology since the application is supposed to display and allow controlling things in a node-based fashion where each node is basically a widget of a specific type and offers altering the flow of data (if it's connected both visually and on a logical level to other nodes that produce data).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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