Global stylesheet isn't fully working - qt

I'm trying to set a global stylesheet for all my buttons.
Doing it for a specific button like the following, works as expected:
button->setStyleSheet(QString("QPushButton:focus {") +
"outline: 0;" +
"background-color: #" + BUTTON_HIGHLIGHT_BG_COLOR + "; " +
"color: #" + BUTTON_HIGHLIGHT_TXT_COLOR + "; " +
"}"
);
But if I make it global, like this:
qApp->setStyleSheet(QString("QPushButton:focus {") +
"outline: 0;" +
"background-color: #" + BUTTON_HIGHLIGHT_BG_COLOR + "; " +
"color: #" + BUTTON_HIGHLIGHT_TXT_COLOR + "; " +
"}"
);
the focused buttons get the correct font color, but they don't seem to have a background (although the background I'm setting for them is different from the main layout's background.)
BUTTON_HIGHLIGHT_BG_COLOR and BUTTON_HIGHLIGHT_TXT_COLOR are strings for colors (e.g. "FF0000")
What could be the cause that it works for a specific widget, but fails globally?
update:
I followed #ThorngardSO's answer and finally solved it by changing:
stackedWidget->setStyleSheet("background-color: white;");
to:
stackedWidget->setStyleSheet("QStackedWidget { background-color: white; }");
which was in the loading screen (first screen)

