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

why QWidget inherited class can't handle QAction ?



  • Hello,

    While developping a small application, i faced a weird behavior concerning QAction. Why a QWidget inherited class cannot handle a QAction ? I made a small example to illustrate my problem:

    a.h

    #include <QObject>
    #include <QWidget>
    #include <QMainWindow>
    #include <QMenuBar>
    #include <QMenu>
    #include <QAction>
    
    using BaseClass = QObject;
    
    class A : public BaseClass
    {
    	Q_OBJECT
    
    public:
    
    	A(QMainWindow& mw) : BaseClass(&mw), m_menu("A"), m_action("a")
    	{
    		m_menu.addAction(&m_action);
    
    		mw.menuBar()->addMenu(&m_menu);
    	}
    
    private:
    
    	QMenu m_menu;
    	QAction m_action;
    
    };
    

    main.cpp

    #include <QApplication>
    #include <QMainWindow>
    #include <QMenuBar>
    #include <QMenu>
    #include <QAction>
    
    #include "a.h"
    
    int main(int argc, char* argv[])
    {
    	QApplication app(argc, argv);
    
    	QMainWindow mw;
    
    	QAction quitAction("Quit");
    	QMenu fileMenu("File");
    	fileMenu.addAction(&quitAction);
    	mw.menuBar()->addMenu(&fileMenu);
    
    	A a(mw);
    
    	mw.show();
    
    	return app.exec();
    }
    

    In the a.h file, when I replace QObject by QWidget for the using BaseClass, the menuBar is not working anymore, I cannot click on any menus. Why ? 0_o

    I searched in the documentation but i did not find any information...

    Thanks in advance !


  • Lifetime Qt Champion

    Hi,

    That's a good question however I can't answer right away.

    That said, your code as it is does not really follow best practices in terms of handling QObject based classes so I am wondering if there's some bad interaction there.


  • Moderators

    It's because of this part:

    BaseClass(&mw),
    

    Setting a parent on a widget adds that widget to the parent, so you just added A widget to your main window. Because it's not in any layout it sits in the top left corner, covering the menus (that's why you can't click any). It's transparent though so you can't see it.
    Add a paint event like this to your A class to see what I mean:

    void paintEvent(QPaintEvent*)
    {
        QPainter p(this);
        p.fillRect(rect(), Qt::red);
    }
    

  • Lifetime Qt Champion

    @Chris-Kawa good catch ! I went for "non-clickable" rather than "hidden by".



  • @SGaist Thanks for the reply ! Concerning the best practices for handling QObject, do you have any ressources regrouping informations ? Or I can find them along the Qt documentation.

    I use Qt also in my company and I make projects alongside in my personal time to improve my skills. I find Qt hard to handle if you don't want to use raw pointers to follow c++ core guideline or something similar for example. I will be grateful if you could link me some materials :)


  • Lifetime Qt Champion

    You have a truck load of examples in Qt's documentation.
    That said it looks like you are trying to work against Qt's parent/child and QObject design by making everything stack based. Trying to keep absolutely everything on the stack will have issues like double deletion happening with properly parented objects. Making everything allocated on the heap is wrong as well. You should learn when to use which so your tool belt will be more complete.



  • @Chris-Kawa Thanks ! It makes sense now ^^

    In my application, I decided to use a MVC like approach with a Gui class inheriting QWidget (so I can make it dockable) to handle and the UI generated by QtDesigner (or manually made) and elements like actions to put in menuBar of the main window. I think it is now compromised...

    Do you have any idea of how to handle that ?

    Edit: Well no I can do it anyway, I just need to hide the widget and it works...



  • @SGaist Yes, I find ugly and so outdated the use of raw pointers. I think I have to back off and keep it to myself ^^.
    Fingers crossed for a better approach in Qt6...


  • Lifetime Qt Champion

    You can uncross them. Raw pointers are not going anywhere.


Log in to reply