Ir al contenido principal

Ralsina.Me — El sitio web de Roberto Alsina

PyQt by Example (Session 3)

Designer is a Good Resource

Requirements

If you ha­ve not do­ne it ye­t, plea­se che­ck the pre­vious ses­sion­s:

All fi­les for this ses­sion are he­re: Ses­sion 3 at Gi­tHub

Designer is a Good Resource

To­day we are going to make our appli­ca­tion look be­tte­r, and in­tro­du­ce so­me new things, like re­sour­ce fi­le­s.

When we fi­nis­hed Ses­sion 2, our main win­dow looked like this:

/static/tut2-window3.png

Not a good looking appli­ca­tio­n.

The­re are se­ve­ral things wrong wi­th that pic­tu­re. Le­t's ta­ck­le them one at a ti­me, using Qt De­sig­ne­r.

Window Title

/static/tut3-wrong1.png

It is a Mai­nWin­do­w, but it's not ca­lled Mai­nWin­do­w!

Tha­t's just wron­g. Whi­le I ha­ve not yet cho­sen a na­me for this exam­ple appli­ca­tio­n, it's si­lly to ha­ve the win­dow ti­tle (and ta­sk­bar en­tr­y!) say "Mai­nWin­do­w"!

He­re's how you chan­ge ob­jet pro­per­ties in De­sig­ne­r.

Firs­t, you se­lect the ob­ject you want to mo­di­fy. You can do that by cli­cking on it, or by se­lec­ting it ­from the Ob­ject Ins­pec­to­r. For so­me wi­dge­ts one or the other is ea­sie­r. For exam­ple, it may be hard to find emp­ty spa­ce in a win­dow to cli­ck and se­lect the win­dow itsel­f, or cli­ck in a ve­ry sma­ll wi­dge­t, like a se­pa­ra­to­r. In tho­se ca­ses, just use the Ins­pec­to­r.

On­ce you ha­ve the ri­ght ob­ject se­lec­te­d, look at the Pro­per­ty Edi­to­r.

The­re is a list of pro­per­ties (ob­vious ;-) se­pa­ra­ted by ti­tles like "QOb­jec­t" or "QWi­dge­t". Do­n't wo­rry about tho­se ti­tles mu­ch, just look for what you nee­d, (it often is pre­tty ob­vious!).

In our ca­se it's the win­do­w­Ti­tle pro­per­ty.

/static/tut3-windowtitle.png

I wi­ll not be wri­ting the­se de­tai­led ex­pla­na­tions and pic­tu­res for ea­ch pro­per­ty. I trust you can find them if I te­ll you "The win­do­w­Ti­tle pro­per­ty of the Mai­nWin­dow Ob­jec­t".

Le­t's chan­ge that to "To­do­".

Application Icon

/static/tut3-wrong2.png

Ge­ne­ric ico­n.

The win­dow icon is the de­fault ge­ne­ric ico­n. This is im­por­tant be­cau­se it appears in the ta­sk­bar along the win­dow ti­tle, and if you are using it in so­me ope­ra­ting sys­te­ms or con­fi­gu­ra­tion­s, the user may on­ly see the ico­n!

Fin­ding icons to use in your appli­ca­tions is a big pro­ble­m. The­re are se­ve­ral things you can do:

  1. Hi­­re a gra­­phi­­cs de­­si­g­­ner to do icons for you.

    This, of cou­r­se, is ra­­ther ex­­pen­­si­­ve, spe­­cia­­lly if you are a ho­­­bb­­yis­­t.

  2. Sea­r­­ch the web and see what you can fi­n­­d.

    For exa­m­­ple, if I look for "to­­­do ico­­n" in google, I find man­­y, so­­­me rea­­lly ni­­ce. Ho­­we­­ve­­r, many of tho­­­se are su­b­­ject to co­­­p­­y­­ri­­gh­­t, so it's a be­­­tter idea to look for them in pla­­ces like wiki­­me­­dia co­­­m­­mons:

    http://upload.wikimedia.org/wikipedia/commons/b/bb/ToDo.jpg

    Or ma­­y­­be Open Cli­­part:

    http://openclipart.org/people/CoD_fsfe/CoD_fsfe_calendar.png

    But my point is: tho­­­se two icons are not all that awe­­so­­­me, and sea­r­­ching for a ni­­ce one is going to take a whi­­le. If you wi­­ll need 10 or 15 icons in your appli­­ca­­tio­­n, the pro­­­blem is even wo­r­se, be­­­cau­­se you want the icons to be co­n­­sis­­tan­­t!

  3. Find a set of KDE (or ma­­y­­be GNO­­­ME) icons you like, and ste­al co­n­­sis­­ten­­tl­­y. This is my pre­­fe­­rred so­­­lu­­tio­­n.

    I pre­­fer KDE icons be­­­cau­­se I use a KDE desk­­top but the­­re's no rea­­son to avoid GNO­­­ME icon the­­me­s. ­­You can find KDE icons in kde-­­look.org and GNO­­­ME icons at gno­­­me-­­look.org

    An added pe­­rk is that all KDE (or GNO­­­ME) icon the­­mes ha­­ve co­n­­sis­­tent in­­te­r­­nal na­­me­s. That way you can la­­ter on swi­­tch to ano­­­ther the­­me ve­­ry ea­s­­y.

