Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Showing custom popup dialog from c++



  • Hi,

    I'm trying to add a general way of showing popup dialogs, messageboxes, settingswindows in my application. I have a function showPopupDialog(const std::string& sourceQMLFile) which should handle this.
    My popup dialogs/messageboxes/... are all implemented in seperate qml files. They have a custom look and feel (Their root item is a Rectangle, not a Window or a Dialog).

    If I do:

    appContect->showPopupDialog("qrc///TestDialog.qml");
    

    with:

    void ApplicationContext::showPopupDialog(const std::string& sourceQMLFile)
    {
    	if(_engine)
    	{
    		QQuickWindow* itm = qobject_cast<QQuickWindow*>(_engine->rootObjects().value(0));
    		if(itm)
    		{
    			QQmlComponent component(_engine, QUrl(QString::fromStdString(sourceQMLFile)));
    			QObject* childItem = qobject_cast<QObject*>(component.create());
    			childItem->setParent(itm);
    		}
    	}	
    }
    

    and TestDialog.qml:

    import QtQuick 2.0
    
    Rectangle {
        width: 100;
    	height: 100;
    	color: "Red";
    	visible: true;
    }
    

    I don't see anything. If I change in the TestDialog.qml the Rectangle with a Dialog, it shows me a dialog, but I don't want to have the standard frame/framebuttons/title. What Am I doing wrong? How can I best load my custom dialogs/messageboxes? Or should I better use a dialog/window as a rootitem (but then i want to have it frameless)?
    Regards,

    Jan



  • Setting a (non-visual) parent object is not enough to make a QQuickItem visible. You must set a (visual) parent item. It can be the window's content item, or any other item that is in the window.

    QQuickItem* childItem = qobject_cast<QQuickItem*>(component.create());
    if (childItem)
        childItem->setParentItem(window->contentItem());
    


  • Changed the loading code to:

    void ApplicationContext::showPopupDialog(const std::string& source)
    {
    	if(_engine)
    	{
    		QQuickWindow* itm = qobject_cast<QQuickWindow*>(_engine->rootObjects().value(0));
    		if(itm)
    		{
    			QQmlComponent component(_engine, QUrl(QString::fromStdString(source)));
    			QObject* childItem = qobject_cast<QObject*>(component.create());
    			if(childItem)
    			{
    				childItem->setParent(itm->contentItem());
    			}			
    		}
    	}	
    }
    

    and the TestDialog.qml to

    import QtQuick 2.0
    
    Rectangle {
    	x: 0;
    	y: 0;
        width: 1000;
    	height: 1000;
    	color: "Red";
    	visible: true;
    
    	Component.onCompleted:
    	{
    		console.log("TestDialog loaded");
    	}
    }
    

    Maybe important info:
    My main.cpp:

    _engine = new QQmlApplicationEngine();
    ...
    _engine->load(QUrl(QStringLiteral("qrc:/MainWindow.qml")));
    

    and my MainWindow.qml

    import QtQuick 2.3
    import QtQuick.Controls 1.4
    import QtQuick.Layouts 1.2
    import QtQuick.Window 2.2
    
    Window
    {
    	id: mainWindow;
    
    	property var logo: "qrc:///logo.png";
    	property var applicationName: "Application";
    	property var projectName: "Untitled";
    
    	width: 800;
    	height: 600;
    	visible: false;
    
    	flags: Qt.FramelessWindowHint | Qt.WindowMinimizeButtonHint | Qt.WindowSystemMenuHint | Qt.Window;
    
    ...
    
    	Component.onCompleted: mainWindow.showMaximized();
    }
    
    

    But still nothing when I try to show the TestDialog (my console output shows qml: TestDialog loaded, so i assume the item is loaded correctly...). It's not because the QQmlComponent gets out of scope, right? (tried to change it to a pointer, but no difference).



  • You are still calling QObject::setParent() instead of QQuickItem::setParentItem().



  • Wow, I should read the answers more carefully. It works now, Thanks!

    Jan


Log in to reply