Hi all,
Thought I’d share some habits I’ve grown to take for granted over the years, and encourage you to share yours, with the goal to make us all better developers. :)
For starters, let me just say that if you aren’t styling via CSS, you’re missing out. Python is amazing at many things but styling is not of them, and compared to CSS it’s a nightmare. I still remember the day when I styled via overriding paintEvent, taming QStyledItemDelegate to my will, abstracting away, trying to make things simpler because clearly, there had to be a better way. This is that better way.
I should also mention that though CSS will blow the minds of those who haven’t given it a shot, CSS is applicable outside of Python too, which means that the usergroup you’ll get when googling go beyond Python into Web; which is a huge resource when it comes to creating pretty UIs.
Taken further, the next incarnation of Qt GUI creation, QML, is also heavily based on the same paradigm (i.e. “declarative” as opposed to “imperative”. Google it) which means you’ll future proof your knowledge by wrapping your head around the differences.
In short, styling and declarative languages make a much better couple than styling and imperative languages.
Now, onwards!
Assuming you’re already convinced CSS is for you and your software, here is a problem you might encounter along the way - CSS often contain lots of duplicate code.
As CSS is a much less intelligent “language” with much less syntactic sugar, you’ll inevitably end up with lots of duplicated keywords and whole stacks of boiler-plate copy/paste material.
Sass is a superset of CSS, a code-generator, essentially filling in for what CSS is missing; nesting, variable definitions and encapsulation, and most importantly, a nicer syntax, one that actually cares about the visual layout of your code; just like Python. Behold:
/*Regular CSS*/
QScrollBar:vertical {
background-color: transparent;
border-top: none;
margin: 0px; }
QScrollBar:horizontal {
background-color: transparent;
border-left: none;
border-right: none;
margin: 0px; }
QScrollBar:horizontal::handle {
margin: 3px;
border-radius: 4px;
background: hsva(0, 0, 100%, 10%);
min-height: 20px;
min-width: 20px; }
QScrollBar:horizontal::add-line {
background: white;
width: 0px;
height: 0px;
subcontrol-position: bottom;
subcontrol-origin: margin; }
QScrollBar:horizontal::sub-line {
background: white;
height: 0px;
width: 0px;
subcontrol-position: top;
subcontrol-origin: margin; }
QScrollBar:horizontal::add-page, QScrollBar:horizontal::sub-page {
background: none; }
// Sass
QScrollBar
&:vertical
background-color: transparent
border-top: none
margin: 0px
&:horizontal
background-color: transparent
border-left: none
border-right: none
margin: 0px
&::handle
margin: 3px
border-radius: 4px
background: hsva(0, 0, 100%, 10%)
min-height: 20px
min-width: 20px
@mixin line-mixin
background: white
width: 0px
height: 0px
subcontrol-position: bottom
subcontrol-origin: margin
&::add-line
@include line-mixin
&::sub-line
@include line-mixin
&::add-page, &::sub-page
background: none
That warm feeling in your stomach right now is called “love”. But that’s nothing.
// General colors
$dark-color: rgb(25, 25, 25)
$mid-color: rgb(50, 50, 50)
$bright-color: rgb(75, 75, 75)
$dimmed-color: rgb(210, 210, 210)
$lowkey-color: rgb(190, 190, 190)
// Special purpuse colors
$red-color: hsl(0, 50%, 50%)
$highlight-color: hsl(35%, 50%, 80%)
// Encapsulation of re-usable sets of properties
@mixin outset
// Apply an overall soft outwards border
border-style: solid
border-width: 1px
border-left-color: lighten($bright-color, 5%)
border-right-color: darken($bright-color, 5%)
border-top-color: lighten($bright-color, 5%)
border-bottom-color: darken($bright-color, 5%)
@mixin inset
// Apply an overall soft inwards border
border-style: solid
border-width: 1px
border-left-color: darken($mid-color, 5%)
border-right-color: lighten($mid-color, 20%)
border-top-color: darken($mid-color, 5%)
border-bottom-color: lighten($mid-color, 20%)
// Class assignments
Body
@include outset
background-color: $dimmed-color
Footer
@include outset
background-color: $lowkey-color
Header
@include inset
&:hover
color: hsva(0, 0, 100%, 80%)
padding: -2px
border: 2px dashed hsva(0, 0, 100%, 10%)
There are a number of ways you can get this hooked up with your sublime, here’s my process:
stylesheet.scss --> stylesheet.css
Initially, you might be tempted to
For my purposes, their names remain identical apart from their extension and in this way I’m never reminded of the fact that I’m generating code.
Finally, since we’re talking Sublime specifically, here’s a potential build script you might want to hack away with:
SASS.sublime-build
{
"cmd": ["sass", "$file:${file_path}/${file_base_name}.css", "--stop-on-error", "--no-cache"],
"selector": "source.sass, source.scss, source.css",
"line_regex": "Line ([0-9]+):",
"shell": true
}
It isn’t all roses of course.
No gradients
Some operators are unique to Qt, like qlineargradient, and these won’t work. I have yet to find a need for them, but this is the case.
Querying properties set in CSS via Python
This applies to working with CSS in general throughout Qt. The question you’ll be faced with is “When is my CSS applied, and when can I count on values returned from querying its properties?” If this is you, let me know and I’ll show you the way.
Animation
CSS has animation capabilities, but these are unfortunately not supported by Qt. Hint: This is where QML comes in.
Oki, your turn.
Best,
Marcus
style1 = "{someProperty: 1; someProperty2: 1; color: $(stateColor)s}"
style2 = "{someProperty: 2; someProperty2: 2; color: $(stateColor)s}"
...
if condition: widget.setStyleSheet(style2 % context)
--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAFRtmOAqCYvwEeBS7516cX5QeknGhvPtwZbTuR1uoL7CHAwZaw%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
pix = QtGui.QPixmap("/path/to/my/image.png")
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file alias="images/myimage.png">/path/to/image.png</file>
</qresource>
</RCC>
import myresources
...
pix = QtGui.QPixmap(":/images/myimage.png")
from ModelTest import ModelTest
...
myModel = MyCustomModel()
myModel.populate()
test = ModelTest(myModel)
print "If you are reading this...I didn't fail hard"
def show_a_dialog(self):
# self our main window
d = MyDialog(self)
...
d.show()
# If your widget has a closeEvent
d.setAttribute(QtCore.Qt.WA_DeleteOnClose)
d.show()
# or just telling it to delete later if you are using exec_
d.exec_()
d.deleteLater()
import inspect
def trace():
frames = (str(f[1:4]) for f in inspect.getouterframes(inspect.currentframe())[1:])
print "\n".join(frames)
print '\n'
if __name__ == "__main__": if it needs to have entry-point executable code.