Then the­re is the icons fi­le for­ma­t. If the icon the­me you like is avai­la­ble in SVG for­ma­t, tha­t's good. SVG is sca­la­ble, whi­ch means the icons wi­ll look good at all si­zes wi­thout the need to in­clu­de mul­ti­ple co­pies in di­ffe­rent si­zes.

In this tu­to­rial I wi­ll use icons from the Rei­nhar­dt se­t. Wh­y? I like the­m, and the sty­le is sim­ple enou­gh that I feel I can ha­ck a fi­tting icon using Inks­ca­pe if nee­ded (as I did in this ca­se, see be­lo­w).

This is how the fol­der icon from Rei­nhar­dt looks at di­ffe­rent si­zes, com­pa­red wi­th Sno­wish, a PNG icon the­me:

/static/tut3-compsize.png

The Rei­nhar­dt SVG fol­der ico­n: ni­ce at all si­zes. ­The Sno­wish PNG fol­der ico­n: from lo­ve­ly to blo­bl­y.

So, in shor­t: choose an icon the­me you like, and use on­ly icons from that the­me, if po­s­si­ble.

For this app's ico­n, I ma­de this out of a pie­ce of "ma­rk_a­s_ha­m.s­v­g" and so­me green co­lou­r:

/static/tut3-todo_icon.png

The real icon does­n't ha­ve tho­se cu­te sha­do­ws, tha­t's an arti­fact of my pre­tty-s­creens­ho­t-s­cript but I le­ft it be­cau­se it looks way too ni­ce ;-)

So, after all this icon ta­lk, how do we use it? We­ll... that nee­ds yet mo­re ta­lk, be­cau­se the­re are two wa­ys: use icon fi­les and use a re­sour­ce fi­le.

  • Icon fi­­le­s:

    In De­­si­g­­ne­­r, go to the wi­n­­do­­wI­­con pro­­­pe­r­­ty of Mai­nWi­n­­do­­w. Cli­­ck on the do­­wn arro­­w. Se­­lect "Choose Fi­­le". ­­The bad news: doing this makes pa­­cka­­ging and dis­­tri­­bu­­tion a bit ha­r­­der la­­ter on. ­­The wo­r­­se news: this wi­­ll not wo­­­rk wi­­th a SVG ico­­n. So fo­r­­get about it.

  • Re­­sou­r­­ce fi­­le:

    In De­­si­g­­ne­­r, go to the wi­n­­do­­wI­­con pro­­­pe­r­­ty of Mai­nWi­n­­do­­w. Cli­­ck on the do­­wn arro­­w. Se­­lect "Choose Re­­sou­r­­ce". You wi­­ll see a ra­­ther em­p­­ty wi­n­­do­­w.

/static/tut3-resource1.png

The emp­ty re­sour­ce win­dow

A re­sour­ce fi­le is a XML fi­le that con­tains re­fe­ren­ces to all the icons you want to use. La­te­r, this is com­pi­led to a py­thon mo­du­le, whi­ch you can use from your appli­ca­tio­n. As long as that py­thon mo­du­le is dis­tri­buted along wi­th the other­s, you wi­ll be fi­ne, so the­re is ne­ver a pro­blem of not fin­ding an ico­n, or wo­rr­ying about whe­re they are ins­ta­lle­d. Things wi­ll just wo­rk. So it's wor­th a bit of effort ge­tting this ri­gh­t.

