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. What is more efficient for custom widget: Re-implementing protected QEvent functions or chaining signals?
QtWS25 Last Chance

What is more efficient for custom widget: Re-implementing protected QEvent functions or chaining signals?

Scheduled Pinned Locked Moved Solved General and Desktop
10 Posts 4 Posters 651 Views
  • 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.
  • Petross404_Petros SP Offline
    Petross404_Petros SP Offline
    Petross404_Petros S
    wrote on last edited by Petross404_Petros S
    #1

    Hello to all. I am subclassing a QPushButton as PushButton like this:

    class Shape //irrelevant for now
    
    class PushButton : public QPushButton
    {
            Q_OBJECT
    
    public:
            explicit PushButton( QWidget* parent, Shape* shape);
    ....
    signals:
    	//! Custom signal to emit the clicked PushButton into slots
    	/*!
    	 * The classic `QPushButton::clicked(bool)` is not sufficient in this case.
    	 * We need a signal that will cary the `PushButton*` that triggered it.
    	 */
    	void pbtnClicked( PushButton* pbtn );
    };
    

    I need to use pbtnClicked signal to pass the PushButton* (ie the this that was clicked) parameter in the ctor of another object.

    I am thinking of two ways to do this:

    A) Chaining signals like:

    // pushbutton.cpp
    PushButton::PushButton( QWidget* parent, Shape* shape )
    	: QPushButton{ dynamic_cast<QWidget*>( parent ) }
    	, m_shape{ new Shape*( shape ) }
    {
    ...
    	connect(
    		this,
    		&PushButton::clicked,  //chain the inherited functionality
    		this,
    		[this]() -> void { emit pbtnClicked( this ); }, // to the custom signal
    		Qt::DirectConnection );
    }
    

    or B) by using the event system like:

    // Ok, this doesn't work if PushButton was clicked with the enter key
    bool PushButton::eventFilter( QObject* watched, QEvent* event )
    {
    	// The watched object has to be a PushButton* (ie *this* PushButton)
    	if ( watched == this && event->type() == QEvent::MouseButtonRelease )
    	{
    		auto* mouseEvent = dynamic_cast<QMouseEvent*>( event );
    		if ( mouseEvent->button() == Qt::MouseButton::LeftButton )
    		{
    			emit pbtnClicked( this );
    			return true;
    		}
    	}
    	return false;
    	} );
    }
    

    Is the second way more low-lever and thus more appropriate to customize widgets? Is it faster that chaining signals?

    Which way would you choose and if you chose B would you use another function like bool QAbstractButton::hitButton(const QPoint &pos) const?

    Thank you for your comments and critic.

    EDIT: Typo.

    1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi
      The chaining of signals is most like the most efficient as
      the eventfiler will see all events and hence do compare to all of them.

      The emit is more direct,

      However, event filter might be more handy if you already have used lots of puthbutton in a Design and
      its huge task to replace them with the subclass.

      However, the PushButton subclass keeps it all neatly contained and I would choose this over
      event filter if starting a new design.

      Petross404_Petros SP 1 Reply Last reply
      1
      • mrjjM mrjj

        Hi
        The chaining of signals is most like the most efficient as
        the eventfiler will see all events and hence do compare to all of them.

        The emit is more direct,

        However, event filter might be more handy if you already have used lots of puthbutton in a Design and
        its huge task to replace them with the subclass.

        However, the PushButton subclass keeps it all neatly contained and I would choose this over
        event filter if starting a new design.

        Petross404_Petros SP Offline
        Petross404_Petros SP Offline
        Petross404_Petros S
        wrote on last edited by
        #3

        @mrjj Thanks for the insightfull answer. Indeed eventFilter will see every event. What would be a more suitable function? I am thinking of mousePressEvent and keyPressEvent to look for left click and enter key respectively.

        I 've read that a signal is used and connected to from some user of the class, while the event system is used to further customize the custom widget (from the developer I suppose). What is your opinion on this?

        Thank you again for your time.

        1 Reply Last reply
        0
        • Christian EhrlicherC Online
          Christian EhrlicherC Online
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by
          #4

          But I don't see why you need to subclass QPushButton at all here. Either use QObject::sender() or a simple lambda in the connect to get the sender.

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          Petross404_Petros SP 1 Reply Last reply
          2
          • Christian EhrlicherC Christian Ehrlicher

            But I don't see why you need to subclass QPushButton at all here. Either use QObject::sender() or a simple lambda in the connect to get the sender.

            Petross404_Petros SP Offline
            Petross404_Petros SP Offline
            Petross404_Petros S
            wrote on last edited by
            #5

            @Christian-Ehrlicher PushButton's ctor accepts a Shape* Now Shape is the base class class for Hex, TBar, Pipe etc. This way each PushButton has a Shape** member and when it is passed to another object, I can use various virtual functions from Shape depending if I passed a Hex, Pipe or something else.

            Although I haven't worked with QObject::sender() I can't think of another way for a QPushButton to hold Shape-related information but to subclass it and emit the derived object so I can access all the Shape virtual functions.

            CalculatorWindow::CalculatorWindow( QWidget* parent )
            	: QMainWindow{ parent }
            	, m_ui{ new Ui::CalculatorWindow() }
            	, mListOfButtons{ QList<PushButton*>() }
            	, m_btnPipe{ new PushButton{ this, new Pipe{ this } } }
            	, m_btnTBar{ new PushButton{ this, new TBar{ this } } }
            	, m_btnHexa{ new PushButton{ this, new Hex{ this } } }
            ....
            

            Later in another widget, I am constructing a ShapeView like this:

            // shapeview.h
            class ShapeView: public QGraphicsView
            {
            	Q_OBJECT
            
            public:
            	ShapeView( const PushButton* pBtn, QWidget* parent = nullptr );
            ....
            
            // shapeview.cpp
            ShapeView::ShapeView( const PushButton* pBtn, QWidget* parent )
            	: QGraphicsView{ pBtn->shapeType()->scene()->p_scene, parent }
            {
            	setWindowTitle( tr( pBtn->shapeType()->name().c_str() ) );
            }
            

            I am suspecting that I could subclass QPushButton and use sender() but I haven't experimented with it (yet).

            Thank you for your answer, it might help me do things simpler.

            1 Reply Last reply
            0
            • mrjjM Offline
              mrjjM Offline
              mrjj
              Lifetime Qt Champion
              wrote on last edited by
              #6

              Hi

              • I 've read that a signal is used and connected to from some user of the class, while the event system is used to further customize the custom widget (from the developer I - suppose). What is your opinion on this?

              Well often signal and slots are used as a defined interface that the user of the class can connect to, to trigger an action or
              get notified of some state changes.

              Events are often more system orientated and more often changed to alter the default behavior of the class in regards to the
              events send by the OS or Qt.

              Both can be used to costimize a class. What do use , mostly depends on what needs to change.
              In your case, adding a new Click signal, it pretty fine to do the way you did.

              However, does your PushButton use shape for anything ?
              Im asking as if button dont use it for anything, you could store it in a dynamic property and use the sender() to get the button.
              and you would not need new signal or anything else.

              However, if button does access the shape, then a sublass seem better.

              Petross404_Petros SP 1 Reply Last reply
              0
              • mrjjM mrjj

                Hi

                • I 've read that a signal is used and connected to from some user of the class, while the event system is used to further customize the custom widget (from the developer I - suppose). What is your opinion on this?

                Well often signal and slots are used as a defined interface that the user of the class can connect to, to trigger an action or
                get notified of some state changes.

                Events are often more system orientated and more often changed to alter the default behavior of the class in regards to the
                events send by the OS or Qt.

                Both can be used to costimize a class. What do use , mostly depends on what needs to change.
                In your case, adding a new Click signal, it pretty fine to do the way you did.

                However, does your PushButton use shape for anything ?
                Im asking as if button dont use it for anything, you could store it in a dynamic property and use the sender() to get the button.
                and you would not need new signal or anything else.

                However, if button does access the shape, then a sublass seem better.

                Petross404_Petros SP Offline
                Petross404_Petros SP Offline
                Petross404_Petros S
                wrote on last edited by Petross404_Petros S
                #7

                @mrjj said in What is more efficient for custom widget: Re-implementing protected QEvent functions or chaining signals?:

                However, if button does access the shape, then a sublass seem better.

                It does, yes. Actually it's the only reason this subclass was created in the first place; Each PushButton must have a different shape but with a unique interface (virtual ShapeScene* Shape::scene(), name() etc).

                Regarding the sender() function, I came up with this:

                //Experimental
                connect(pbtn,
                        &PushButton::clicked,
                	this,
                	[this](){showDialog(qobject_cast<PushButton*>(sender()));});
                ...
                
                void CalculatorWindow::showDialog( PushButton* pbtn ){ ...
                

                Earlier it used to be less "hacky" because pbtnClicked(PushButton* pbtn) signal carried what I needed. Also, Qt states that sender() ...

                ... function violates the object-oriented principle of modularity. However, getting access to the sender might be useful when many signals are connected to a single slot.

                I don't have many signals connected to showDialog(PushButton*) but I get the same result. So it boils for me to learn good habits now that I am more inexperienced.

                Anyway thank you all for your good answers. I certainly learned something here :)

                mrjjM 1 Reply Last reply
                1
                • Petross404_Petros SP Petross404_Petros S

                  @mrjj said in What is more efficient for custom widget: Re-implementing protected QEvent functions or chaining signals?:

                  However, if button does access the shape, then a sublass seem better.

                  It does, yes. Actually it's the only reason this subclass was created in the first place; Each PushButton must have a different shape but with a unique interface (virtual ShapeScene* Shape::scene(), name() etc).

                  Regarding the sender() function, I came up with this:

                  //Experimental
                  connect(pbtn,
                          &PushButton::clicked,
                  	this,
                  	[this](){showDialog(qobject_cast<PushButton*>(sender()));});
                  ...
                  
                  void CalculatorWindow::showDialog( PushButton* pbtn ){ ...
                  

                  Earlier it used to be less "hacky" because pbtnClicked(PushButton* pbtn) signal carried what I needed. Also, Qt states that sender() ...

                  ... function violates the object-oriented principle of modularity. However, getting access to the sender might be useful when many signals are connected to a single slot.

                  I don't have many signals connected to showDialog(PushButton*) but I get the same result. So it boils for me to learn good habits now that I am more inexperienced.

                  Anyway thank you all for your good answers. I certainly learned something here :)

                  mrjjM Offline
                  mrjjM Offline
                  mrjj
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  Hi
                  Just as a note.
                  When using a lambda, one can also just capture the button

                  connect(pbtn,
                          &PushButton::clicked,
                  	this,
                  	[this, pbtn](){showDialog(pbtn);});
                  

                  but for a normal/classic slot, the sender() is needed for same trick.

                  Petross404_Petros SP 1 Reply Last reply
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    Hi,

                    This looks a bit convoluted. Why not use a QMap between QPushButton and your shape class ?

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    1 Reply Last reply
                    1
                    • mrjjM mrjj

                      Hi
                      Just as a note.
                      When using a lambda, one can also just capture the button

                      connect(pbtn,
                              &PushButton::clicked,
                      	this,
                      	[this, pbtn](){showDialog(pbtn);});
                      

                      but for a normal/classic slot, the sender() is needed for same trick.

                      Petross404_Petros SP Offline
                      Petross404_Petros SP Offline
                      Petross404_Petros S
                      wrote on last edited by
                      #10

                      @mrjj said in What is more efficient for custom widget: Re-implementing protected QEvent functions or chaining signals?:

                      Hi
                      Just as a note.
                      When using a lambda, one can also just capture the button

                      connect(pbtn,
                              &PushButton::clicked,
                      	this,
                      	[this, pbtn](){showDialog(pbtn);});
                      

                      but for a normal/classic slot, the sender() is needed for same trick.

                      I think you are right, yes.

                      For your next comment, yes it's a bit messy. It all started when PushButtons couldn't work with QButtonGroup and I had to subclass this too. Anyway, as soon as I fix some nasty valgrind/memory errors I will post the link for review and critic :)

                      This program can certainly do things way simpler.

                      1 Reply Last reply
                      0
                      • Pl45m4P Pl45m4 referenced this topic on

                      • Login

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