Results 1 to 11 of 11

Thread: Changing QPalette doesn't affect to its QWidget

  1. #1
    Join Date
    Nov 2014
    Location
    Germany
    Posts
    69
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Windows Android

    Default Changing QPalette doesn't affect to its QWidget

    Hello everybody,

    I try to create a window with multiple QLineEdits and QPushbuttons that are grouped. Each group has a different background color, like, QLineEdits 1-5 are green and its corresponding QPushButton is also green, QLineEdits 6-10 are red and so does its corresponding QPushButton.

    What I try to achieve now is updating each group by clicking its corresponding QPushButton.
    From start, hence build and first display of the window, all QLineEdits should appear with classic white background. After clicking its corresponding QPushButton, they all should update its background color to green/red.

    I could now create a new palette for each QLineEdit, but this would result in much work. An easier solution would be a single QPalette.
    I noticed that QLineEdit::setPalette() accepts a reference to the QPalette. So afaik changing the palette should affect to every QLineEdit. Unfortunatelly, it doesn't...

    Example:
    Qt Code:
    1. QLineEdit *edit1 = new QLineEdit;
    2. QLineEdit *edit2 = new QLineEdit;
    3. QPalette palette;
    4.  
    5. palette.setColor(QPalette::Base, QColor(0,255,0);
    6. edit1->setPalette(palette);
    7. palette.setColor(QPalette::Base, QColor(255,0,0);
    8. edit2->setPalette(palette);
    To copy to clipboard, switch view to plain text mode 
    The result is that edit1 has a green background and edit2 has a red background. Why changing palette from green to red doesn't affect to edit1?
    Could the problem be that QLineEdit::setPalette() accepts a CONST reference? I thought that references are always const, because once initialized, they can't be re-initialized...

    Maybe someone can help me with that

    Kind regards,
    Binary

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Changing QPalette doesn't affect to its QWidget

    Quote Originally Posted by Binary91 View Post
    I could now create a new palette for each QLineEdit, but this would result in much work. An easier solution would be a single QPalette.
    You can pass the same palette object for any number of widgets.

    Quote Originally Posted by Binary91 View Post
    I noticed that QLineEdit::setPalette() accepts a reference to the QPalette
    No, it does not.

    Quote Originally Posted by Binary91 View Post
    Why changing palette from green to red doesn't affect to edit1?
    Each line edit has its own copy of the palette you passed in

    Quote Originally Posted by Binary91 View Post
    Could the problem be that QLineEdit::setPalette() accepts a CONST reference?
    Exactly.

    Quote Originally Posted by Binary91 View Post
    I thought that references are always const, because once initialized, they can't be re-initialized...
    A normal reference argument can be changed in the function it is passed to, a const reference argument cannot.
    E.g. a non-const reference argument is often used as an output or input/output argument, a const reference is always just an input argument.

    A reference member variable can only be initialized once but the object it reference can still be modified.
    The initialization needs to happen in the constructor's initialization list, it cannot be done through assignment.

    A setter function can never store a reference argument in a reference member.

    So even if QWidget had a reference member for its palette and even if setPalette would pass the object by reference, it could not change the object the member references.

    Cheers,
    _

  3. #3
    Join Date
    Nov 2014
    Location
    Germany
    Posts
    69
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Windows Android

    Default Re: Changing QPalette doesn't affect to its QWidget

    A reference member variable can only be initialized once but the object it reference can still be modified.
    The initialization needs to happen in the constructor's initialization list, it cannot be done through assignment.

    A setter function can never store a reference argument in a reference member.
    So does that mean the setter function just compares the object to which the ref argument points to with its "own" object and changes this instead of "replacing" it?

    If yes, how could I realize my purpose? Do I really have to manually change each QLineEdits palette?
    Last edited by Binary91; 3rd December 2016 at 13:03.

  4. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Changing QPalette doesn't affect to its QWidget

    Do I really have to manually change each QLineEdits palette?
    Yes, if you want each QLineEdit to have a different set of palette properties. If you use Qt Designer to lay out your form, you can create one QLineEdit, change its properties, then copy and paste it into other places in your form. The copies will have the same properties as the original one. This is not the same as making the change at run time, of course.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  5. #5
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Changing QPalette doesn't affect to its QWidget

    Quote Originally Posted by Binary91 View Post
    So does that mean the setter function just compares the object to which the ref argument points to with its "own" object and changes this instead of "replacing" it?
    I don't think that the setter compares the old and new value, it is more likely that it will just replace the old value.
    But we can check that, can't we?

    https://code.woboq.org/qt5/qtbase/sr...teERK8QPalette
    Looks a bit more complicated then just replacing.

    Quote Originally Posted by Binary91 View Post
    If yes, how could I realize my purpose? Do I really have to manually change each QLineEdits palette?
    Well, even if you do it manually, you can easily do that with a loop if you put all the line edits into a vector or list.
    Or you create a subclass and make setPalette a slot and connect all to the same signal.
    Or you use a global stylesheet, etc.

    Cheers,
    _

  6. #6
    Join Date
    Nov 2014
    Location
    Germany
    Posts
    69
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Windows Android

    Default Re: Changing QPalette doesn't affect to its QWidget

    Well, even if you do it manually, you can easily do that with a loop if you put all the line edits into a vector or list.
    Yap, that is how I did it (till) now.

    Or you create a subclass and make setPalette a slot and connect all to the same signal.
    Or you use a global stylesheet, etc.
    Both sound interesting, but I neighter know how to create own Signals in Qt, nor do I have advanced skills with stylesheets. Maybe I have to take a look at Qt's documentation again.

    EDIT:
    Well, I see that I can declare a signal like a regular function that is called when I set an "emit mysignal()". I'm asking myself what could be the benefit by using "emit signal()" instead of simply calling the function? Also I do not know how to automate this to avoid work. For my purposes I need something like every QLineEdit recognizes when one single QLineEdit changes its QPalette and they automatically do the same.


    Cheers,
    Binary
    Last edited by Binary91; 4th December 2016 at 08:47.

  7. #7
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Changing QPalette doesn't affect to its QWidget

    Quote Originally Posted by Binary91 View Post
    Well, I see that I can declare a signal like a regular function that is called when I set an "emit mysignal()".
    It also needs to be declared in a "signals:" section of the class.

    Quote Originally Posted by Binary91 View Post
    I'm asking myself what could be the benefit by using "emit signal()" instead of simply calling the function?
    No difference, the "emit" is "syntactic sugar" to make it obvious to the reader that this is a signal emit, not a normal function call.

    Quote Originally Posted by Binary91 View Post
    Also I do not know how to automate this to avoid work.
    You would only need to emit the signal if all your line edits are conncted to it.

    Cheers,
    _

  8. #8
    Join Date
    Nov 2014
    Location
    Germany
    Posts
    69
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Windows Android

    Default Re: Changing QPalette doesn't affect to its QWidget

    You would only need to emit the signal if all your line edits are conncted to it.
    I don't understand this. Let's say I have a signal colorChanged(QColor(int,int,int)) which I declare in every of my QLineEdits. Now I subclass the QLineEdit's setPalette function and like this (no correct syntax, just to display the idea):
    Qt Code:
    1. myQLineEdit::setPalette(QPalette())
    2. {
    3. QLineEdit::setPalette(QPalette());
    4. emit colorChanged();
    5. return;
    6. }
    To copy to clipboard, switch view to plain text mode 
    Now, changing background color of ONE QLineEdit with setPalette(..) should emit the signal for THIS QLineEdit. But why should all QLineEdits react on this? I mean, if I have 3 QPushButtons and each connected to the signal clicked(), then not all three buttons are clicked when I click one button, right? So in that situation, only the corresponding (clicked) QPushButton emits the signal clicked().

    Can you explain what you mean with "all your line edits" react on one signal?

  9. #9
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Changing QPalette doesn't affect to its QWidget

    I think you have the logic a little inside-out. It is the line edits that should react to the signal sent from somewhere else. In your MainWindow class (or whoever owns the line edits), you implement both the slot for setting the new palette on all of the line edits as well as the signal that gets emitted when a new palette should be set on a line edit.

    Qt Code:
    1. // constructor
    2. MainWindow::MainWindow( QWidget * parent ) : QMainWindow( parent )
    3. {
    4. // usual setup stuff here
    5.  
    6. connect( this, &MainWindow::paletteChanged, this, &MainWindow::onPaletteChanged );
    7. }
    8.  
    9. // slot pseudocode; slot declared in "slots" section of class definition
    10. void MainWindow::onChooseColor()
    11. {
    12. QColor newColor = QColorDialog::getColor( ... );
    13. if ( newColor.isValid() )
    14. {
    15. QPalette newPalette;
    16. palette.setColor( QPalette::Window, newColor );
    17. emit paletteChanged( newPalette ); // Your signal, defined in "signals" section of MainWindow class definition
    18. }
    19. }
    20.  
    21. // slot pseudocode; slot declared in "slots" section of class definition
    22. void MainWindow::onPaletteChanged( const QPalette & newPalette )
    23. {
    24. foreach( QLineEdit * pEdit in ui )
    25. {
    26. if ( pEdit->palette() != newPalette )
    27. pEdit->setPalette( newPalette );
    28. }
    29. }
    To copy to clipboard, switch view to plain text mode 

    One way to do it, assuming you want all of the line edits to have the same color. Why you'd want to do that, I don't know. Usually color changes are used to indicate specific things about specific items in a UI, like a red background to indicate an error in a line edit entry. You don't change all of them to red, just the bad ones. One the other hand, if you are providing an app that has custom skinning, then this would make sense in that context.

    You cannot avoid looping through the line edits to set each one's palette. If you derive from QLineEdit and implement a custom signal / slot combination on the derived class to do this, you still, at some point, have to loop over all of the line edit instances to hook up the signal and slot for all of them. Nothing is going to make a QWidget magically respond to some external change unless you tell it to, and that's by way of a signal / slot connection or event handler.
    Last edited by d_stranz; 7th December 2016 at 15:47.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  10. #10
    Join Date
    Nov 2014
    Location
    Germany
    Posts
    69
    Thanks
    1
    Qt products
    Qt4 Qt5
    Platforms
    Windows Android

    Default Re: Changing QPalette doesn't affect to its QWidget

    You cannot avoid looping through the line edits to set each one's palette. If you derive from QLineEdit and implement a custom signal / slot combination on the derived class to do this, you still, at some point, have to loop over all of the line edit instances to hook up the signal and slot for all of them. Nothing is going to make a QWidget magically respond to some external change unless you tell it to, and that's by way of a signal / slot connection or event handler.
    Aaah, then I really misunderstood him. But this is what my "logic" was about. I was just wondering how any other QLineEdit could react on a signal of a specific QLineEdit... Well, then I don't need to create own signals.

    Why you'd want to do that, I don't know. Usually color changes are used to indicate specific things about specific items in a UI, like a red background to indicate an error in a line edit entry. You don't change all of them to red, just the bad ones.
    Exactly what I'm doing. I have groups of QLineEdits within QVectors. Each group is connected to a QPushButton (Button Step1, Step2 and so on). When the button is clicked, I loop through the corresponding QVector list and change its QLineEdits to mark them as "active".

    Ok, thank you guys for your help.

    Kind regards,
    Binary

  11. #11
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Changing QPalette doesn't affect to its QWidget

    Quote Originally Posted by Binary91 View Post
    Let's say I have a signal colorChanged(QColor(int,int,int)) which I declare in every of my QLineEdits.
    No. The signal would be on the class that triggers the change.

    The line edits would have a matching slot.

    E.g. a changePalette(const QPalette&) signal and a "setPalette(const QPalette&)" slot in your line edit class.

    Cheers,
    _

Similar Threads

  1. why changing QCheckBox's text color doesn't work?
    By nuliknol in forum Qt Programming
    Replies: 2
    Last Post: 8th November 2015, 22:10
  2. Stylesheets affect performance
    By fredrikn in forum Qt Programming
    Replies: 8
    Last Post: 12th August 2011, 12:57
  3. Changing QPalette Highlight doesn't work on Windows 7
    By BinbinDesbois in forum Qt Programming
    Replies: 9
    Last Post: 7th August 2011, 11:19
  4. Replies: 0
    Last Post: 4th March 2011, 19:18
  5. Replies: 3
    Last Post: 30th April 2006, 19:22

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.