I would like to add stylesheet options for a custom widget I have developed. We have extended the QPushButton to be a different colour and to flash when it is depressed. This has been done by adding a new property, background color down. And we set this in code. But I would like to set this instead using a Qt stylesheet entry, something like
QFlashingButton
{
background-color-down: yellow;
flashing-interval: 5;
}
I can see one way to do this, read out the stylesheet info using the stylesheet() method, then parse it for parameters relevant to my widget and set them. But I am wondering if there is some way to access the code Qt have themselves for processing stylesheets. At first sight of their code this seems perhaps not to be publically available.
As long as the parameter you want to control in the stylesheet is a QProperty, you can set it in the stylesheet using the syntax: qproperty-<PROPERTY_NAME>: <PROPERTY_VALUE>
I don't think property names can actually have dashes in them, so assuming your QProperties on your custom widget are actually backgroundColorDown and flashingInterval, then your stylesheet would look like:
QFlashingButton
{
qproperty-backgroundColorDown: yellow;
qproperty-flashingInterval: 5;
}
Related
Is there any solution to change the font color of QTableWidget's heads and items separately using Qt Designer? I want to make a complete design in Qt Designer without using code to set any styles
I wanted to add this as a comment but unfortunately my reputation is too low.
This should be possible by using a Stylesheet in the property editor. I can't test it right now but I assume it should look like these:
QTableWidget {
color: red;
}
QHeaderView {
color: blue;
}
Edit: I saw later that you asked without using code to set any styles. This is as far as I know not possible. But you can set the Style in property editor as I suggested, s.t. you can see the changes in the Qt Designer directly.
I know that QML does not support CSS styling like widgets do, and I have read up on alternative approaches to styling/theming:
https://qt-project.org/wiki/QmlStyling
http://www.slideshare.net/BurkhardStubert/practical-qml-key-navigation/34
Common for these approaches is that they require the developer to specify the parts of the QML that can be styled, either by binding to a property in a “styling QML file/singleton”, or by using a Loader to load a different QML component based on style name. What I would like is something that works like the "id" selector in CSS instead of the "class" selector, so that the individual QML files do not have to know whether they will be styled later on or not.
My current approach make all the QML files look similar to this (using approach in link 2):
Main.qml
Rectangle {
Id: background
color: g_theme.background.color
//g_theme is defined in root context and loaded dynamically
}
What I would like to do is:
Main.qml
Rectangle {
Id: background
color: “green” // default color
}
And then have a styling file that defines (or similar)
Main.qml #background.color: red
Is this possible at the moment, or something that is in the pipeline for a future Qt version, or will the preferred way of styling continue to be something similar to the approach described in the links above?
The preferred way isn't applying a style on default components, but deriving from these components to create pre-styled custom components.
What I do for my projects :
First, I create one centralized 'theme' file, as a JavaScript shared module :
// MyTheme.js
.pragma library;
var bgColor = "steelblue";
var fgColor = "darkred";
var lineSize = 2;
var roundness = 6;
Next, I create custom components that rely on it :
// MyRoundedRect.qml
import QtQuick 2.0;
import "MyTheme.js" as Theme;
Rectangle {
color: Theme.bgColor;
border {
width: Theme.lineSize;
color: Theme.fgColor;
}
radius: Theme.roundness;
}
Then, I can use my pre-styled component everywhere with a single line of code :
MyRoundedRect { }
And this method has a huge advantage : it's really object-oriented, not simple skinning.
If you want you can even add nested objects in your custom component, like text, image, shadow, etc... or even some UI logic, like color-change on mouse hover.
PS : yeah one can use QML singleton instead of JS module, but it requires extra qmldir file and is supported only from Qt 5.2, which can be limiting. And obviously, a C++ QObject inside a context property would also work (e.g. if you want to load skin properties from a file on the disk...).
It could also be helpful to look at Qt Quick Controls Styles
When using Controls Styles it is not necessary to explicitly assign each property in the target control. All properties can be defined in a separate [ControlName]Style component (e.g. ButtonStyle).
Then in target component (e.g. Button) you can just reference to style component in one line of code.
The only one downside here is that Style components are available for Qt Quick Controls only. Not for any Qt Component.
I have an ExtJS form that uses hbox-layout containers to create sentences that contain form inputs and there is a requirement to disable the form under certain conditions. The hbox-layout containers have a series of radio, text, checkbox, and textfield components. You can see an example on jsfiddle.
This is an answered question here on SO that doesn't fully work for me because if you disable something that isn't a field (like the text component I'm using) the disable style is different - it appears to mask the component instead of just graying out the text. When nested components are disabled, the mask gradients stack. Examples of this scenario are illustrated on this jsfiddle.
Is there a way to override how text handles its styling when it becomes disabled? I think that may be the easiest solution.
You'll have to handpick each style fix, but yes that's completely possible. Just addCls to give a hook for your CSS...
For example, using the following CSS:
.my-disabled-ct text {
opacity: .3;
}
You can give a similar disabled look both to fields and text items with the following code:
var rootCt = Ext.getCmp('lotsOfItems');
rootCt.query('field').forEach(function(field) {
field.disable();
});
rootCt.query('container').forEach(function(ct) {
ct.addCls('my-disabled-ct');
});
You should probably avoid using disable on field since Ext put a mask over them then (though you could probably hide it with CSS).
You could add the class and target the CSS directly to text items however, why not? In this case, you would query for 'text' and use addCls on them, with this kind of CSS:
text.my-disabled-cls {opacity: .3;}
That goes without saying that you'll restore your components look to "not disabled" by removing the CSS class with the same query and the removeCls method.
In my application, a User clicks on any widget of my program (which are at the time; dormant) and picks a color for it.
This color will then be added to a stylesheet for that particular widget.
However, when the program ends and is started again, I would like that particular widget to retain its stylesheet.
I would like to not have to hard code in stylesheets for every widget. In fact, I'd rather not even know which particular widget is having the stylesheet.
What I'd really like to do is have a single style sheet for the application, and code the new color just to the particular widget clicked.
(ie: If the User clicked on a QPushButton and chose a stylesheet of { color: red},
I would like just THAT QPushButton red and none others.
So, if that QPushButton had a variable name of 'Clicky',
to the QApplications stylesheet I would add:
'QPushButton#Clicky { color: red }' )
To do this and not have to hard-code it in for every widget,
I must somehow convert the variable name of my PyQt4 widgets to strings.
How can I do this?
Thanks!
(I've read it can be extremely difficult to get python variable names from their values;
Is there any other form of ID for a widget that can be added to a stylesheet?)
PyQt4
python 2.7.2
Windows 7
You need to first setObjectName("somename") before an object is named, then objectName() will work, or even better - findChild(), or findChildren()
Example
header:
QButton foo;
class:
foo = new QButton();
foo.setObjectName("MySuperButton");
Then, finally in your QSS..
#MySuperButton {
background: black;
}
This also works similarly to CSS with
QButton#MySuperButton {
background: red;
}
The logic behind why you'd want to set multiple object names similarly (for different objects), or use the granularity of only one type of widget with a specific name is also pretty much the same as CSS.
I have a class that inherits QStandardItem and I put the elements in a QTreeWidget. The class receives notifications from the outside and I want to change the background color of the item based on what happened.
If I do not use stylesheets, it works just fine, like this:
void myClass::onExternalEvent()
{
setBackground(0, QColor(255,0,0)));
}
However, as soon as I put a stylesheet on the QTreeWidget, this has no effect : the stylesheet seems to override the setBackground() call.
So I tried :
void myClass::onExternalEvent()
{
this->setStyleSheet("background-color: red");
}
but this is probably all wrong, it changed the color of some other element on my screen, not sure why.
Does anyone have an idea on how I can alter the background color like with setBackgroundColor but still be able to use stylesheet on my QTreeWidget?
Palettes propagate to the children of a widget, and it's bad to mix and match style-sheet controls and native controls (I do not have a citation for the latter handy, but I have read it in the QT docs somewhere).
That being said, try setting setAutoFillBackground(false) on your QStandardItem derived class.
EDIT: Sorry - also, are you specifying the QTreeWidget in the stylesheet or just setting "background-color:"? If you specify the QTreeWidget only in the stylesheet that might take care of it as well.
QTreeWidget { background-color: white; }
But I think you still have to set the autoFillBackground(false).