Dabo Home Page

Frequently Asked Questions by New Users


I have installed dabo but I run it I get: ImportError?: No module named dabo

ImportError: No module named dabo

OK you have downloaded Dabo. Now you try to run it and you immediately get an error: “ImportError: No module named dabo”

Python is reporting that the module dabo is not in it's search path “PYTHONPATH”. The easiest way to solve this is to add a file (dabo.pth) to your site-packages directory that directs (tells) python where to find the “dabo” module. Why a “pth” file? Because it is easier that screwing around with your environment variables like the “PYTHONPATH” which can be a pain on Mac OS and Windows.

To use a “pth” you have to create a file “dabo.pth” and save the file into the “site-packages” directory/folder. The “site-packages” directory is located below “the python root directory/lib”.

The “dabo.pth” file contain a single statement (one line) which tells python where to find Dabo. Note that this is the path to the folder that contains the dabo code, not the path to the dabo code itself. For example, let's say you are running Windows, and have installed Dabo in your "C:\someFolder\anotherFolder\projects\dabo". Inside this path is dApp.py, the biz, db, lib and ui folders, etc. Your dabo.pth file should contain:

"C:\someFolder\anotherFolder\projects\"

since that is where Python should look to find the dabo folder.

For windows: “C:\folder containing dabo” or “C:\myProject\”

For Linux: “/home/userName/projects/”


How Do I Use Sizers?

Working with Dabo sizers

Hopefully, you have reviewed the dabo sizers screencast parts 1 and 2. In the screencast Ed is very careful to tell you that a “sizer” is not a control. It is more of a set of rules that describe what will happen to controls/objects within it's (the sizer's) control. Although, Ed starts off with his definition of sizers though out the screencast he uses the term “sizer” losely. Often he really is referring to the place holder called the “slot” and not the sizer. But if you pay close attention I'm sure you will get a very good overall understanding of sizers.

We will work through a simple case and then build to a more involved case of using sizers. We will not be using the ClassDesigner program. I believe that doing a little hand coding will provide a better understanding of what the ClassDesigner is doing in the background. Also there are very few examples of hand coding a Dabo application and I'm sure it will help the reader understand Dabo a little better.

First we need a basic Dabo program:

import dabo
dabo.ui.loadUI('wx')


class MainForm(dabo.ui.dForm):
        def afterInit(self):
                self.Sizer = dabo.ui.dSizer("vertical")
                self.layout()

if __name__ == "__main__":
        app = dabo.dApp()
        app.MainFormClass = MainForm
        app.start()

The above program should open a form on your screen. You should see the standard dabo menu and nothing else in the body of the form. All this does is start the main Dabo loop and uses the class “MainForm” as the main form for the application.

The first thing to note is I added a method “afterInit” to the class. This is the recommended way to add code to a form. Yes there are other ways – but unless you have some over whelming reason DON'T use them. Note that I have added a sizer to the form “dabo.ui.dSizer("vertical")”. I even added a “self.layout()”. Yet when you run the application you see nothing in the body of the form. **This is because – sizers are “a set of rules to follow” and not controls such as buttons and labels**..

In the ClassDesigner when you add a sizer a place holder is added called a slot. Most of the settings you may see (in other screencasts) being done to the sizer (such as editing sizer properties) is really being done to the slot. I have said this fact three different ways. You may ask why I have said it so often. It is because most newbies mistake what is really happening when they follow the screencasts. And yes I made the mistake too.

So let's add a couple of controls to our form. But first let's explain a few of the parameters that are available. You may ask how I found the list. I didn't! I had to be told were I could find the list (which is in “dSizerMixin.py”). Like most open source projects the documentation is last thing to come. So as March 2007 the documentation is not much. So read the wiki, source code and ask questions on the mailing list to get answers.

