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

先上代码

#include "mainwindow.h"
#include <QApplication>
#include <iostream>
using namespace std;
#ifdef _WIN32
    // Windows 平台的代码
#include <windows.h>
#elif __linux__
    // Linux 平台的代码
    // ...
    #include <X11/Xlib.h>
#else
    // 其他平台的代码或错误处理
    // ...
#endif
QString cmd = QString("/home/lxk/Code/build-MyQtApp-Desktop_Qt_5_9_6_GCC_64bit-Debug/MyQtApp");


#include <QThread>
#include <QWidget>
#include <QVBoxLayout>
#include <QLabel>

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

一般情况下,宿主程序嵌入子程序的思路是个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;

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;

xdotool search --name oop
这个oop是WindowTitle

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

                      //xdotool windowunmap 52428805
                      arguments.clear();
                      arguments << "windowunmap";
                      arguments << tmp;
                      xprop.start("xdotool", arguments);

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

相关命令如下:

 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

上文需要在系统中安装一些工具。
下文可以不用看!
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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值