He­re's how I do it:

  1. Cli­­ck on the pen­­cil bu­­tton in the top ri­­ght to get to the "E­­dit Re­­sou­r­­ce­s" wi­n­­do­­w.

    /static/tut3-resource2.png

    The em­p­­ty re­­sou­r­­ce edi­­tor wi­n­­dow

  2. Cli­­ck on the "New Re­­sou­r­­ce Fi­­le" bu­­tton in the bo­­­tto­­­m-­­le­­ft. Ca­­ll it "i­­co­n­s" (or wha­te­­ver you wan­­t)

  3. Cli­­ck in the "A­­dd pre­­fix" bu­­tton (fou­r­­th from the le­­ft). I ca­­lled my pre­­fix "/"

  4. Cli­­ck in the "A­­dd fi­­le­s" bu­­tton (fi­­fth from the le­­ft). Add to­­­do­­.s­­vg (fi­­na­­ll­­y!), cli­­ck OK.

Steps 1, 2 and 3 are on­ly nee­ded the first ti­me you use an ico­n. To add the icons we wi­ll use la­ter it's just step 4.

So now your re­sour­ce win­dow looks like this:

/static/tut3-resource3.png

The­re is an icon he­re!

Choose it, and tha­t's it, the win­dow has the ri­ght ico­n! We­ll ... not rea­ll­y.

First com­pi­le the UI. Re­mem­ber we need to do this whe­ne­ver we chan­ge so­me­thing using de­sig­ne­r!

$ pyuic4 window.ui -o windowUi.py

Then run the pro­gra­m:

$ python main.py
Traceback (most recent call last):
File "main.py", line 11, in <module>
    from windowUi import Ui_MainWindow
File "/home/ralsina/Desktop/proyectos/pytut/session3/windowUi.py", line 41, in <module>
    import icons_rc
ImportError: No module named icons_rc

This is because you also need to compile the icons.qrc file we created. This is done using pyrcc4:

$ pyrcc4 icons.qrc -o icons_rc.py

And the icon wo­rks now :-)

/static/tut3-window4.png

The lon­gest ex­pla­na­tion ever on how to chan­ge an ico­n, but it wo­rke­d!

Since it's boring having to remember to run pyuic4 and pyrcc4, I wrote a trivial script to handle it, build.sh. If you are in windows, a similar BAT file is trivial.

Lu­cki­l­y, the next two UI fixes are mu­ch sim­ple­r!

Tree Decorations

At the le­ft of our ta­sk list the­re is a tree de­co­ra­tio­n. Sin­ce this is not meant to be a tree, they are just a was­te of spa­ce. They can be re­mo­ved wi­th the rootIs­De­co­ra­ted pro­per­ty of the list wi­dge­t.

/static/tut3-wrong3.png

This is rea­lly a lis­t, not a tree.

Wide Margins

I thi­nk the de­fault mar­gins he­re (4 pixel­s) look old fas­hio­ne­d. I pre­fer 0 pixel­s. YM­M­V.

/static/tut3-wrong4.png

Per­so­nal tas­te: too wi­de.

You can chan­ge them in the la­you­t[­so­me­thin­g]­Mar­gin pro­per­ties of cen­tra­lWi­dge­t.

Extra Fixes

I al­so pre­fer to set the­se in our QTreeWi­dge­t:

  • all­­Co­­­lum­n­sS­ho­­w­­Fo­­­cus True

  • uni­­fo­r­­m­­Ro­­wHe­i­gh­­ts True (be­­­tter pe­r­­fo­r­­man­­ce for long lis­­ts)

  • so­r­­ti­n­­gE­­na­­bled True

  • al­­te­r­­na­­ti­n­­gRo­­w­­Co­­­lors True

See the do­cs to see what they do!

Finished!

So, after run­ning buil­d.s­h, this is how the app looks no­w:

/static/tut3-window5.png

A clea­ner look.

Coming Soon

In this ses­sio­n, we did no co­ding at all, we just wo­rked on de­sig­ner and gra­phi­cal de­tail­s. This may not seem too im­por­tant to you, if you are a har­dco­re co­de­r, but trust me: it is. Making apps as plea­sant to­ u­se and look at as you can wi­thin your po­s­si­bi­li­ties is ve­ry im­por­tant if you want the first re­lea­se to make any kind of im­pac­t. I lear­ned it the hard way by re­lea­sing ugly apps ;-)

It does­n't ma­tter if your gra­phi­cal de­sign ski­lls are li­mite­d, like mi­ne, try not to ove­rrea­ch and do your bes­t.

In ses­sion 4 we wi­ll di­ve in­to co­din­g, and make this app func­tio­nal for the first ti­me, in­tro­du­cing one of the nea­test fea­tu­res in Qt: Ac­tion­s.