[SOLVED] Extending widgets



  • I'm trying to figure out what's the best way to extend a widget.

    I want to have a QLabel with a hover behavior, and as it seems from my research so far, the only way to do that is to extend the QLabel widget and and override the HoverEnter, HoverMove and HoverLeave methods.

    My question though is how do I then use my extended widget instead of the QLabel in the design view of Qt Creator?
    Do I actually need to go through all of this to do that?
    Is it enough to promote my widget?
    This isn't very clear how to do something that seems to be very basic..

    Thanks.


  • Qt Champions 2016

    Hi

    The promote feature is an easy way to use a custom widget in Designer.

    The full plugin road is for widgets where you want to be able to alter
    properties design time.



  • Ok, then promoting sounds like the option for me.
    What do I need to provide for that? cpp and h files?


  • Qt Champions 2016

    @nitzan
    Yes, just a normal cpp and h file.
    Just make sure you type ClassName (of your widget) correctly as it don't validate it :)



  • @mrjj

    thanks!
    that worked well, except for one problem.
    calling the setTest method seems to have no effect at all..
    I'm doing this:

    MyWidget::MyWidget(QWidget* parent) : QLabel(parent) {
    	qDebug() << "MyWidget ctor";
    	this->setText("hey there");
    	this->setAttribute(Qt::WA_Hover);
    }
    
    bool MyWidget::event(QEvent* event) {
    	switch (event->type()) {
    		case QEvent::HoverEnter:
    			this->setStyleSheet("color: rgb(255, 0, 0)");
    			break;
    
    		case QEvent::HoverLeave:
    			this->setStyleSheet("color: rgb(0, 0, 0)");
    			break;
    
    		default:
    			return QLabel::event(event);
    	}
    
    	return true;
    }
    

    And the label has no text in it.
    Any idea why?


  • Qt Champions 2016

    @nitzan said:

    this->setText(..)

    Have you tried SetText from outside, like via a button ?
    Sometimes I get fooled by stuff overwritten by the ui->setup which is run after
    your constructor.



  • @mrjj
    but that creates coupling i would prefer to avoid..
    is there anyway to have that in the same class in a way that will be called after the ui->setup?


  • Qt Champions 2016

    @nitzan
    It was just for testing.

    Have you tried to set it on the label you promote. ?
    And not call SetText at all in constructor.

    I get the text here. (from designer)



  • @mrjj
    calling setText from outside the class works well, even if I do it from the event method it works, but not in the ctor.

    I can't set the text from the designer as the actual text I'm trying to put there is from font awesome (using QtAwesome), and so the actual code is:

    UserWidget::UserWidget(QWidget* parent) : QLabel(parent) {
    	qDebug() << "UserWidget ctor";
    	this->setText(QString(QChar(fa::user)).append(" login"));
    	this->setAttribute(Qt::WA_Hover);
    }
    

  • Moderators

    If you don't want the text overwritten by the text from designer then instead of promoting QLabel to your class promote a plain QWidget. It won't have the Text property in the editor so the generated setupUi code won't call setText and the value set in your constructor will be preserved.



  • @Chris-Kawa
    Sounds like a workaround, but I would like to understand why it's needed.

    As the ctor of QLabel is called before the code in my widget is executed, then the setupUi code should be executed before my code as well.
    Unless I'm missing something?


  • Qt Champions 2016

    Well its the setupui for the mainform/dialog.
    It creates the Qlabel and set its text.
    So calls setText after the constructor.


  • Moderators

    It's not a workaround. You should always promote from the "lowest" widget of which functionality you want to preserve. In this case you don't want to have the label's ability to edit text in the designer so you promote from a widget, not label.

    As the ctor of QLabel is called before the code in my widget is executed, then the setupUi code should be executed before my code as well. Unless I'm missing something?

    The code of the window widget's constructor usually looks something like this:

    Foo::Foo(QWidget* parent) : QWidget(parent) {
        ui->setupUi(this);
    }
    

    which "expands" to something like this:

    Foo::Foo(QWidget* parent) : QWidget(parent) {
        ...
        ui->someLabel = new YourLabel(this);
        ui->someLabel->setText(whateverWasSetinTheDesigner);
        ...
    }
    

    so as you can see whatever you set in the constructor is immediately overwritten by what was set in the designer.
    If you promote from a QWidget the designer doesn't "know" it's a label and it won't generate the setText() call.



  • Alright, promoting from QWidget indeed did the job and now it works well!
    Thanks for the both of you.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.