Many of the methods for adding objects to sizers take the following parameters:

  • layout:
    • "expand": The object will expand to fill in the extra space (may also use "ex" or simply "x" to mean the same thing)
    • "fixed": The object will not be resized
    • "normal": The sizer will determine how to lay out the object. (default)
  • proportion: The relative space this object should get in relation to the other objects. Default has all objects getting 0, equal share.
  • halign, valign: Allows you to specify Horizontal and Vertical alignment independently. Alternately, you can specify both with a tuple passed to the alignment parameter.
  • alignment: The horizontal and vertical alignment of the object in the sizer.
    • This is a tuple: set it like ("left", "top") or ("center", "middle").
    • In most cases, though, passing the separate halign and valign parameters is preferable.
  • border: The width of the border. Default is 0, no border.
  • borderSides: A tuple containing the locations to draw the border, such as ("all") or ("top", "left", "bottom"). Default is ("all").
  • index: The index of the existing sizer item before which you want the object inserted.
  • For the most common usage of adding an object to the sizer, just do any of the following:
    • sizer.append(object)
    • sizer.append(object, "x")

Please replace the “afterInit” method with below.

        def afterInit(self):
                self.Sizer = dabo.ui.dSizer("vertical")
                lbl = dabo.ui.dLabel(self,Caption="My label",BorderWidth=2)
                txtbox = dabo.ui.dTextBox(self,RegID ="txtboxID",BorderWidth=2)
                hs=dabo.ui.dSizer('horizontal')
                hs.append(lbl,proportion=0)
                hs.appendSpacer(5)
                hs.append(txtbox,proportion=1)
                self.Sizer.append1x(hs)
                self.layout()

You should see a simple label and a textbox when you run the application. Try resizing the form. You will notice that the textbox grows (resizes) as you increase the width of the form.

The first thing to learn is when you ask a vertical sizer to expand it will fill the available horizontal space. And if I set a horizontal sizer to expand it will fill the available vertical space. Not what I'd call intuitive! So when you add a vertical sizer you are saying - Vertical sizer control the vertical sizing for me and I will set the horizontal via my parameters. And again it is just the opposite for horizontal sizers – Horizontal sizers control the horizontal size and I pass parameters to control the vertical space.

I'll explain my code:

self.Sizer = dabo.ui.dSizer("vertical") I try to work from the outside ->in. So I started by creating a vertical sizer that will contain all the controls at the end. Remember all I have done is create a RULE.

Next I create two controls. But I have not added them to a sizer yet. lbl = dabo.ui.dLabel(self,Caption="My label",BorderWidth?=2) txtbox = dabo.ui.dTextBox(self,RegID="txtboxID",BorderWidth?=2)

Now I create a horizontal sizer hs=dabo.ui.dSizer(horizontal)

Next I add the label control and I tell the horizontal sizer to create space just large enough to contain my control (proportion=0). I'm appending my label to the sizer. hs.append(lbl,proportion=0)

Next I add a spacer between the controls that is 5 pixels wide. Horizontal sizer spacers control the in the horizontal space for “spacers”. And Vertical sizers control vertical “spacers” hs.appendSpacer(5)

Next add the txtbox hs.append(txtbox,proportion=1)

Here you should take note that I added “proportion=1”. This is saying take the available horizontal space in proportion to other items in the sizer. So I have a label with a proportion=0 which means take only the space required of horizontal sizer to meet my needs. Then I add a textbox with a proportion=1 which means to “take the rest of the available horizontal space.

What if I had added four items to the horizontal sizer each with different proportion settings? Let's say: hs.append(lbl, proportion=0) hs.append(txtbox1,proportion=1) hs.append(txtbox2,proportion=3) hs.append(txtbox3,proportion=2)

then the sizer rules would do the following: divide the horizontal space into seven slots lbl would get a fixed space of the horizontal sizer or slot one (proportion=0). txtbox1 would get 1 slot. txtbox2 would get 3 slots. txtbox3 would get 2 slots. The horizontal sizer would fill the space based on the proportion settings

Next I add the vertical sizer to hold the horizontal rules and objects. self.Sizer.append1x(hs) The “1x” is a short cut to typing “self.Sizer.append(hs,1,x) which tells the sizer to “expand” Ok Now tell the sizer to arrange them selfs. self.layout()

Hopefully, this wiki entry, the screencast and the Dabo sizer demo have provided you with some understanding of sizers.