qt mousemoveEvent (involved with qss) - qt

I have a widget class 'BlockWidget' subclass of QLabel, in the ctor I set its qss qss_1, and I want animated effect that when the mouse move on it, it will change its background-color, so I set its qss qss_2, but it seems not working... My code like this:
BlockWidget::BlockWidget(const QString &objname)
{
this->setObjectName(objname);
setAlignment(Qt::AlignCenter);
setStyleSheet(tr("BlockWidget#%1{color:white; background-color: gray; font-size:18px;"
"font-family:'Consolas';}").arg(objectName()));
}
void BlockWidget::mouseMoveEvent(QMouseEvent *ev)
{
setStyleSheet(tr("BlockWidget#%1{color:white; background-color: blue; font-size:18px;"
"font-family:'Consolas';}").arg(objectName()));
repaint();
}
And I have a mainwindow, I instantiated 81 instances of BlockWidget. when my mouse move to one of them, nothing happened. but if I click on it some times, it do change its qss style(its background turns blue)

As stated by the documentation, mouse move events are only sent when you click, drag or release the buttons, if mouse tracking isn't enabled for the widget.
You can detect the mouse entering and leaving the labels by redefining QWidget::enterEvent and QWidget::leaveEvent in your BlockWidget class.
Or you can simply use the :hover QSS pseudo-state without having to redefine any mouse related function:
setStyleSheet("BlockWidget {"
" color:white;"
" background-color: gray;"
" font-size:18px;"
" font-family:'Consolas';"
"}"
"BlockWidget:hover {"
" background-color: blue;"
"}");
PS:
According to Qt style sheet documentation, QLabel doesn't support the :hover pseudo-state, however changing the background or the borders seems to be working fine.
Since your BlockWidget widgets don't have themselves BlockWidget children, and because you set the stylesheet individually to all of them, it should be safe to omit the object name from the QSS selector.

You must enable mouse tracking for your widget http://qt-project.org/doc/qt-4.8/qwidget.html#mouseTracking-prop

Related

Why does padding-left style result in QComboBox menu stretching to screen height?

Consider the following example. It creates two instances of QComboBox: one with a stylesheet, and another without. If the first one is clicked (with widget style being Fusion), the menu is sized as expected, although padding of text is inconsistent between hovered and non-hovered items. But if you click on the second one, the padding problem is now fixed, but the menu appears to have huge entries, making the menu fill the whole screen height.
#include <QComboBox>
#include <QApplication>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QComboBox box1, box2;
const QString stylesheetOrig=R"(
QComboBox::item:selected
{
background-color: #0000ff;
}
)";
box1.setStyleSheet(stylesheetOrig);
box2.setStyleSheet(stylesheetOrig+R"(
QComboBox::item
{
padding-left: 27px;
}
)");
box1.addItems({"Hello 1","Goodbye 1"});
box2.addItems({"Hello 2","Goodbye 2"});
box1.show();
box2.show();
return app.exec();
}
If I remove the padding statement, still leaving the QComboBox::item {} part, then nothing strange (and nothing useful) happens. But if I even set the padding to 1px or 0px, the stretching already happens with all its might.
Why does setting horizontal padding result in such a strange change vertically?
Wow OK, that is screwy indeed. Adding any css to a combo box makes it go into some other "retro" mode with showing icons next to the current item. I've never noticed that in many years, but I see a bunch of common threads on the issue. Seems to only affect Fusion style though, I was confused for a while on my Windows box until I figured that out.
The question is if you want the checkbox or not. Here's one way to get rid of it, the only consistent one I found after a bit of playing with it. The main trick is setting the selection colors on the ::item and not on ::item:selected (the latter makes the checkmarks appear).
QComboBox::item {
selection-background-color: #0000ff;
selection-color: palette(highlighted-text);
}
PS. Another reason for confusion and why QComboBox::item and :checked even work is that the QComboBox default item delegate (used to draw the items in the QListView which the combo box uses for the options list) "pretends" it's a QMenu: QComboMenuDelegate::paint()
So another workaround would be to use something more sane/customizable for a delegate, perhaps even a default QStyledItemDelegate.
ADDED: A version keeping the checkbox and ensuring the unchecked items have padding (w/out using padding property which appears to be FUBAR when used in a combo box item with Fusion style). The icon size seems easiest set via iconSize property -- I tried a few ways via css icon/image/element width/height but nothing affected it... probably because the iconSize property overrides it.
QComboBox { qproperty-iconSize: 12px; } /* or QComboBox::setIconSize() */
QComboBox::indicator { color: transparent; } /* to force space for the icon column */
/* Using ::item:selected vs. ::item { selection-*-color: } will apparently make the
checkbox column appear... at least with Fusion as the main style */
QComboBox::item:selected {
color: palette(highlighted-text);
background-color: #0000ff;
}
VERSION 3 (as per comments):
QComboBox { qproperty-iconSize: 12px; } /* or QComboBox::setIconSize() */
QComboBox::indicator:!checked { border: 0; } /* to force space for the icon column */
QComboBox::item { background-color: palette(base); } /* gets rid of icon|text separator */
/* Using ::item:selected vs. ::item { selection-*-color: } will apparently make the
checkbox column appear... at least with Fusion as the main style */
QComboBox::item:selected {
color: palette(highlighted-text);
background-color: #0000ff;
}
There's still a 1px frame line at the top of the unselected icon area, though it's pretty subtle. I have no idea where that comes from... tried some guesses but to no avail.

