Issue changing a QPushButton style in Qt - c++

I have created a QPushButton in Qt without applying any style, so it inherits the style from Windows10, with this result:
Then I wanted to change temporary the color of the button, so I used:
pushButton->setStyleSheet("background-color: rgb(255,220,220)")
getting this result:
Already this result does not satisfy me because also the style is slightly different from the original one. Anyway the next step was that the button had to return to the "normal" style when pressed, so I added this command
pushButton->setStyleSheet("background-color: rgb(240,240,240)")
but the result is different from the starting button:
Can you please give me some advice to better manage the style?
Thanks

Actually when you set background-color alone to QPushButton, The background may not appear unless you set some value for border.
Look here for (List of Stylable Widgets: QPushButton)
http://doc.qt.io/qt-5/stylesheet-reference.html
I think in windows 10 for some reason, you are able to see something without even setting border.
But the recommended way is to set some border value.
So try setting border value as said below, and see if it addresses your requirement:
pushButton->setStyleSheet("background-color: rgb(255,220,220);border: none; ")
In the above said link you can find below information:
Warning: If you only set a background-color on a QPushButton, the background may not appear unless you set the border property to some value. This is because, by default, the QPushButton draws a native border which completely overlaps the background-color.

Here are some snippets you may find quite similar and helpful.
I had an Update button which I turned into red Cancel button. Once the update action is finished or cancel is pressed, I restored the original color and text.
// Global variables to save off button state
QPalette update_btn_palette_restore;
QString update_btn_text_restore;
....
// Update button is pressed.
// Save the palette and text.
update_btn_palette_restore = _ui->update_button->palette ();
update_btn_text_restore = _ui->update_button->text ();
// Change the color palette and text
QPalette p=palette();
p.setBrush(QPalette::Button,Qt::red);
_ui->update_button->setPalette(p);
_ui->update_button->setText ("Cancel");
....
// Handler for when either cancel is pressed or update has finished
if(! update_btn_text_restore.isEmpty ()) {
_ui->update_button->setText (update_btn_text_restore);
_ui->update_button->setPalette(update_btn_palette_restore);
}

Related

Qt/C++ - Set background of disabled button?

I have all my buttons disabled in a grid, but for some, I'd like to change the background color. I'm trying:
_fieldButtons[0][0]->setStyleSheet("color: blue; background-color: blue;");
Where
QVector<QVector<QPushButton*> > _fieldButtons;
However, these buttons are all disabled, and only the text color gets changed:
How can I change the background, but not the text? Thank you!
UPDATE
I figured it's not working because the buttons are flat. How can I change flat button colors?
Two options:
Add border: none; to your stylesheet.
Use setAutoFillBackground(true) in conjunction with QPalette::Button
myButton->setFlat(true);
myButton->setAutoFillBackground(true);
QPalette pal = myButton->palette();
pal.setColor(QPalette::Button, QColor(Qt::blue));
myButton->setPalette(pal);
http://doc.qt.io/qt-5/qpushbutton.html#flat-prop
Try this:
myButton->setPalette(QColor("#124e6b"));
simply change the QColor to suit your use.
Or in Qt Creator you can right-click on the widget and select Change Style Sheet, as shown here:
Here you have two "Pseudo-States" in your control. For list of "Pseudo-States" refer below link.
http://doc.qt.io/qt-5/stylesheet-reference.html#list-of-pseudo-states
The first "Pseudo-State" is -- flat
The second "Pseudo-State" is -- disabled
Here you have to club both the states to set the style using "setStyleSheet".
_fieldButtons[0][0]->setStyleSheet(":flat:disabled {background-color: blue; border: none;}");
look for ":hover:enabled" (two different "Pseudo-States" how documentation handled) in the below link to get better idea.
http://doc.qt.io/qt-4.8/stylesheet-syntax.html
To understand, why you we have to give border:none for QPushButton, please look for below information in the first hyperlink in this answer.
"Warning: If you only set a background-color on a QPushButton, the background may not appear unless you set the border property to some value. This is because, by default, the QPushButton draws a native border which completely overlaps the background-color."