You should try to narrow it down as much as possible:
Is this the only rule in your global stylesheet? If not, remove all other rules for testing purposes and see what happens.
Get a clear grasp on the widget-hierachy of your button (perhaps it's the child of a groupbox which is itself a child of a mainwindow), and then check:
Do any of those widgets in the hierachy have a stylesheet set? If yes, remove those stylesheets for testing purposes and see what happens.
Do you, at any time, call functions like setPalette() or setAutoFillBackground() on any of the widgets in the hierachy (or have the auto-fill-background property set in the designer)? If yes, remove those calls and see what happens.

Not that it's your problem, but you're assembling that constant string at runtime from bits and pieces. Don't do that. Instead, you can simply concatenate string literals in C and C++ simply by putting them next to each other.
qApp->setStyleSheet(QStringLiteral(
"QPushButton:focus {"
"outline: 0;"
"background-color: #" BUTTON_HIGHLIGHT_BG_COLOR "; "
"color: #" BUTTON_HIGHLIGHT_TXT_COLOR "; "
"}"
));
If you wanted the colors to be changeable at runtime, use the %-substitution:
qApp->setStyleSheet(QStringLiteral(
"QPushButton:focus {"
"outline: 0;"
"background-color: #%1; "
"color: #%2; "
"}"
).arg(background).arg(foreground));

Related

Inline CSS looks different when looping through

I have a solution which have boxes. If the user wants three boxes it will look like this:
The user can also choose 2 different colors for _each_box. If the user choose one color for one box, the box background color will be changed to that color. If the user enter two colors instead, a linear gradient will be set. These data will be sent as a variable via props:
firstColorBox1
secondColorBox1
firstColorBox2
secondColorBox2
and so on. These can have values such as "red" or hex-codes. I also have another props "nrofboxes" which is the number of boxes. I use this variable for my for loops.
To dynamically change the css of the boxes, I am using inline CSS which is manipulated via props. In short, I have a state with an empty array. Each box inline style properties will be saved in this array and extracted via its index in a for-loop. Too handle each box specific css style I have done like this:
I have an empy array in state where each individual style object till be added to:
boxStyle: []
in componentDidMount
for (var i = 1; i <= Number(this.props.nrofboxes); i++){
let style = {backgroundColor:"", };
let concatToState;
if(this.props["firstColorBox" + i] || this.props["secondColorBox" + i] ) {
if(this.props["firstColorBox" + i] && this.props["secondColorBox" + i] ){
style["backgroundImage"] = `linear-gradient(${this.props["firstColorBox" + i]}, ${this.props["secondColorBox" + i]})`
concatToState = this.state.boxStyle.concat(style);
this.setState({boxStyle:concatToState})
}
else if(this.props["firstColorBox" + i]) {
style.backgroundColor = `${this.props["firstColorBox" + i]}`
concatToState = this.state.boxStyle.concat(style);
this.setState({boxStyle:concatToState})
} }}
Above I have a loop for each box, and I check if it has value in both props and if so --> add linear gradient, and if not --> add background color. Notice how I go through each box dynamically via:
this.props["firstColorBox" + i]
I then add the value of the color/props to an object, and concat it to state:
style.backgroundColor = `${this.props["firstColorBox" + i]}`
concatToState = this.state.boxStyle.concat(style);
this.setState({boxStyle:concatToState})
The idea is to take the index of the specific box style in the state array in a for loop in render.
In render, I output all boxes via a for loop:
for (var i = 1; i <= Number(nrofboxes); i++){
boxes.push(
<div className={globalStyles["a-Grid-col"] + " " + globalStyles["w-sm12"] + " " + globalStyles["w-lg" + size] + " " + globalStyles["w-xl" + size] + " " + styles["w-link-box-container"]}>
<div className={styles["link-box"]} >
<a href={this.props["linkurl" + i]} style={this.state.boxStyle[i]} >
<h4 className={styles["link-box-header-container"]}>
<small className={styles["link-box-header-title"] + " " + (this.props.themefontcolor ? styles["w-themed-color"] : "")}>{this.props["linktitle" + i]}</small>
<span className={styles["link-box-header-text"] + " " + (this.props.themefontcolor ? styles["w-themed-color"] : "")}>{this.props["linktext" + i]}</span>
</h4>
</a>
</div>
</div>
);
}
As you can see above, I try to get each specific style object from the state via the for loop like this:
style={this.state.boxStyle[i]}
However, it does not work. If the firstColorBox1 is = "red", the expected behaviour would be that only the first box will be red but it looks like this:
2 problems: instead of a red background color, the border is red. And not only that, all three boxes are affected by it instead of only the first one.
And if I hardcode the inline style to be red like this:
style={{backgroundColor:"red"}}
it will look like this:
It should be equal, but there is no red border and the backgroundColor is set properly. Why is that? I guess something with my loops is wrong.

Set a button of custom color to a disabled style

I have a class that inherits QWidget. Under certain circumstances, I wish to set it disabled.
The widget has some color buttons, that are set from a list of colors:
void MyWidget::colorUpdate(QString color)
{
if(!color.isEmpty())
{
QString foreground = (QColor(color).lightness() < 125 ? "white" : "black");
m_colorButton->setStyleSheet("color: " + foreground + "; background-color: " + color);
}
}
Calling myWidget.setEnabled(enabledOption); disables the widget, grays out all text and every other items in the widget - except for these color buttons.
So I am thinking of making my own action:
void MyWidget::setWidgetEnabled(bool enabled)
{
this->setEnabled(enabled);
// what else ?
}
How can I make my buttons - of a background color and text color that I don't know, but the button does - have that "disabled look" ?
(Note - the color update works on disabled items too - that is not really complicated though - whatever style sheet I apply on setting widget disabled can be applied in the colorUpdate function).
I just don't know how to apply a stylesheet with that gray shade - or possibly have a "disabled" option in the stylesheet even...
What do colors look like in "disabled" ?
To set your own style for the disable state.
You can set a special style for disabled state in the stylesheet :
m_colorButton->setStyleSheet(":enabled { color: " + foreground
+ "; background-color: " + color
+ " } :disabled { color: " + disabledForeground
+ "; background-color: " + disabledColor + " }");
edit: changed code for the widget instead of a global stylesheet.
To keep the default disabled style. You can set your custom style only for the enabled state, then when the widget is disabled the style does not apply :
m_colorButton->setStyleSheet(":enabled { color: " + foreground
+ "; background-color: " + color + "}");

Qt 4.8.5 QLabel setStylesheet ignores inherited font

I want to set some style properties via setStylesheet, e.g. a border
label.setStylesheet("border: 1px solid white;");
After that my label has a white border but all font properties set in the parent widget (QDesigner) are ignored!
qDebug() << label->font().family();
qDebug() << label->font().rawName();
both print the right font family but this is not applied after the setStylesheet function was called.
Same thing with colors. Colors set via QPlatte in the Designer are not used if I set some other properties via setStylesheet().
I don't know but it seems that we should not mix both technologies or I am doing something wrong here.
Unfortunately, setting one property in the style sheet of a widget usually results in all styles properties needing to be set, as well as breaking inheritance for any of those properties. I couldn't reproduce the font inheritance issue in my own environment (what version of Qt are you using?), but the following code should get you around this issue.
// Get the color of the label's parent (this).
QColor color = this->palette().windowText().color();
QString colorString = "rgb(" +
QString::number( color.red() ) + "," +
QString::number( color.green() ) + "," +
QString::number( color.blue() ) + ")";
// Get the Font of the label's parent (this).
QFont font = this->font();
// Set the Font and Color.
label->setFont( font );
label->setStyleSheet( "color: " + colorString + "; border: 1px solid white;" );
Personally, I try to keep all of my styling in either the form editor for specific form object styles, or in a style sheet that is loaded in at the top level, much like CSS for a web page.

Auto fit tag clouds in a div

I have some tag clouds placed within a div. For each tag cloud there is a thumbs down icon and I used sliding tag css from http://www.cssflow.com/snippets/sliding-tags
If a tag cloud is greater than 80px, it does not fit inside that div. I used word wrap and also fittext plugin from jquery but I could not manage to make it work. Could you suggest what could be the possible solution for it?
I have created fiddle for it: http://jsfiddle.net/aexqoe8n/1/
In Js side :
resultDiv = document.getElementById('tokenCloudResultDiv');
resultDiv.innerHTML = '';
resultDiv .innerHTML="<ul class='tags blue' style='list-style-type: none;padding:5px;'>";
for (i in json) {
addToken(resultDiv, i, json[i]);
}
resultDiv.innerHTML=resultDiv.innerHTML+"</ul>";
function addToken(target, key, result) {
var str;
var weight;
if(result['tagWeight']>80)
$("#tokenCloudResultDiv").fitText(1.2);
weight= "style='font-size: " + result['tagWeight'] + "px;'";
if(addedAutomatically)
str = "<li><div><a " + weight + " >" + result['tagName'] +"</a><span class='thumbsDownIcon' id ='" + tagId + "' style='display:block;cursor:pointer;' ></span></div></li>";
target.innerHTML += str;
}

google maps v3 formatting multiple lines of content in infoWindow

I am trying to create an infoWindow in google maps v3 which contains multiple lines of content. However the "\n" I am using to insert a newline doesn't seem to work. What is the recommended way to insert a newline?
see code:
//set content of infoWindow
window.setContent(inspStates[i].name+ "\n"+"total: "+inspStates[i].totalInsp+ "\n"+ info);
The easiest thing to do it wrap the content in a div or in a p and then use <br /> for line breaks.
So something like
//set content of infoWindow
window.setContent("<p>" + inspStates[i].name + "<br />" +
"total: " + inspStates[i].totalInsp + "<br />" + info +
"</p>");
Use HTML for the content, and put each line in its own paragraph. Line separation helps with readability, especially if any of the lines is long enough to wrap.
window.setContent(
"<p>" + inspStates[i].name + "</p>" +
"<p>Total: " + inspStates[i].totalInsp + "</p>" +
"<p>" + info + "</p>");

Resources