布局管理

当很多GUI工具包要求你使用绝对位置来精确地摆放窗括部件时,GTK+使用了一个不同的方式。 不需要指定每一个窗口部件的位置和大小,你可以以行、列或者表格来摆放你的窗口部件。 你的窗口的大小可以自动的决定——基于其包含的窗口部件的尺寸。并且, 部件的尺寸是由其包含的文本数或者你指定的最大最小尺寸或者你指定在部件之间共享的空间大小来决定的。 你可以通过指定每一个部件的填充大空间小来设置你自己的布局。当用户操作窗口时GTK+根据这些信息可以很平滑地重新摆放和改变这些部件的大小。

GTK+使用 容器 来分层次地管理这些窗口部件。这些容器对于终端用户来是是不可见的,容器一般插入到窗口里,或者放入到其他容器里以布局组件。 有两种类型的容器:单孩子容器—— Gtk.Bin 的子孙和多孩子容器—— Gtk.Container 的子孙。 最常用的容器是水平和垂直的Box盒子(Gtk.Box),表格(Gtk.Table)和网格(Gtk.Grid)。

Boxes盒子

Box盒子是不可见的容器,我们可以把我们的窗口控件打包近Box盒子。当将窗口控件打包进水平(horizontal)的盒子时, 这些对象水平地插入到盒子中来,根据使用 Gtk.Box.pack_start() 或者 Gtk.Box.pack_end() 可能是从左到右页可能是从右到左。而对于一个垂直的盒子,对象可能是垂直地从上到下或相反方向插入到盒子里来。 你可以使用任何组合方式的盒子(放在其他盒子中或者挨着其他盒子)来创建任何你想要达到的效果。

Box 对象

class Gtk.Box([homogenous[, spacing]])

Gtk.Box 的矩形区域被组织为或者是单行或者是单列的子窗口部件——这依赖于 “orientation”属性被设置为 Gtk.Orientation.HORIZONTAL 或者 Gtk.Orientation.VERTICAL 。 如果 homogeneous 属性为 True ,盒子中所有的部件大小将相同,它们的大小由最大的那个部件决定。如果不设置,默认为 Falsespacing 指子窗口部件之间默认的像素值。如果忽略,则不填充空白,即 spacing 为0。 默认子窗口部件被组织为一行,即“orientation”属性为 Gtk.Orientation.HORIZONTALGtk.Box 使用了 打包(packing) 的概念。打包指将一个窗口部件的一个引用添加到一个 Gtk.Container 容器中。 对于一个 Gtk.Box ,有两个不同的位置:盒子的开始与结尾。如果“orientation”属性设置为 Gtk.Orientation.VERTICAL , 开始是盒子的顶端结尾是底端。如果“orientation”属性设置为 Gtk.Orientation.HORIZONTAL ,左端是开始右端是结尾。

pack_start(child, expand, fill, padding)

添加 child 到盒子中,打包到其他已经打包到盒子开始的 child 后面。 child 应该是一个 Gtk.Widget 类型。 expand 参数设置为 True 允许 child 占用所有其可以占用的空间。如果设置为 False ,盒子就会萎缩到与孩子控件一样的大小。 如果 fill 参数设置为 Truechild 会占用所有可用的空间,与盒子的大小相等。 只有 expand 设置为 True 时才有效。一个孩子总是占用垂直盒子的全部高度或者一个水平盒子的所有宽度。这个选项会影响其他的尺寸。 padding 是指在孩子和其“邻居”之间的额外的空白像素点,会覆盖全局的 “spacing” 设定。如果一个 child 控件在盒子的一个边缘, 那么填充的像素也会存在于孩子与边缘之间。

pack_end(child, expand, fill, padding)

添加一个 child ,打包到盒子的末尾。会放在所有已经打包到末尾的孩子之前。

参数与 pack_start() 相同。

set_homogeneous(homogeneous)

如果 homogeneous 设置为 True ,盒子中所有的空间大小相同,尺寸依赖于最大的孩子控件的尺寸。

例子

   轻松一下,将上面那个有例子扩展为包含两个按钮。

../../_images/layout_box_example.png
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from gi.repository import Gtk

class MyWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="Hello World")

        self.box = Gtk.Box(spacing=6)
        self.add(self.box)

        self.button1 = Gtk.Button(label="Hello")
        self.button1.connect("clicked", self.on_button1_clicked)
        self.box.pack_start(self.button1, True, True, 0)

        self.button2 = Gtk.Button(label="Goodbye")
        self.button2.connect("clicked", self.on_button2_clicked)
        self.box.pack_start(self.button2, True, True, 0)

    def on_button1_clicked(self, widget):
        print "Hello"

    def on_button2_clicked(self, widget):
        print "Goodbye"

win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

首先,我们创建了一个水平的盒子容器,并设置孩子之间有六个像素的空白填充。并将这个盒子容器设置为顶层窗口的孩子。

        self.box = Gtk.Box(spacing=6)
        self.add(self.box)

接下来我们一次向盒子容器中添加了两个不同的按钮。

        self.button1 = Gtk.Button(label="Hello")
        self.button1.connect("clicked", self.on_button1_clicked)
        self.box.pack_start(self.button1, True, True, 0)

        self.button2 = Gtk.Button(label="Goodbye")
        self.button2.connect("clicked", self.on_button2_clicked)
        self.box.pack_start(self.button2, True, True, 0)

Gtk.Box.pack_start() 添加的孩子从左到右依次放置,而 Gtk.Box.pack_end() 添加的孩子从右到左依次放置。

Grid网格