In MFC, for an initial focus on a checked RadioButton, setting the text label to be "highlighted"

I am using a Win32 app with MFC in C++ and utilizing Forms with a series of Dialog Screens. My problem is, when I have a series of these screens in sequence, I want the initial focus and its associated text label to be set on a particular radio button. In other screens, if I have a first control widget that is an edit text field, this automatically occurs (i.e. the first control widget in creation and tab order sequence is Focused on, and the text inside that edit text field is highlighted). However, in some dialog screens, the first control widget is a Radio Button group. In these cases, focus is correctly implicitly set to the currently checked radio button. However, the associated text label that describes that label button is displayed un-highlighted. Any subsequent user navigation (by mouse clicks or translation by keyboard) will always highlight the associated text label, when any radio button is checked or selected. However, only in this initial dialog screen creation, I cannot get the text label to be highlighted.
To clarify, by "highlight" I mean a perforated outline surrounding the text label beside the circular radio button image.
Here are some of the things I have tried in the OnInitDialog() function of said Dialog screens:
SendDlgItemMessage(IDC_RADIO1, BM_SETCHECK, BST_CHECKED, 0);
Which does display the filled in circular button representing it is checked, but the associated text label is still not highlighted.
I've also tried to "force" it to treat it as a button clicked message:
HWND hwdButton = ::GetDlgItem(m_hWnd, IDC_RADIO1);
::PostMessage(m_hWnd, WM_COMMAND, MAKELONG(IDC_RADIO1, BN_CLICKED),
(LPARAM) hwdButton);
I've also tried to send an explicit message to set the "State" (where, for a RadioButton, I believe having the State ON or true is represented by the highlighting of the text).
SendDlgItemMessage(IDC_RADIO1, BM_SETSTATE, TRUE, 0);
I've also tried doing these operations with or without a subsequent UpdateData(false) to refresh and with or without separately setting the focus and returning from the OnInitDialog() with a false instead of true. None of these combinations has any apparent impact on the GUI behavior.
The focus is always implicitly set on the correct radio button, and it's displayed as being correctly checked, just no highlighted text label, and any subsequent navigation or traversal yields the appropriate highlighted text labels.
The problem is on the initial dialog screen creation only.
Thanks for any help or recommendations.
Per the reference in #cha comment above, the reason the "focus rectangle" is not appearing has to do with a Microsoft Windows display setting. That column gets into how to change the setting in various flavors of Windows. In actuality, this is apparently the standard configuration for Windows MFC behavior - when focus is on a dialog control widget that is a radio button upon initialization, the "focus rectangle" is intentionally and specifically withheld from being drawn until the user initiates a keyboard navigation event (i.e. tab/enter/arrow keys). The problem with that (as already seen and illustrated in the problem description above) is that it changes the focus - and can be misleading to the user when the focus was actually already correctly set, just wasn't being indicated with the "focus rectangle".
The "exception" which draws the focus rectangle in-place, without having to change focus, is to depress the <Alt> Key on the keyboard.
After some digging elsewhere, I utilized this code to simulate the keyboard event of the depress of an <Alt> Key at the end of the OnInitDialog() function, and this yielded the desired behavior, the focus is set as desired, and the "focus rectangle" is drawn around the label of the currently selected radio button:
// Simulating an <Alt> keystroke.
keybd_event(VK_MENU, 0xb8, 0, 0); // Depress `Alt` key.
keybd_event(VK_MENU, 0xb8, KEYEVENTF_KEYUP, 0); // Release `Alt` key.

How to stop graying out of main window menu after activation of child window?

