Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Issue with Embedding Qt Window into QStackedLayout Using DLL
Forum Updated to NodeBB v4.3 + New Features

Issue with Embedding Qt Window into QStackedLayout Using DLL

Scheduled Pinned Locked Moved Unsolved General and Desktop
5 Posts 3 Posters 394 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    Teni
    wrote on last edited by Teni
    #1

    Hello everyone,

    I’m using Qt version 6.5.3 and have encountered a tricky issue that I hope the community can help with.

    I’ve wrapped my Qt frontend code in a DLL and use the following approach to load it in my main program:

    QStackedLayout *pluginview_layout = window->findChild<QStackedLayout*>("pluginview_layout");
    

    Everything works fine when loading a typical Qt interface. However, I ran into an issue when embedding another independent Qt application into my main program using the createMainWindowStyle function.

    Here’s what I’ve observed:

    When embedding a non-Qt application, everything works as expected, and the window is successfully embedded and displayed.
    When embedding a Qt application, although the window capture seems to succeed, it fails to display after being added to the pluginview_layout.
    To investigate, I checked the following variables:

    QWindow *exe_window = QWindow::fromWinId(winId);
    QWidget *plugin_widget = QWidget::createWindowContainer(exe_window);
    

    Both variables are not null, which suggests the window was captured successfully. However, after adding plugin_widget to the pluginview_layout, the window does not appear.

    Has anyone encountered a similar issue or have any suggestions on how to debug this?

    This is my code:

    typedef QMainWindow* (*GetMainwindowStyleFunc)();
    typedef const QString (*GetStyleSecretKeyFunc)();
    
    QStringList get_dll_files(const QDir &dir) {
        QStringList dll_files;
        QFileInfoList sub_dirs = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
        QStringList dll_file_names = dir.entryList(QStringList() << "*.dll", QDir::Files);
    
        for (const QString &file_name : dll_file_names) {
            QFileInfo file_info(file_name);
            dll_files.append(file_info.completeBaseName());
        }
    
        for (const QFileInfo &sub_dir : sub_dirs) {
            QDir child_dir(sub_dir.absoluteFilePath());
            dll_files.append(get_dll_files(child_dir));
        }
    
        return dll_files;
    }
    
    void find_exe(QStringList exe_plugin_files, QLayout* layout)
    {
        foreach (QString plugin_file, exe_plugin_files) {
            // List to store QProcess objects
            QList<QProcess*> processList;
            // 1. Create and start external program
            QProcess *process = new QProcess();
            processList.append(process);  // Store QProcess in the list to avoid destruction
            process->start(plugin_file);
    
            if (!process->waitForStarted()) {
                qDebug() << "Failed to start process:" << plugin_file;
                continue;
            }
    
            // 2. Construct .ini file path
            QFileInfo fileInfo(plugin_file);
            QString ini_file = fileInfo.absolutePath() + "/" + fileInfo.baseName() + ".ini";
    
            // 3. Check if .ini file exists
            if (!QFile::exists(ini_file)) {
                qDebug() << "INI file does not exist:" << ini_file;
                continue;
            }
    
            // 4. Read the plugin_info section from the .ini file
            QSettings settings(ini_file, QSettings::IniFormat);
            settings.beginGroup("plugin_info");
            QString plugin_name = settings.value("get_plugin_name", "").toString();
            settings.endGroup();
    
            if (plugin_name.isEmpty()) {
                qDebug() << "Window title (get_plugin_name) not found in INI file.";
                continue;
            }
    
            // 5. Create a timer to check if the window loads every 3 seconds
            QTimer *timer = new QTimer();
            int elapsed_time = 0;  // Record total check time
    
            QObject::connect(timer, &QTimer::timeout, [=, &elapsed_time]() mutable {
                // Find window handle (WinId)
                WId winId = (WId)FindWindow(NULL, (LPCWSTR)plugin_name.utf16());
                if (winId != 0) {
                    qDebug() << "Found window with title:" << plugin_name;
    
                    // 6. Embed the window into the Qt widget
                    QWindow *window = QWindow::fromWinId(winId);
                    QWidget *plugin_widget = QWidget::createWindowContainer(window);
    
                    // 7. Create button and connect signals and slots
                    QPushButton *button = new QPushButton(plugin_name);
                    button->setFixedHeight(40);
                    layout->addWidget(button);
                    layout->addWidget(plugin_widget);
    
                    // Stop the timer
                    timer->stop();
                    return;
                }
    
                // Update check time
                elapsed_time += 3000;  // Each timeout is 3 seconds
                if (elapsed_time >= 30000) {  // Stop checking after 30 seconds
                    qDebug() << "Failed to find window within 30 seconds for plugin:" << plugin_name;
                    timer->stop();
                }
            });
    
            // Start the timer to check every 3 seconds
            timer->start(3000);
        }
    
    }
    
    int main(int argc, char *argv[]) {
        QApplication a(argc, argv);
        QLibrary library;
        QMainWindow* window;
        QDir app_dir(QFileInfo(QCoreApplication::applicationDirPath()).absolutePath() + "/..");
        QDir mainWindowDir = app_dir;
        QString dll_name = "technology";
        mainWindowDir.cd("mainwindow_styles/" + dll_name);
        QString dllPath = mainWindowDir.absoluteFilePath(dll_name + ".dll");
        library.setFileName(dllPath);
        GetMainwindowStyleFunc createMainWindowStyle = (GetMainwindowStyleFunc)library.resolve("get_mainwindow_style");
        window = createMainWindowStyle();
    
    
        QStackedLayout *pluginview_layout = window->findChild<QStackedLayout*>("pluginview_layout");
        QLayout *pluginlist_layout = window->findChild<QLayout*>("pluginlist_layout");
    
        // QWidget *window_Widget = new QWidget();
        // QStackedLayout *pluginview_layout = new QStackedLayout(window_Widget);
    
    
        // Add paths to QStringList
        QStringList exe_plugin_files;
        exe_plugin_files << "C:\\Users\\Ling\\Desktop\\RCMSrelease\\RCMS_Release\\plugins\\exe\\test.exe";
    
        QWidget *VWidget = new QWidget();
        QVBoxLayout *Vlayout = new QVBoxLayout(VWidget);
    
    
        find_exe(exe_plugin_files, Vlayout);
    
    
        pluginview_layout->addWidget(VWidget);
    
        pluginview_layout->setCurrentWidget(VWidget);
    
    
        window->show();
        QCoreApplication::processEvents();
        return a.exec();
    }
    
    Pl45m4P 1 Reply Last reply
    0
    • T Teni

      Hello everyone,

      I’m using Qt version 6.5.3 and have encountered a tricky issue that I hope the community can help with.

      I’ve wrapped my Qt frontend code in a DLL and use the following approach to load it in my main program:

      QStackedLayout *pluginview_layout = window->findChild<QStackedLayout*>("pluginview_layout");
      

      Everything works fine when loading a typical Qt interface. However, I ran into an issue when embedding another independent Qt application into my main program using the createMainWindowStyle function.

      Here’s what I’ve observed:

      When embedding a non-Qt application, everything works as expected, and the window is successfully embedded and displayed.
      When embedding a Qt application, although the window capture seems to succeed, it fails to display after being added to the pluginview_layout.
      To investigate, I checked the following variables:

      QWindow *exe_window = QWindow::fromWinId(winId);
      QWidget *plugin_widget = QWidget::createWindowContainer(exe_window);
      

      Both variables are not null, which suggests the window was captured successfully. However, after adding plugin_widget to the pluginview_layout, the window does not appear.

      Has anyone encountered a similar issue or have any suggestions on how to debug this?

      This is my code:

      typedef QMainWindow* (*GetMainwindowStyleFunc)();
      typedef const QString (*GetStyleSecretKeyFunc)();
      
      QStringList get_dll_files(const QDir &dir) {
          QStringList dll_files;
          QFileInfoList sub_dirs = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
          QStringList dll_file_names = dir.entryList(QStringList() << "*.dll", QDir::Files);
      
          for (const QString &file_name : dll_file_names) {
              QFileInfo file_info(file_name);
              dll_files.append(file_info.completeBaseName());
          }
      
          for (const QFileInfo &sub_dir : sub_dirs) {
              QDir child_dir(sub_dir.absoluteFilePath());
              dll_files.append(get_dll_files(child_dir));
          }
      
          return dll_files;
      }
      
      void find_exe(QStringList exe_plugin_files, QLayout* layout)
      {
          foreach (QString plugin_file, exe_plugin_files) {
              // List to store QProcess objects
              QList<QProcess*> processList;
              // 1. Create and start external program
              QProcess *process = new QProcess();
              processList.append(process);  // Store QProcess in the list to avoid destruction
              process->start(plugin_file);
      
              if (!process->waitForStarted()) {
                  qDebug() << "Failed to start process:" << plugin_file;
                  continue;
              }
      
              // 2. Construct .ini file path
              QFileInfo fileInfo(plugin_file);
              QString ini_file = fileInfo.absolutePath() + "/" + fileInfo.baseName() + ".ini";
      
              // 3. Check if .ini file exists
              if (!QFile::exists(ini_file)) {
                  qDebug() << "INI file does not exist:" << ini_file;
                  continue;
              }
      
              // 4. Read the plugin_info section from the .ini file
              QSettings settings(ini_file, QSettings::IniFormat);
              settings.beginGroup("plugin_info");
              QString plugin_name = settings.value("get_plugin_name", "").toString();
              settings.endGroup();
      
              if (plugin_name.isEmpty()) {
                  qDebug() << "Window title (get_plugin_name) not found in INI file.";
                  continue;
              }
      
              // 5. Create a timer to check if the window loads every 3 seconds
              QTimer *timer = new QTimer();
              int elapsed_time = 0;  // Record total check time
      
              QObject::connect(timer, &QTimer::timeout, [=, &elapsed_time]() mutable {
                  // Find window handle (WinId)
                  WId winId = (WId)FindWindow(NULL, (LPCWSTR)plugin_name.utf16());
                  if (winId != 0) {
                      qDebug() << "Found window with title:" << plugin_name;
      
                      // 6. Embed the window into the Qt widget
                      QWindow *window = QWindow::fromWinId(winId);
                      QWidget *plugin_widget = QWidget::createWindowContainer(window);
      
                      // 7. Create button and connect signals and slots
                      QPushButton *button = new QPushButton(plugin_name);
                      button->setFixedHeight(40);
                      layout->addWidget(button);
                      layout->addWidget(plugin_widget);
      
                      // Stop the timer
                      timer->stop();
                      return;
                  }
      
                  // Update check time
                  elapsed_time += 3000;  // Each timeout is 3 seconds
                  if (elapsed_time >= 30000) {  // Stop checking after 30 seconds
                      qDebug() << "Failed to find window within 30 seconds for plugin:" << plugin_name;
                      timer->stop();
                  }
              });
      
              // Start the timer to check every 3 seconds
              timer->start(3000);
          }
      
      }
      
      int main(int argc, char *argv[]) {
          QApplication a(argc, argv);
          QLibrary library;
          QMainWindow* window;
          QDir app_dir(QFileInfo(QCoreApplication::applicationDirPath()).absolutePath() + "/..");
          QDir mainWindowDir = app_dir;
          QString dll_name = "technology";
          mainWindowDir.cd("mainwindow_styles/" + dll_name);
          QString dllPath = mainWindowDir.absoluteFilePath(dll_name + ".dll");
          library.setFileName(dllPath);
          GetMainwindowStyleFunc createMainWindowStyle = (GetMainwindowStyleFunc)library.resolve("get_mainwindow_style");
          window = createMainWindowStyle();
      
      
          QStackedLayout *pluginview_layout = window->findChild<QStackedLayout*>("pluginview_layout");
          QLayout *pluginlist_layout = window->findChild<QLayout*>("pluginlist_layout");
      
          // QWidget *window_Widget = new QWidget();
          // QStackedLayout *pluginview_layout = new QStackedLayout(window_Widget);
      
      
          // Add paths to QStringList
          QStringList exe_plugin_files;
          exe_plugin_files << "C:\\Users\\Ling\\Desktop\\RCMSrelease\\RCMS_Release\\plugins\\exe\\test.exe";
      
          QWidget *VWidget = new QWidget();
          QVBoxLayout *Vlayout = new QVBoxLayout(VWidget);
      
      
          find_exe(exe_plugin_files, Vlayout);
      
      
          pluginview_layout->addWidget(VWidget);
      
          pluginview_layout->setCurrentWidget(VWidget);
      
      
          window->show();
          QCoreApplication::processEvents();
          return a.exec();
      }
      
      Pl45m4P Offline
      Pl45m4P Offline
      Pl45m4
      wrote on last edited by Pl45m4
      #2

      Hi @Teni ,

      first thing that jumped right in my face:

      @Teni said in Issue with Embedding Qt Window into QStackedLayout Using DLL:

      foreach (QString plugin_file, exe_plugin_files) {
          // List to store QProcess objects
          QList<QProcess*> processList;
          // 1. Create and start external program
          QProcess *process = new QProcess();
          processList.append(process);  // Store QProcess in the list to avoid destruction
          // .....
          // ....
       }
      

      What?!
      On every iteration you create a new local list of QProcess* in the same scope as your process and append the actual pointer to it "to avoid (its) destruction"?!
      And you don't even use that list ever?!

      Am I the only one to find this strange?!

      Both variables are not null, which suggests the window was captured successfully

      They are not null, but do they load correctly?!
      Is the QLibrary instance alive at all time?
      What does your QMainWindow window contain?!

      When embedding a Qt application, although the window capture seems to succeed, it fails to display after being added to the pluginview_layout.
      To investigate, I checked the following variables:

      QWindow *exe_window = QWindow::fromWinId(winId);
      QWidget *plugin_widget = QWidget::createWindowContainer(exe_window);
      

      Haven't done it myself this way, but maybe this thread on StackOverflow helps:

      • https://stackoverflow.com/questions/40348044/executing-a-qt-application-inside-qt-application

      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

      ~E. W. Dijkstra

      T 2 Replies Last reply
      0
      • Pl45m4P Pl45m4

        Hi @Teni ,

        first thing that jumped right in my face:

        @Teni said in Issue with Embedding Qt Window into QStackedLayout Using DLL:

        foreach (QString plugin_file, exe_plugin_files) {
            // List to store QProcess objects
            QList<QProcess*> processList;
            // 1. Create and start external program
            QProcess *process = new QProcess();
            processList.append(process);  // Store QProcess in the list to avoid destruction
            // .....
            // ....
         }
        

        What?!
        On every iteration you create a new local list of QProcess* in the same scope as your process and append the actual pointer to it "to avoid (its) destruction"?!
        And you don't even use that list ever?!

        Am I the only one to find this strange?!

        Both variables are not null, which suggests the window was captured successfully

        They are not null, but do they load correctly?!
        Is the QLibrary instance alive at all time?
        What does your QMainWindow window contain?!

        When embedding a Qt application, although the window capture seems to succeed, it fails to display after being added to the pluginview_layout.
        To investigate, I checked the following variables:

        QWindow *exe_window = QWindow::fromWinId(winId);
        QWidget *plugin_widget = QWidget::createWindowContainer(exe_window);
        

        Haven't done it myself this way, but maybe this thread on StackOverflow helps:

        • https://stackoverflow.com/questions/40348044/executing-a-qt-application-inside-qt-application
        T Offline
        T Offline
        Teni
        wrote on last edited by Teni
        #3

        @Pl45m4 said in Issue with Embedding Qt Window into QStackedLayout Using DLL:

        "to avoid (its) destruction"

        First of all, thank you very much for taking the time to look into and respond to my issue.

        Regarding the processList, you're absolutely right—it does seem odd, and no one would create a list that's never used. The truth is, this was a fix suggestion from an AI because the program I need to embed starts very slowly. Even after a full iteration of the foreach loop, the program hasn’t launched yet, and by the time the loop finishes, the process object is destroyed. That’s why I added this “to avoid (its) destruction” step. Of course, I know there's a more elegant solution, but my main focus right now is on solving the issue of embedding the Qt program. When I was able to successfully embed an Electron app, I realized the problem isn't in this part of the code.

        The error I encountered is:

        QProcess: Destroyed while process ("C:\\Users\\Ling\\Desktop\\RCMSrelease\\RCMS_Release\\plugins\\exe\\test.exe") is still running.
        

        As for the two variables being non-null, this is because when I tested embedding non-Qt applications, everything displayed properly. Strangely, programs built with Qt and PySide don’t load properly through the "mainwindow loaded via DLL" process, but when I define the mainwindow in int main, it displays correctly. This confused me, so I checked if these two variables successfully captured the winID and converted it to a QWidget when dealing with Qt/PySide apps. It turns out they were captured and converted correctly. I could see in the Windows Task Manager that the program I wanted to embed was active.

        Regarding what my Library contains, it's actually quite simple:

        extern "C" TECHNOLOGY_EXPORT QMainWindow* get_mainwindow_style() 
        {
            return new Technology();
        }
        

        I’ve defined an interface like this. The Technology class inherits from QMainWindow. In the Technology class, I’ve created some layouts like main_layout and dockbar_layout, along with other window decorations.

        As long as the main program instantiates this Technology plugin through the interface, it can directly create the QMainWindow I’ve designed. Using

        findChild<QLayout*>("")
        

        I can retrieve the pre-created main_layout and dockbar_layout from Technology and place the desired functional widgets inside them.

        To put it simply, I’ve separated the logic and the window design.

        #include "technology.h"
        
        Technology::Technology(QWidget *parent) : FramelessWindow(parent)
        {
            setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowTitleHint);
            setAttribute(Qt::WA_TranslucentBackground);
            QWidget *main_widget = new QWidget(this);
            QHBoxLayout *main_layout = new QHBoxLayout(main_widget);
        
            main_widget->setObjectName("main_widget");
            main_widget->setStyleSheet("#main_widget {border-radius: 8px;}"
                                       "#dockbar_wiget {border-top-left-radius: 8px;}"
                                       "#dockbar_wiget {border-bottom-left-radius: 8px;}"
                                       "#workspace_widget {border-top-right-radius: 8px;}"
                                       "#workspace_widget {border-bottom-right-radius: 8px;}");
        
            QWidget *dockbar_wiget = new QWidget();
            QWidget *workspace_widget = new QWidget();
        
            dockbar_wiget->setObjectName("dockbar_wiget");
            workspace_widget->setObjectName("workspace_widget");
        
            dockbar_wiget->setStyleSheet("#dockbar_wiget {background-color: #6A6F84;}");
            workspace_widget->setStyleSheet("#workspace_widget {background-color: #3D3F47;}");
        
            dockbar_layout = new QVBoxLayout(dockbar_wiget);
            workspace_layout = new QVBoxLayout(workspace_widget);
        
            dockbar_wiget->setMaximumWidth(200);
        
            main_layout->addWidget(dockbar_wiget, 2);
            main_layout->addWidget(workspace_widget, 8);
        
            build_dockbar();
            build_workspace();
        
            setCentralWidget(main_widget);
        
            main_layout->setSpacing(0);
            main_layout->setContentsMargins(0, 0, 0, 0);
        }
        
        void Technology::build_dockbar()
        {
            DraggableWidget *appinfo_widget = new DraggableWidget(this);
            QWidget *userinfo_widget = new QWidget();
            QWidget *pluginlist_widget = new QWidget();
        
            QScrollArea *pluginlist_scrollarea = new QScrollArea();
            pluginlist_scrollarea->setWidget(pluginlist_widget);
            pluginlist_scrollarea->setWidgetResizable(true);
        
            dockbar_layout->addWidget(appinfo_widget, 1);
            dockbar_layout->addWidget(userinfo_widget, 1);
            dockbar_layout->addWidget(pluginlist_scrollarea, 8);
        
            appinfo_widget->setFixedHeight(40);
        
            QHBoxLayout *appinfo_layout = new QHBoxLayout(appinfo_widget);
            QHBoxLayout *userinfo_layout = new QHBoxLayout(userinfo_widget);
            QVBoxLayout *pluginlist_layout = new QVBoxLayout(pluginlist_widget);
            pluginlist_layout->setObjectName(QString("pluginlist_layout"));
        
            pluginlist_layout->setAlignment(Qt::AlignTop);
        
            pluginlist_widget->setObjectName("pluginlist_widget");
            pluginlist_widget->setStyleSheet("#pluginlist_widget { background: transparent; border: none; }");
        
            pluginlist_scrollarea->setObjectName("pluginlist_scrollarea");
            pluginlist_scrollarea->setStyleSheet("#pluginlist_scrollarea { background: transparent; border: none; }");
        
            QPushButton *logo_placeholder = new QPushButton("MS");
            logo_placeholder->setFixedSize(40, 40);
            QLabel *appname_label = new QLabel("MS");
            QLabel *userpre_label = new QLabel("Uesr");
        
            appname_label->setObjectName(QString("appname_label"));
            userpre_label->setObjectName(QString("userpre"));
        
            appname_label->setStyleSheet("font-size: 11pt; color: white;");
            userpre_label->setStyleSheet("font-size: 12pt; color: white;");
        
            appname_label->setAlignment(Qt::AlignCenter);
            userpre_label->setAlignment(Qt::AlignCenter);
        
            appinfo_layout->addWidget(logo_placeholder);
            appinfo_layout->addWidget(appname_label);
            userinfo_layout->addWidget(userpre_label);
        
            appinfo_layout->setSpacing(0);
            pluginlist_layout->setSpacing(10);
            appinfo_layout->setContentsMargins(0, 0, 0, 0);
            pluginlist_layout->setContentsMargins(0, 0, 0, 0);
        }
        
        JonBJ 1 Reply Last reply
        0
        • Pl45m4P Pl45m4

          Hi @Teni ,

          first thing that jumped right in my face:

          @Teni said in Issue with Embedding Qt Window into QStackedLayout Using DLL:

          foreach (QString plugin_file, exe_plugin_files) {
              // List to store QProcess objects
              QList<QProcess*> processList;
              // 1. Create and start external program
              QProcess *process = new QProcess();
              processList.append(process);  // Store QProcess in the list to avoid destruction
              // .....
              // ....
           }
          

          What?!
          On every iteration you create a new local list of QProcess* in the same scope as your process and append the actual pointer to it "to avoid (its) destruction"?!
          And you don't even use that list ever?!

          Am I the only one to find this strange?!

          Both variables are not null, which suggests the window was captured successfully

          They are not null, but do they load correctly?!
          Is the QLibrary instance alive at all time?
          What does your QMainWindow window contain?!

          When embedding a Qt application, although the window capture seems to succeed, it fails to display after being added to the pluginview_layout.
          To investigate, I checked the following variables:

          QWindow *exe_window = QWindow::fromWinId(winId);
          QWidget *plugin_widget = QWidget::createWindowContainer(exe_window);
          

          Haven't done it myself this way, but maybe this thread on StackOverflow helps:

          • https://stackoverflow.com/questions/40348044/executing-a-qt-application-inside-qt-application
          T Offline
          T Offline
          Teni
          wrote on last edited by Teni
          #4

          @Pl45m4 said in Issue with Embedding Qt Window into QStackedLayout Using DLL:

          https://stackoverflow.com/questions/40348044/executing-a-qt-application-inside-qt-application

          I've attempted to follow the method suggested on StackOverflow, but unfortunately, I still haven't been able to resolve the issue. Despite my best efforts, the embedding process for the Qt application remains unsuccessful. If you have any further suggestions or insights, I would greatly appreciate your guidance. Thank you!

          1 Reply Last reply
          0
          • T Teni

            @Pl45m4 said in Issue with Embedding Qt Window into QStackedLayout Using DLL:

            "to avoid (its) destruction"

            First of all, thank you very much for taking the time to look into and respond to my issue.

            Regarding the processList, you're absolutely right—it does seem odd, and no one would create a list that's never used. The truth is, this was a fix suggestion from an AI because the program I need to embed starts very slowly. Even after a full iteration of the foreach loop, the program hasn’t launched yet, and by the time the loop finishes, the process object is destroyed. That’s why I added this “to avoid (its) destruction” step. Of course, I know there's a more elegant solution, but my main focus right now is on solving the issue of embedding the Qt program. When I was able to successfully embed an Electron app, I realized the problem isn't in this part of the code.

            The error I encountered is:

            QProcess: Destroyed while process ("C:\\Users\\Ling\\Desktop\\RCMSrelease\\RCMS_Release\\plugins\\exe\\test.exe") is still running.
            

            As for the two variables being non-null, this is because when I tested embedding non-Qt applications, everything displayed properly. Strangely, programs built with Qt and PySide don’t load properly through the "mainwindow loaded via DLL" process, but when I define the mainwindow in int main, it displays correctly. This confused me, so I checked if these two variables successfully captured the winID and converted it to a QWidget when dealing with Qt/PySide apps. It turns out they were captured and converted correctly. I could see in the Windows Task Manager that the program I wanted to embed was active.

            Regarding what my Library contains, it's actually quite simple:

            extern "C" TECHNOLOGY_EXPORT QMainWindow* get_mainwindow_style() 
            {
                return new Technology();
            }
            

            I’ve defined an interface like this. The Technology class inherits from QMainWindow. In the Technology class, I’ve created some layouts like main_layout and dockbar_layout, along with other window decorations.

            As long as the main program instantiates this Technology plugin through the interface, it can directly create the QMainWindow I’ve designed. Using

            findChild<QLayout*>("")
            

            I can retrieve the pre-created main_layout and dockbar_layout from Technology and place the desired functional widgets inside them.

            To put it simply, I’ve separated the logic and the window design.

            #include "technology.h"
            
            Technology::Technology(QWidget *parent) : FramelessWindow(parent)
            {
                setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowTitleHint);
                setAttribute(Qt::WA_TranslucentBackground);
                QWidget *main_widget = new QWidget(this);
                QHBoxLayout *main_layout = new QHBoxLayout(main_widget);
            
                main_widget->setObjectName("main_widget");
                main_widget->setStyleSheet("#main_widget {border-radius: 8px;}"
                                           "#dockbar_wiget {border-top-left-radius: 8px;}"
                                           "#dockbar_wiget {border-bottom-left-radius: 8px;}"
                                           "#workspace_widget {border-top-right-radius: 8px;}"
                                           "#workspace_widget {border-bottom-right-radius: 8px;}");
            
                QWidget *dockbar_wiget = new QWidget();
                QWidget *workspace_widget = new QWidget();
            
                dockbar_wiget->setObjectName("dockbar_wiget");
                workspace_widget->setObjectName("workspace_widget");
            
                dockbar_wiget->setStyleSheet("#dockbar_wiget {background-color: #6A6F84;}");
                workspace_widget->setStyleSheet("#workspace_widget {background-color: #3D3F47;}");
            
                dockbar_layout = new QVBoxLayout(dockbar_wiget);
                workspace_layout = new QVBoxLayout(workspace_widget);
            
                dockbar_wiget->setMaximumWidth(200);
            
                main_layout->addWidget(dockbar_wiget, 2);
                main_layout->addWidget(workspace_widget, 8);
            
                build_dockbar();
                build_workspace();
            
                setCentralWidget(main_widget);
            
                main_layout->setSpacing(0);
                main_layout->setContentsMargins(0, 0, 0, 0);
            }
            
            void Technology::build_dockbar()
            {
                DraggableWidget *appinfo_widget = new DraggableWidget(this);
                QWidget *userinfo_widget = new QWidget();
                QWidget *pluginlist_widget = new QWidget();
            
                QScrollArea *pluginlist_scrollarea = new QScrollArea();
                pluginlist_scrollarea->setWidget(pluginlist_widget);
                pluginlist_scrollarea->setWidgetResizable(true);
            
                dockbar_layout->addWidget(appinfo_widget, 1);
                dockbar_layout->addWidget(userinfo_widget, 1);
                dockbar_layout->addWidget(pluginlist_scrollarea, 8);
            
                appinfo_widget->setFixedHeight(40);
            
                QHBoxLayout *appinfo_layout = new QHBoxLayout(appinfo_widget);
                QHBoxLayout *userinfo_layout = new QHBoxLayout(userinfo_widget);
                QVBoxLayout *pluginlist_layout = new QVBoxLayout(pluginlist_widget);
                pluginlist_layout->setObjectName(QString("pluginlist_layout"));
            
                pluginlist_layout->setAlignment(Qt::AlignTop);
            
                pluginlist_widget->setObjectName("pluginlist_widget");
                pluginlist_widget->setStyleSheet("#pluginlist_widget { background: transparent; border: none; }");
            
                pluginlist_scrollarea->setObjectName("pluginlist_scrollarea");
                pluginlist_scrollarea->setStyleSheet("#pluginlist_scrollarea { background: transparent; border: none; }");
            
                QPushButton *logo_placeholder = new QPushButton("MS");
                logo_placeholder->setFixedSize(40, 40);
                QLabel *appname_label = new QLabel("MS");
                QLabel *userpre_label = new QLabel("Uesr");
            
                appname_label->setObjectName(QString("appname_label"));
                userpre_label->setObjectName(QString("userpre"));
            
                appname_label->setStyleSheet("font-size: 11pt; color: white;");
                userpre_label->setStyleSheet("font-size: 12pt; color: white;");
            
                appname_label->setAlignment(Qt::AlignCenter);
                userpre_label->setAlignment(Qt::AlignCenter);
            
                appinfo_layout->addWidget(logo_placeholder);
                appinfo_layout->addWidget(appname_label);
                userinfo_layout->addWidget(userpre_label);
            
                appinfo_layout->setSpacing(0);
                pluginlist_layout->setSpacing(10);
                appinfo_layout->setContentsMargins(0, 0, 0, 0);
                pluginlist_layout->setContentsMargins(0, 0, 0, 0);
            }
            
            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by
            #5

            @Teni said in Issue with Embedding Qt Window into QStackedLayout Using DLL:

            The error I encountered is:

            QProcess: Destroyed while process ("C:\Users\Ling\Desktop\RCMSrelease\RCMS_Release\plugins\exe\test.exe") is still running.

            If this is your only question/issue now we can surely help with that.

            However there is no point if this is a side-show to your main issue of "embedding" the sub-process window in your parent. For that I don't know. If you wish to pursue this I would start by testing the accepted solution there as a standalone program without any of your stuff. If that works try adapting to your situation. For my part I don't use Windows and I don't know what issues DLLs may cause.

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved