簡體   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