There is a feature in Windows: If current window is not activated, main menu of this window looks disabled (but in fact it is just grayed out, so you can click on any item in this menu). It is ok when you switch to another program, but it looks wrong when you go to child window.
It is easy to reproduce this effect even with standard Notepad:
Put any text in it,
Press Ctrl+F,
Now you can see that main menu looks disabled, but you can click on any item in it.
The question is following: How to block this effect for my program only? In my program (C++ and Qt) I have the same graying out of all items in the main menu when user goes to child windows. Is there a way to stop it?
I do not put any code here, because this effect it reproducible in the most of programs. But I hope that it is possible to change flags/properties of my QMenu or QMenuBar to correct this behavior. Is it possible?
We can correct a palette of the QMenuBar to substitute a text color in inactive state with text color in active state.
The code:
QPalette pal = pMenuBar->palette();
QColor col = pal.color(QPalette::Active, QPalette::ButtonText);
pal.setColor(QPalette::Inactive, QPalette::ButtonText, col);
pMenuBar->setPalette(pal);
After it user will not see graying out of items in a main menu, because text colors of active and inactive items will be the same.
(Theoretically it is possible that background color of active and inactive states of the same item are different. So it might be reasanoble to make the same replacement for background too)

QDockWidget::background-color not applied when docked

I have a QDockWidget:
I would like to alert the user to certain events by setting the background color of the title bar.
I have achieved this by setting the style sheet for my DockWidget:
void DockWidget::setCriticalAlert()
{
setStyleSheet("QDockWidget { background-color:red; }");
}
The result is this:
The problem is that the background-color doesn't get applied when the QDockWidget is docked:
How can I get the background color to be applied when the QDockWidget is docked?
This is a bug in Qt.
Issue 10537
Quoting from the linked issue:
The problem is that in QDockWidget::paintEvent, there is a
isFloating() condition before drawing PE_FrameDockWidget. We cannot
jsut remove this condition as it would break the other style (that
does not whish to draw frame when the dockwidget is docked) We cannot
either use PE_Widget to draw the frame as then it goes over the
dockwidget's title The solution is maybe to introduce a new
PE_FrameDockWidgetDocked primitive element. Or some
SH_DockWidget_DrawDockedFrame stylehint to draw the frame in every
cases.
a valid workaround seems to be to set the stylesheet of the parent, and use the class-and-id selector. Forgive the python formatted code but the concept is the same - in this case, 'dock' is a QDockWidget which has been given an object name using setObjectName(), and its parent, the QMainWindow, is 'self':
self.setStyleSheet("QDockWidget#"+str(dock.objectName())+"::title {background-color:red}")
In PyQt5.5, this works at runtime, i.e., can be changed on the fly.
I find a solution like this:
Firstly put a frame behind all the widgets of dockwidget's center widget, as the background.
Then set stylesheet for the frame.
By this way, we could change the background color of dockwidget.
Or you can extend the dockwidget and overwrite the function
void QDockWidget::setWidget(QWidget *widget)
using private/qdockwidget_h. and add a frame as this widget's father.

Changing QPushButton Color when Pressed

Is there a way to change the background color of a QPushButton which is pressed by modifying its QPalette object? I realize it can be done with style sheets but would like a way to do it by modifying the QPalette. Something similar to how one changes the background color of the button when not pressed:
QPushButton myButton;
QPalette p(myButton.palette());
p.setColor(QPalette::Button, QColor("#ffffff"));
myButton.setPalette(p);
Simply add a stylesheet to the qbushbutton itself or to his parent qwidget:
qwidget.setStyleSheet("QPushButton:checked { background-color: red; }")
This will set the background color to red when the QPushButton is checked.
Connect to QPushButton's pressed() signal and update the palette with your desired color and then connect to released() signal and switch back the color to the old color. That should do it.
You may want to run update() after settings the colors or in extreme cases repaint().
Connect to the button's pressed signal and set the palette in the connected slot. You may have to call repaint() to force an immediate update.
you can set stylesheet for button when it is pressed.. here is the Example tells how to set style sheet for button.. but in your case u need to have two different style sheets, one is button pressed and similarly when it is released you should reset with some other stylesheet.