HowToUseAGridSizer

From Dabo Wiki
Jump to: navigation, search

How To Use a dGridSizer

The easiest way to make use of a dGridSizer has to use the ClassDesigner. It is a piece of genius that will take the headache out of designing a form to meet your desires.

But if you want to do it in code, or perhaps just to understand it a little better, this is what you need to know.

What is a dGridSizer?

dGridSizer is a sizer that can lay out items in a virtual grid arrangement. Items can be placed in specific row/column positions if that position is unoccupied. You can specify either MaxCols or MaxRows, and then append items to the grid sizer; it will place them in the first open row/col position, until the Max* dimension is reached; after that, it starts over in the next row/col. This allows for easily adding items without having to explicitly track each one's row/col. For example, if I have a bunch of labels and edit controls to add, and I want them in a grid arrangement with labels on the left and controls on the right, I can set MaxCols to 2, and then append label, control, label, control, ..., and the dGridSizer will automatically arrange them as desired.

What you need to do:

  1. Create a form with a sizer on it.
  2. Create an instance of a grid sizer.
  3. Create instances of the controls you want to place in the cells of the grid.
  4. Append the controls to the grid.
  5. Append the dGridSizer to your parent control.

Example:

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


class MainForm(dabo.ui.dForm):
    def afterInit(self):
        # Create a initial sizer to add to
        self.Sizer = dabo.ui.dSizer("horizontal")
        # Create the dGridSizer with gaps between the rows and columns
        gs = self.mygrid = dabo.ui.dGridSizer(HGap=12, VGap=15)
        # Create some labels and textboxes
        self.lblFirst = dabo.ui.dLabel(self, Caption="First Name:")
        self.txtboxFirst = dabo.ui.dTextBox(self)
        self.lblSecond = dabo.ui.dLabel(self, Caption="Last Name:")
        self.txtboxSecond = dabo.ui.dTextBox(self)

        # Append the controls to the dGridSizer by specifying location cell (in this example)
        gs.append(self.lblFirst, row=0, col=0, halign="right")
        gs.append(self.txtboxFirst, row=0, col=1)
        gs.append(self.lblSecond, row=1, col=0, halign="right")
        gs.append(self.txtboxSecond, row=1, col=1)

        # Append the sizer to its parent. To show it halfway down,
        # we set 'valign' to 'middle'.
        self.Sizer.append(gs, proportion=1, valign="middle")


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

Now if you prefer to just fill up the rows without having to specifically index the locations, you can write the MainForm class from above, this way:

class MainForm(dabo.ui.dForm):
    def afterInit(self):
        # Create a initial sizer to add to
        self.Sizer = dabo.ui.dSizer("horizontal")
        # Create the dGridSizer with only 2 Columns
        gs = self.mygrid = dabo.ui.dGridSizer(MaxCols=2, HGap=12, VGap=15)

        # Create some labels and textboxes
        self.lblFirst = dabo.ui.dLabel(self, Caption="First Name:")
        self.txtboxFirst = dabo.ui.dTextBox(self)
        self.lblSecond = dabo.ui.dLabel(self, Caption="Last Name:")
        self.txtboxSecond = dabo.ui.dTextBox(self)


        # Append the controls to the dGridSizer by making use of the MaxCol setting (in this example)
        # As each row fills, it automatically moves to the next row.
        gs.append(self.lblFirst, halign="right")
        gs.append(self.txtboxFirst)
        gs.append(self.lblSecond, halign="right")
        gs.append(self.txtboxSecond)

        # Append the sizer to its parent
        self.Sizer.append(gs, proportion=1, valign="middle")

How to make an expandable column on a dGridSizer

You need to understand the previous two examples first.

Here is what you do:

Define a dGridSizer as you did above but with two differences:

The append() argument to dGridSizer takes an optional layout parameter; by default this is "normal", which means just layout the control using its natural size, but if you want the control to expand to take up any available space, pass this parameter as "expand" (or simple pass "x", which is interpreted as an alias for "expand"). Once the control has been appended to the dGridSizer, the column now exists as far as the grid sizer is concerned, and you can call the setColExpand() method for the column that you require. This causes all controls in the specified column to expand, providing that control had the "expand" setting when you added it to the sizer. It also allows the grid sizer to expand that column to use the available width.

NB: Add the controls to the grid sizer FIRST, then call setColExpand() for whatever columns you want to be "growable". It is good practice to make the setColExpand() calls at the end of the code that defines the grid sizer.

The Signature for the method is: setColExpand(self, expand, colNum, proportion=0)

  • expand is a boolean argument. Passing True enables the column to expand; False disables it.
  • colNum is the single column that you are setting this for. You can also replace colNum with a tuple of column numbers, and it will set all of them to the passed value (remember that column numbers start at 0). And as an even further convenience, you can pass all for this argument, and it will enable the expanded state for all columns.
  • proportion in an integer value that affects the relative weighting of the column compared to the other expandable columns. In other words, if you have two expandable columns, but want the second one to appear twice as wide as the first, you'd pass proportion=1 for the first, and proportion=2 for the second. If you simply accept the default of 0 for all columns, they are sized equally.

Example 1:

# Define the control as usual
self.txtboxFirst = dabo.ui.dTextBox(self)
# Append the control to the dGridSizer, but add the parameter to "expand".
self.mygrid.append(self.txtboxFirst, "expand", row=0, col=1, BorderStyle="sunken")
# Make Column 1 expandable (growable) for any of its controls already set to expand.
self.mygrid.setColExpand(True, 1)

Example 2:

# Make colums 1 and 2 expandable by specifying multiple columns in a tuple.
self.mygrid.setColExpand(True, (1, 2))

Example 3:

# Make all colums expandable.
self.mygrid.setColExpand(True, "all")

Here is the entire example from above with the dTextBox control on the first line made expandable.

Example 4:

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


class MainForm(dabo.ui.dForm):
    def afterInit(self):
        # Create a initial sizer to add to
        self.Sizer = dabo.ui.dSizer("horizontal")
        gs = self.mygrid = dabo.ui.dGridSizer(HGap=12, VGap=15)
        # Define some Controls e.g. labels and textboxes
        self.lblFirst = dabo.ui.dLabel(self, Caption="First Name:")
        self.txtboxFirst = dabo.ui.dTextBox(self)
        self.lblSecond = dabo.ui.dLabel(self, Caption="Last Name:")
        self.txtboxSecond = dabo.ui.dTextBox(self)

        # Append the controls to the dGridSizer by location (in this example)
        gs.append(self.lblFirst, row=0, col=0, halign="right")
        # This next control will be set to expand
        gs.append(self.txtboxFirst, "expand", row=0, col=1)
        gs.append(self.lblSecond, row=1, col=0, halign="right")
        # This textbox will not expand
        gs.append(self.txtboxSecond, row=1, col=1)
        # Now set column 1 to expand
        gs.setColExpand(True, 1)

        # Append the sizer to its parent
        self.Sizer.append(gs, proportion=1, valign="middle")


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

The equivalent methods also exist for Rows: setRowExpand().

These notes written by Fraser Burns and amended by those who know more.