Keeping the same selection color in a TableView whether it's active or not

I'm using QTableView class in my GUI and I would like the selected row to have the same color whether the TableView is active or inactive.
I tried to set this CSS stylesheet to achieve this:
QTableView:!active {
selection-background-color: palette(Highlight);
selection-color: palette(HighlightedText)
}
On Linux, it works just fine, but on Windows 7, when the TableView loses its focus, the text turns black instead of staying white (the background stays blue, so that part is OK). Am I missing something here ?
You also have to style text color, for example just add:
QTableView:!active {
...
selection-color: white;
}
This works well in python
pal = tbl_list.palette()
pal.setColor(QPalette.Inactive, QPalette.Highlight, pal.color(QPalette.Active, QPalette.Highlight))
tbl_list.setPalette(pal)

QDockWidget change background color when floating

I have a QDockWidget with a transparent background, but I would like to change the background color or background image when it is floating. It doesn't look like the qt style sheets have a pseudo state to tell you whether or not they are floating, so I'd like to know: is this possible to do?
Found the solution. Add the following connection in the code:
connect(knobDock, &QDockWidget::topLevelChanged, [&] (bool isFloating)
{
if (isFloating)
{
setAttribute(Qt::WA_TranslucentBackground, false);
setAttribute(Qt::WA_NoSystemBackground, false);
}
});
This will cause the dock widgetto use whatever background is specified in the stylesheet when the dock is floating, but it will be transparent (i.e. show the mainwindow background) when it's docked.
You can use custom properties to do this.
Thanks #phyatt for link to Dynamic Properties and Stylesheets.
To declare custom property in your custom class you can write in .cpp:
setProperty("customPropertyName", 1);
or in .h (don't forget to define and implement used get/set access methods too):
Q_PROPERTY( int customPropertyName, READ getCustomPropertyName, WRITE setCustomPropertyName);
And in your global stylesheet file you can use the state of your custom property as following:
.YourClass[customPropertyName="1"] {
background-color: transparent;
}
.YourClass[customPropertyName="2"] {
background-color: black;
}
Also it's needed to reload stylesheet of the object instance after your set new property value, because stylesheets are not recalculated automatically:
object->style()->unpolish(tstFrame);
object->style()->polish(tstFrame);
object->update();
or:
object->setStyleSheet("/* */");

Qt Style Sheet - Different styles for same type widgets

I need to assign different styles for the same typed widget instances. Specially for QActions. Following style sheet sets QActions' background images, actualy tool buttons'.
QToolButton
{
background-image: url(bg.png);
}
But I need to assign different backgrounds for tool buttons like this.
QToolButton::actClose
{
background-image: url(close.png);
}
QToolButton::actOpen
{
background-image: url(open.png);
}
Is there any easy way like this or is it not possible?
You can set object name for instances of QToolButton
QToolButton *button = new QToolButton;
button->setObjectName("firstButton");
button = new QToolButton;
button->setObjectName("secondButton");
and next use them in Style Sheet
QToolButton#firstButton
{
background-color: gray
}
QToolButton#secondButton
{
background-color: red
}
It helps if you can post c++ code that creates the QToolButton and associates with QActions.
Cite from QToolBar's reference "Toolbar buttons are added by adding actions, using addAction() or insertAction(). " and "QWidget * QToolBar widgetForAction (QAction *action )const
Returns the widget associated with the specified action."
So if you are creating QToolBar and call QToolBar::addAction(QAction*) to fill it, it is possible to get pointer to the tool buttons. Try QToolBar::widgetForAction(), and call setObjectName("") and Blueman's method can be applied.
while applying Style Sheet to widgets, "#" is used after class name to specify object name, ":" is used after className of objectName indicating the object's status such like "enabled", "::" is used to specify the subcontrols such as "ListView::Item", unfortunately QAction is neither of QToolBar.

Changing the default color on flex validation errors

The examples I've seen seem to show how to change the color that shows when the user actually hovers over the textinput field.
However when the validation fails, a generic textInput border qill have a red line over it. My CSS file uses a border skin for the textInput, so I can't see this line.
I was hoping there was a way to highlight the text box when it failed validation, or re-enable the red line feature. I don't want to get rid of my CSS cos it'll totally blow my color-scheme, but any tweak allowing the error line to show would be much appreciated.
This is the CSS:
TextInput, TextArea
{
border-skin: Embed(source='/../assets/images/input_bg.png', scaleGridLeft=8, scaleGridRight=20, scaleGridTop=8,scaleGridBottom=9);
padding-top:2;
padding-left:2;
font-size:11;
}
anything that extends UIComponent (both TextInput and TextArea do) has a style called errorColor. It defaults to red. You can change this to whatever you want.
Additionally, if you've got an image that you are using as a border, you should probably remove the pixels from the middle so that it is an actual border instead of an overlay.
The only way I've managed to find, is that Validator will change the component's borderColor style. I don't think it can be achieved using an image- you'll have to embed the image in a basic GraphicRectangularBorder subclass or similar. You can then add this to your skin class:
override public function styleChanged(styleProp:String):void
{
super.styleChanged(styleProp);
if (styleProp == "borderColor")
{
if (getStyle("borderColor") == getStyle("errorColor"))
{
// show error outline
}
else
{
// hide error outline
}
}
}

Resources