Gtk.Grid 是一个将其孩子控件按照行列来放置的容器,但是在构造函数中你不用指定网格的大小。 使用 Gtk.Grid.attach() 来添加孩子。他们可以占用多行活在个多列。 也可以使用 Gtk.Grid.attach_next_to() 来挨着一个孩子添加另一个孩子。

Gtk.Grid 如果使用 Gtk.Grid.add() 可以像使用 Gtk.Box 那样一个孩子挨着一个孩子放置——以“orientation”属性指定的方向(默认为 Gtk.Orientation.HORIZONTAL )。

Grid 对象

class Gtk.Grid

创建一个新的网格控件。

attach(child, left, top, width, height)

向网格中添加一个孩子。

孩子的位置根据单元格左边( left )和上边( top )单元格的书目来决定,孩子的大小(占用几个单元格)由 width 和 height 来决定。

attach_next_to(child, sibling, side, width, height)

挨着其 兄弟(sibling) 添加一个 childside 决定添加到该兄弟的哪一边,可以是以下其中之一:

  • Gtk.PositionType.LEFT
  • Gtk.PositionType.RIGHT
  • Gtk.PositionType.TOP
  • Gtk.PositionType.BOTTOM

Widthheight 决定了孩子可以占用几个单元格。

add(widget)

根据“orientation”决定的方向添加一个窗口部件。

Example

../../_images/layout_grid_example.png
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from gi.repository import Gtk

class GridWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="Grid Example")

        grid = Gtk.Grid()
        self.add(grid)

        button1 = Gtk.Button(label="Button 1")
        button2 = Gtk.Button(label="Button 2")
        button3 = Gtk.Button(label="Button 3")
        button4 = Gtk.Button(label="Button 4")
        button5 = Gtk.Button(label="Button 5")
        button6 = Gtk.Button(label="Button 6")

        grid.add(button1)
        grid.attach(button2, 1, 0, 2, 1)
        grid.attach_next_to(button3, button1, Gtk.PositionType.BOTTOM, 1, 2)
        grid.attach_next_to(button4, button3, Gtk.PositionType.RIGHT, 2, 1)
        grid.attach(button5, 1, 2, 1, 1)
        grid.attach_next_to(button6, button5, Gtk.PositionType.RIGHT, 1, 1)

win = GridWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

Table

表格允许我们以类似于 Gtk.Table 的方式放置控件。 由于此接口是过时的,最好不再使用,因此不再翻译,请使用 Gtk.Grid 来代替。

Gtk.Table.set_row_spacing() and Gtk.Table.set_col_spacing() set the spacing between the rows at the specified row or column. Note that for columns, the space goes to the right of the column, and for rows, the space goes below the row.

You can also set a consistent spacing for all rows and/or columns with Gtk.Table.set_row_spacings() and Gtk.Table.set_col_spacings(). Note that with these calls, the last row and last column do not get any spacing.

Table Objects

3.4 版后已移除: Use Gtk.Grid instead.

class Gtk.Table(rows, columns, homogeneous)

The first argument is the number of rows to make in the table, while the second, obviously, is the number of columns. If homogeneous is True, the table cells will all be the same size (the size of the largest widget in the table).

attach(child, left_attach, right_attach, top_attach, bottom_attach[, xoptions[, yoptions[, xpadding[, ypadding]]]])

Adds a widget to a table.

child is the widget that should be added to the table. The number of ‘cells’ that a widget will occupy is specified by left_attach, right_attach, top_attach and bottom_attach. These each represent the leftmost, rightmost, uppermost and lowest column and row numbers of the table. (Columns and rows are indexed from zero).

For example, if you want a button in the lower-right cell of a 2 x 2 table, and want it to occupy that cell only, then the code looks like the following.

button = Gtk.Button()
table = Gtk.Table(2, 2, True)
table.attach(button, 1, 2, 1, 2)

If, on the other hand, you wanted a widget to take up the entire top row of our 2 x 2 table, you’d use

table.attach(button, 0, 2, 0, 1)

xoptions and yoptions are used to specify packing options and may be bitwise ORed together to allow multiple options. These options are:

  • Gtk.AttachOptions.EXPAND: The widget should expand to take up any extra space in its container that has been allocated.
  • Gtk.AttachOptions.FILL: The widget will expand to use all the room available.
  • Gtk.AttachOptions.SHRINK: Reduce size allocated to the widget to prevent it from moving off screen.

If omitted, xoptions and yoptions defaults to Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL.

Finally, the padding arguments work just as they do for Gtk.Box.pack_start(). If omitted, xpadding and ypadding defaults to 0.

set_row_spacing(row, spacing)

Changes the space between a given table row and the subsequent row.

set_col_spacing(col, spacing)

Alters the amount of space between a given table column and the following column.

set_row_spacings(spacing)

Sets the space between every row in this table equal to spacing.

set_col_spacings(spacing)

Sets the space between every column in this table equal to spacing.

Example

../../_images/layout_table_example.png
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from gi.repository import Gtk

class TableWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="Table Example")

        table = Gtk.Table(3, 3, True)
        self.add(table)

        button1 = Gtk.Button(label="Button 1")
        button2 = Gtk.Button(label="Button 2")
        button3 = Gtk.Button(label="Button 3")
        button4 = Gtk.Button(label="Button 4")
        button5 = Gtk.Button(label="Button 5")
        button6 = Gtk.Button(label="Button 6")

        table.attach(button1, 0, 1, 0, 1)
        table.attach(button2, 1, 3, 0, 1)
        table.attach(button3, 0, 1, 1, 3)
        table.attach(button4, 1, 3, 1, 2)
        table.attach(button5, 1, 2, 2, 3)
        table.attach(button6, 2, 3, 2, 3)

win = TableWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()