Python qt: colours/stylesheets

From wikinotes

Style Methods

Stylesheets (QSS)

References
http://doc.qt.io/qt-4.8/stylesheet-reference.html Official Qt Documentation for QSS files


QSS is is Qt's version of CSS. QSS can be applied to a specific control, the QApp, or just about anything else. Just like CSS, it is inherited by all children unless the children get their own stylesheet.

QSS stylesheets or QSS set by using the widget.setStyleSheet() will always override any other colouring set to the object. QLabels are always lower in the heirarchy. However, it is important to note that QSS information cannot at this time be retrieved once applied. You must manage your stylesheets/settings independent of the program.

qssFile = open('/home/will/dev/test.qss').read()
QApp    = newUI.initQApp()
myWin   = MyWindowFunc()
myWin.setStyleSheet(qssFile)									## If planning for compatibility with Maya,
																		## apply the stylesheet to the window. (you don't
																		## wan't to mess with Autodesk's QApp settings)
/* Sample QSS */


*::hover {
	/* Applies to All Controls when hovered over */
	color:            #ffffff;
	background-color: #000000;
}

QPushButton::hover {
	/* Settings overridden for QPushButtons */
	background-color: #333333;
}

QPushButton::down-arrow {
	/* Example Image Settings */
	image: url(  ./image.png );			/* image is in same dir as file sourcing it */
	image: url( ../image.png );			/* image is one dir above file sourcing it  */
	image: url( /path/to/image.png );	/* fixed path */
}

Testing Icon-Overrides in QSS

If you are overriding one of the standard-icons used by several of Qt's widgets, you can isolate it with a simple window like this.

from PySide import QtCore, QtGui
from libpyside import newUI

class TestWin( newUI.NewWindow ):
    def main(self):
        layout = QtGui.QVBoxLayout()

        widget = QtGui.QPushButton()
        style  = widget.style()
        icon   = style.standardIcon(QtGui.QStyle.SP_ArrowRight)

        widget.setIcon( icon )

        layout.addWidget( widget )
        self.setLayout( layout )

if __name__ == '__main__':
    with newUI.WithQApp():
        win = TestWin()
        win.display()


Stylesheet Properties

See: https://wiki.qt.io/Dynamic_Properties_and_Stylesheets

You cannot retrieve QSS attributes at runtime. You can however create properties, and apply alternative styles to objects with those properties.

QLineEdit[changed=true] {
  background-color: yellow;
}
# change a widget's property, and repaint
lineedit = QtWidgets.QLineEdit()
lineedit.setProperty('changed', True)
lineedit.style.unpolish()
lineedit.style.polish()



QStyles

Reference
https://srinikom.github.io/pyside-docs/PySide/QtGui/QStyle.html Official QStyles Doc


QStyles are css encapsulated into objects. Here you'll find ways of simulating the stylesheets used by a variety of operating systems. I haven't used these very much at this time.

btn   = QtGui.QPushButton( 'test button' )
btn.setStyle(QtGui.QStyleFactory.create('motif'))

btn2   = QtGui.QPushButton( 'test button' )
btn2.setStyle(QtGui.QStyleFactory.create('cde'))

QPalettes

QPalettes are Qt's internal method of dealing with colours. This is generally where selection colours, disabled colours, etc. originate. QPalettes are divided into roles, and groups. Because of their incompatibility with QSS stylesheets I do not intend to use them very much. It should be noted that colours set using QPalettes can be retrieved, which is a feature that is unique from the other options.

### Get QApplication's Default BG-Colour (as set by Qpalette)
QApp         = QtCore.QCoreApplication.instance() 
palette      = QApp.palette()
colorRole    = getattr( palette.ColorRole, 'Window' )
defaultColor = palette.color( colorRole ).rgba()

### Set a control's colour using QPalettes
(see old commits on layoutList.py)

Styling Widgets

Contol Colours in QT are done with QSS. You can use an external QSS File that is applied to the entire QApp/Window etc, but it will prevent the following changes to be observed.


Per-Control QSS

btn = QtGui.QPushButton('test Button')                                 ## The whole background colour is #112244
btn.setStyleSheet("background-color: #112244")

## OR word-specific colouring 
btn = QtGui.QPushButton('<font color="red">test</font> Button')        ## test is in red, the rest of the line is default

QWidget Background Colour

This allows you to set the background colour of the margin-space in a QWidget. (space around buttons, controls, text, etc).

a = QtGui.QWidget()

pallet = QtGui.QPalette()
pallet.setColor( a.backgroundRole(), QtGui.QColor( '#3333AA' ))

a.setAttribute( QtCore.Qt.WA_StyledBackground, 1 )
a.setPalette(pallet)
a.setAutoFillBackground(1)

get Default QApp Colours

import PySide

a = QtGui.QWidget()                                       ## Create Widget (that we will be colouring)

Qapp      = PySide.QtCore.QCoreApplication.instance()
palette   = Qapp.palette()
colorRole = getattr( palette.ColorRole, 'Window' )        ## This returns a shiboken obj, getattr gets the python obj
color     = palette.color( colorRole )

pallet.setColor( a.backgroundRole(), color )              ## Set Colour

reference palette colous in stylesheet

btn = QtWidgets.QPushButton()
btn.setStyleSheet(
    'background-color: palette(highlight);'
)