Using Widget Style Sheets

We have already seen many examples of customizing widgets by changing their properties. Some of these have affected widget behavior, such as setting a QSpinBox's range, and others have affected widget appearance, such as setting a QLabel's frame. Qt 4.2 introduced a new widget property, the style sheet property. This property holds a QString and uses a syntax borrowed from HTML's CSS (Cascading Style Sheets).*

The screenshot in Figure 11.1 shows a dialog that has a style sheet set. Style sheets apply to the widget they are set on, and all the widget's child widgets. In this case, we have set the combobox to use dark blue text and the line edits to used dark green text. We have also set line edits that are "mandatory" to have a yellow background.

Qlabel Border
Figure 11.1 A dialog customized using a style sheet

No PyQt widget has a "mandatory" property, but from Qt 4.2 it is possible to add properties dynamically to QObjects. Note that Qt properties are different from Python properties—for example, they are accessed using property() and setProperty(). From PyQt 4.2, the QtCore.pyqtProperty() function can be used to create properties that are both Python and Qt properties at the same time.

self.lineedits = (self.forenameEdit, self.surnameEdit, self.companyEdit, self.phoneEdit, self.emailEdit) for lineEdit in self.lineedits:

lineEdit.setProperty("mandatory", QVariant(True))

★Style sheets are not officially supported on Mac OS X, so they may not behave predictably. They are expected to be supported from Qt 4.4 onward.

self.connect(lineEdit, SIGNAL("textEdited(QString)"), self.updateUi)

The preceding code is from the form's initializer. It adds a "mandatory" property to those line edits that we do not want the user to be able to leave blank. All Qt properties are held as QVariants. The signal-slot connections are discussed shortly.

We have created a style sheet for the widget as a class static variable, and set it on the form toward the end of the constructor. We could just as easily have read the style sheet from a file (since it is simply plain text), or from a PyQt resource.

StyleSheet = """ QComboBox { color: darkblue; } QLineEdit { color: darkgreen; } QLineEdit[mandatory="true"] {

background-color: rgb(255, 255, 127); color: darkblue;

ii II II

self.setStyleSheet(ContactDlg.StyleSheet)

The style sheet syntax essentially consists of "selectors" and property name: value pairs. In the preceding snippet, the first line has a selector of QComboBox, which means that its property values will apply to any QComboBox or QComboBox subclass that is a child of the widget on which the style sheet is set. In this case, the effect is to set the text color to dark blue. The second selector is a QLineEdit, and this works similarly.

The third selector is more specific: It specifies both a class, and a property of that class whose state must be matched. In other words, this third selector will apply only to QLineEdit and QLineEdit subclasses that have a "mandatory" property, and where that property's value is True. For such cases, the background color is set to yellow (specified as an RGB triple), and the text color is set to dark blue.

The dialog is slightly subtler than it may at first appear. This is because the company line edit is mandatory only if the category combobox is set to "Business". To achieve this we need the signal-slot connections shown earlier, and one other connection:

self.connect(self.categoryComboBox, SIGNAL("activated(int)"), self.updateUi)

All the connections are to the updateUi() method:

def updateUi(self):

mandatory = self.companyEdit.property("mandatory").toBool() if self.categoryComboBox.currentText() == "Business": if not mandatory:

self.companyEdit.setProperty("mandatory",

QVariant(True))

elif mandatory:

self.companyEdit.setProperty("mandatory", QVariant(False)) if mandatory != \

self.companyEdit.property("mandatory").toBool(): self.setStyleSheet(ContactDlg.StyleSheet) enable = True for lineEdit in self.lineedits:

if lineEdit.property("mandatory").toBool() and \ lineEdit.text().isEmpty(): enable = False break self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(enable)

If the user has changed the category, we must reapply the style sheet to force the widgets to be restyled. This ensures that the background of the company line edit is correctly set to white or yellow depending on whether it is mandatory. Unfortunately, on slower machines, there is a slight flicker when the style sheet is reset—for this reason we have slightly long-winded code to ensure that the style sheet is reapplied only if necessary. Reapplying a style sheet is not necessary for changes to "pseudostates" such as enabled, checked, and hover.

Style sheets have a much richer syntax, and are much more powerful, than this simple example might suggest. For example, if we precede a selector with a dot, as in .QLineEdit, the selector will apply only to the class specified and not to its subclasses. If we want to a selector to apply to one specific widget we can call setObjectName() on the widget and then use that name as part of the selector. For example, if we had a button with an object name of "findButton", the selector that would apply only to that button would be QPushButton#findButton.

Some widgets have "subcontrols". For example, a QComboBox has an arrow that the user can click to make its list drop down. Subcontrols can be specified as part of the selector—for example, QComboBox::drop-down. Pseudostates can be specified using a single colon—for example, QCheckBox:checked.

In addition to setting colors, style sheets can also be used to set fonts, borders, margins, paddings, and backgrounds. One quick and easy way to experiment with simple style sheets is to run Qt Designer, create a new form, drag some widgets onto the form, and then enter and edit a style sheet for the form.

A style sheet can be set on a particular widget in a form, or on the form (QDialog or QMainWindow) itself. In either case, the style sheet will automatically be applied to any child widgets. It is also possible (and quite common) to set a single style sheet for the entire application, in which case we set it on the QApplication object.

Was this article helpful?

0 -3
Tube Jacker

Tube Jacker

Download Tube Jacker And Discover Everything You Need To Know About Jacking Unlimited Traffic From The Video Giant. The drop dead easy way to create winning video campaigns that will FLOOD your website with unstoppable FREE traffic, all on complete and total autopilot. How to exploit a sneaky method of boosting exposure and getting your videos to the top of Google within 72 hours, guaranteed.

Get My Free Ebook


Responses

  • Elsa Utrio
    How to use qt style sheets pyqt?
    27 days ago

Post a comment