• ubuntu20.04.3中qt程序界面嵌套另一个qt界面


    先上代码

    #include "mainwindow.h"
    #include 
    #include 
    using namespace std;
    #ifdef _WIN32
        // Windows 平台的代码
    #include 
    #elif __linux__
        // Linux 平台的代码
        // ...
        #include 
    #else
        // 其他平台的代码或错误处理
        // ...
    #endif
    QString cmd = QString("/home/lxk/Code/build-MyQtApp-Desktop_Qt_5_9_6_GCC_64bit-Debug/MyQtApp");
    
    
    #include 
    #include 
    #include 
    #include 
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        //w.init();
        //w.show();
        QString cmd = QString("/home/lxk/Code/build-MyQtApp-Desktop_Qt_5_9_6_GCC_64bit-Debug/MyQtApp");;
        QProcess m_pProcess(&a);
          //m_pProcess.setProcessChannelMode(QProcess::MergedChannels);
          m_pProcess.start(cmd);
          WId wid2 = 0;
          //-- 只保证进程已经开始,但不保证进程的主窗口已经创建
          if (m_pProcess.waitForStarted()) {
                 QThread::sleep(2);
                  // 获取外部窗口句柄
                  QStringList arguments;
                  {
                      arguments << "search";
                      arguments << "--name" << "oop";
                      QProcess xprop;
                      xprop.start("xdotool", arguments);
                      xprop.waitForFinished();
                      //if(xprop.waitForFinished())
                      {
                          QByteArray byteArray = xprop.readAllStandardOutput();
                          QString input = QString::fromUtf8(byteArray);
                          QStringList numbers = input.trimmed().split("\n");
                          QString tmp = numbers[0];
                          wid2 = numbers[0].toULong();
                          qDebug() << "WId2:" << wid2;
    
                          //xdotool windowunmap 52428805
                          arguments.clear();
                          arguments << "windowunmap";
                          arguments << tmp;
                          xprop.start("xdotool", arguments);
    
                          QWidget *container  = new QWidget;
                          container->setMinimumSize(QSize(600,500));
                          QLabel* label = new QLabel("Hello Kand");
                          QWidget* pWidget2 = QWidget::createWindowContainer(QWindow::fromWinId(wid2));
                          //pWidget2->setWindowFlags(pWidget2->windowFlags() | Qt::WindowStaysOnTopHint);
                         // pWidget2->raise(); // 将窗口降低到最后面
    
                          QVBoxLayout* layout = new QVBoxLayout(container);
                         
                          layout->addWidget(pWidget2);
                          //layout->addWidget(label);
    
                          container->setLayout(layout); // This is important, it sets the layout for the container widget
                          container->show();
                      }
                  }
            }
        return a.exec();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79

    一般情况下,宿主程序嵌入子程序的思路是个window下的思路是一样的。
    1.也是先启动程序

        QString cmd = QString("/home/Code/build-MyQtApp-Desktop_Qt_5_9_6_GCC_64bit-Debug/MyQtApp");;
        QProcess m_pProcess(&a);
          //m_pProcess.setProcessChannelMode(QProcess::MergedChannels);
          m_pProcess.start(cmd);
          WId wid2 = 0;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.找到窗口句柄

          if (m_pProcess.waitForStarted()) {
                 QThread::sleep(2);
                  // 获取外部窗口句柄
                  QStringList arguments;
                  {
                      arguments << "search";
                      arguments << "--name" << "oop";
                      QProcess xprop;
                      xprop.start("xdotool", arguments);
                      xprop.waitForFinished();
                      //if(xprop.waitForFinished())
                      {
                          QByteArray byteArray = xprop.readAllStandardOutput();
                          QString input = QString::fromUtf8(byteArray);
                          QStringList numbers = input.trimmed().split("\n");
                          QString tmp = numbers[0];
                          wid2 = numbers[0].toULong();
                          qDebug() << "WId2:" << wid2;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    xdotool search --name oop
    这个oop是WindowTitle

    3.设置窗口的状态(有的系统不需要设置窗口的状态,比如window10不设置窗口状态,也可以嵌入)很重要。

                          //xdotool windowunmap 52428805
                          arguments.clear();
                          arguments << "windowunmap";
                          arguments << tmp;
                          xprop.start("xdotool", arguments);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4.然后常规的嵌入就ok了

    QWidget* pWidget2 = QWidget::createWindowContainer(QWindow::fromWinId(wid2));
                          //pWidget2->setWindowFlags(pWidget2->windowFlags() | Qt::WindowStaysOnTopHint);
                         // pWidget2->raise(); // 将窗口降低到最后面
    
                          QVBoxLayout* layout = new QVBoxLayout(container);
                         
                          layout->addWidget(pWidget2);
                          //layout->addWidget(label);
    
                          container->setLayout(layout); // This is important, it sets the layout for the container widget
                          container->show();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    相关命令如下:

     WindowTitle不要重名;
    xdotool search --name oop 查看WindowTitle为oop的窗口的id
    xprop -id <window_id> WM_STATE   查看这个窗口的状态
    比如:
    (base) l@ubuntu:~/Desktop$ xprop -id 52428805 WM_STATE
    WM_STATE(WM_STATE):
    		window state: Normal
    		icon window: 0x0
    		
    改变这个窗口的状态
    xdotool windowunmap 52428805
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    上文需要在系统中安装一些工具。
    下文可以不用看!
    Ps: 一个进程可以管理程序的多个窗口,我的测试代码如下,不知为何我检测到两个MyQtApp,我没有深究,可能原本启动一个程序,个人猜测 ------然后在嵌入的时候又复制了一个吧,不清楚!反正不对!也许把窗口状态改变就可以了。 我没试。

            #ifdef _WIN32
                // Windows 平台的代码
                wid = (WId)FindWindow(L"UnityWndClass", nullptr);
            #elif __linux__
                //-- XOpenDisplay 允许你的程序与 X Window System 进行通信,从而实现图形界面交互。
                Display* display = XOpenDisplay(NULL);
                if (display == NULL) {
                    fprintf(stderr, "无法打开显示\n");
                    return 1;
                }
    
                //-- "根窗口"是一个特殊的窗口,它是所有其他窗口的祖先。所有的窗口,无论是顶级窗口还是子窗口,都是从根窗口派生出来的。
                //-- 在大多数情况下,根窗口是整个屏幕或整个显示设备。
                Window root = DefaultRootWindow(display);
    
                Window root_return, parent_return;
                Window* children;
                unsigned int num_children;
    
                if (XQueryTree(display, root, &root_return, &parent_return, &children, &num_children)) {
                    for (unsigned int i = 0; i < num_children; i++) {
                        char* name = NULL;
                        if (XFetchName(display, children[i], &name)) {
                            qDebug() << "name:" << name;
                            //if (name != NULL && strcmp(name, "gnome-calculator") == 0) {
                            if (name != NULL && strcmp(name, "MyQtApp") == 0) {
    
                                wid = children[i];
                                XFree(name);
                                break;
                            }
                            XFree(name);
                        }
                    }
                    XFree(children);
                }
    
                if (wid == 0) {
                    fprintf(stderr, "未找到指定窗口\n");
                    XCloseDisplay(display);
                    return 1;
                }
                else
                {
                    //窗口的名字是"MyQtApp",那么会将这个窗口的ID赋值给wid,否则wid会是无效的。所以,如果窗口的名字是"MyQtApp",那么pWindow应该是有效的。
                    //在使用 Xlib(X Window System 的 C 语言库)时,你需要通过 XOpenDisplay 函数来打开一个连接到 X Server 的会话。
                    //这个会话会在你的程序运行期间保持打开状态,直到你显式地关闭它。
                    //但是,需要注意的是,你在代码中使用了XCloseDisplay(display);来关闭display。在调用XCloseDisplay后,所有与这个display相关的资源都应该被释放。CloseDisplay(display) 就是用于关闭这个连接的函数调用。在你的代码中,display 是一个指向 Display 结构体的指针,它代表了与 X Server 的连接。关闭连接是一个良好的做法,因为它会释放与 X Server 的通信资源,并且可以确保你的程序在退出时不会留下未关闭的连接。
                    XCloseDisplay(display);
                    // 现在你可以使用 'wid' 变量来操作该窗口
                    qDebug() << "Window ID:" << wid;
                }
            #else
                // 其他平台的代码或错误处理
                // ...
            #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
  • 相关阅读:
    软件设计模式系列之四——简单工厂模式
    c++中的deque容器和queue容器
    Bean的作用域和生命周期
    计算机网络第3章(数据链路层)-----总结1
    Spring源码深度解析(六):Spring事务原理详解
    【高并发】深度解析线程池中那些重要的顶层接口和抽象类
    Java实现简易版的【图书管理系统】
    十八、商城 - 规格管理-模板管理(6)
    『Jmeter入门万字长文』 | 从环境搭建、脚本设计、执行步骤到生成监控报告完整过程
    C++—— pass by value and use std::move
  • 原文地址:https://blog.csdn.net/baidu_19552787/article/details/133513638