02 PyGTK 中的布局管理
本教程在这章中,我们将怎样在窗口或者对话框(dialogs)中布置我们的部件。
当我们设计程序的GUI界面时,我们决定哪些部件我们将会使用,和我们将怎样在程序中组织那些部件。为了组织我们的部件,我们使用专门的不可见部件,其被称为布局容器(layout containers)。在这章中,我们将提到Alignment, Fixed, VBox和Table这四种布局容器(layout containers)。
Fixed
Fixed容器将放置位置固定和尺寸固定的子部件。这个容器不进行自动的布局管理。在大多数的程序中,我们不用这种容器。但是在一些专门的领域,我们会用它。例如游戏,一些工作在图表中的专门程序,那些能被移动可变化尺寸的组件(就想在电子表格程序中的一个chart表一样),小型的学习示例等。
Code:fixed.py
#!/usr/bin/python
# ZetCode PyGTK tutorial
#
# This example demonstrates a Fixed
# container widget
#
# author: jan bodnar
# website: zetcode.com
# last edited: February 2009
import gtk
import sys
class PyApp(gtk.Window):
def __init__(self):
super(PyApp, self).__init__()
self.set_title("Fixed")
self.set_size_request(300, 280)
self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(6400, 6400, 6440))
self.set_position(gtk.WIN_POS_CENTER)
try:
self.bardejov = gtk.gdk.pixbuf_new_from_file("bardejov.jpg")
self.rotunda = gtk.gdk.pixbuf_new_from_file("rotunda.jpg")
self.mincol = gtk.gdk.pixbuf_new_from_file("mincol.jpg")
except Exception, e:
print e.message
sys.exit(1)
image1 = gtk.Image()
image2 = gtk.Image()
image3 = gtk.Image()
image1.set_from_pixbuf(self.bardejov)
image2.set_from_pixbuf(self.rotunda)
image3.set_from_pixbuf(self.mincol)
fix = gtk.Fixed()
fix.put(image1, 20, 20)
fix.put(image2, 40, 160)
fix.put(image3, 170, 50)
self.add(fix)
self.connect("destroy", gtk.main_quit)
self.show_all()
PyApp()
gtk.main()
在我们的例子中,我们在窗口上显示了3个小图片。在我们放置这些图片的地方,我们明确地指定其x,y坐标。
self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(6400, 6400, 6440))
为了更好的视觉体验,我们更改了窗口的背景颜色为暗灰色。
self.bardejov = gtk.gdk.pixbuf_new_from_file("bardejov.jpg")
我们从磁盘中一个文件里载入图片。
image1 = gtk.Image()
image2 = gtk.Image()
image3 = gtk.Image()
image1.set_from_pixbuf(self.bardejov)
image2.set_from_pixbuf(self.rotunda)
image3.set_from_pixbuf(self.mincol)
Image是一个部件,其作用是用来显示图片的。它在构造函数占用了一个Pixbuf(图片缓存)对象。
fix = gtk.Fixed()
我们创建了Fixed容器。
fix.put(image1, 20, 20)
我们将第一张图片放置在坐标为x=20,y=20的位置上。
self.add(fix)
最后,我们将Fixed容器添加到窗口中。
Figure:Fixed
Alignment
Alignment容器控制它的子部件的对齐和尺寸。
Code:alignment.py
#!/usr/bin/python
# ZetCode PyGTK tutorial
#
# This example shows how to use
# the Alignment widget
#
# author: jan bodnar
# website: zetcode.com
# last edited: February 2009
import gtk
class PyApp(gtk.Window):
def __init__(self):
super(PyApp, self).__init__()
self.set_title("Alignment")
self.set_size_request(260, 150)
self.set_position(gtk.WIN_POS_CENTER)
vbox = gtk.VBox(False, 5)
hbox = gtk.HBox(True, 3)
valign = gtk.Alignment(0, 1, 0, 0)
vbox.pack_start(valign)
ok = gtk.Button("OK")
ok.set_size_request(70, 30)
close = gtk.Button("Close")
hbox.add(ok)
hbox.add(close)
halign = gtk.Alignment(1, 0, 0, 0)
halign.add(hbox)
vbox.pack_start(halign, False, False, 3)
self.add(vbox)
self.connect("destroy", gtk.main_quit)
self.show_all()
PyApp()
gtk.main()
在上述代码示例中,我们放置了两个按钮在窗口的右下角。为了完成这项任务,我们使用了一个水平箱子容器(horizontal box)和一个垂直箱子容器(vertical box)以及两个alignment容器。
valign = gtk.Alignment(0, 1, 0, 0)
这一步将会放置小部件到底部。
vbox.pack_start(valign)
在这里,我们Alignment容器放置到垂直箱子容器中。
hbox = gtk.HBox(True, 3)
...
ok = gtk.Button("OK")
ok.set_size_request(70, 30)
close = gtk.Button("Close")
hbox.add(ok)
hbox.add(close)
我们创建了一个水平箱子容器,并放置了两个按钮到其中。
halign = gtk.Alignment(1, 0, 0, 0)
halign.add(hbox)
vbox.pack_start(halign, False, False, 3)
这将创建一个alignment容器,这个容器将放置其子部件到右边。我们添加水平箱子容器到alignment容器中,并将alignment容器放置进垂直箱子容器中。我们必须记住的是:alignment容器中只能有一个子部件。这就是为什么我们必须用box容器。
Figure:alignment
【译者理解:alignment容器的位置按顺序分别是gtk.alignment(右,下,上,左)】
Table
Table容器部件是将其部件安排在行和列中。
Code:calculator.py
#!/usr/bin/python
# ZetCode PyGTK tutorial
#
# This example shows how to use
# the Table container widget
#
# author: jan bodnar
# website: zetcode.com
# last edited: February 2009
import gtk
class PyApp(gtk.Window):
def __init__(self):
super(PyApp, self).__init__()
self.set_title("Calculator")
self.set_size_request(250, 230)
self.set_position(gtk.WIN_POS_CENTER)
vbox = gtk.VBox(False, 2)
mb = gtk.MenuBar()
filemenu = gtk.Menu()
filem = gtk.MenuItem("File")
filem.set_submenu(filemenu)
mb.append(filem)
vbox.pack_start(mb, False, False, 0)
table = gtk.Table(5, 4, True)
table.attach(gtk.Button("Cls"), 0, 1, 0, 1)
table.attach(gtk.Button("Bck"), 1, 2, 0, 1)
table.attach(gtk.Label(), 2, 3, 0, 1)
table.attach(gtk.Button("Close"), 3, 4, 0, 1)
table.attach(gtk.Button("7"), 0, 1, 1, 2)
table.attach(gtk.Button("8"), 1, 2, 1, 2)
table.attach(gtk.Button("9"), 2, 3, 1, 2)
table.attach(gtk.Button("/"), 3, 4, 1, 2)
table.attach(gtk.Button("4"), 0, 1, 2, 3)
table.attach(gtk.Button("5"), 1, 2, 2, 3)
table.attach(gtk.Button("6"), 2, 3, 2, 3)
table.attach(gtk.Button("*"), 3, 4, 2, 3)
table.attach(gtk.Button("1"), 0, 1, 3, 4)
table.attach(gtk.Button("2"), 1, 2, 3, 4)
table.attach(gtk.Button("3"), 2, 3, 3, 4)
table.attach(gtk.Button("-"), 3, 4, 3, 4)
table.attach(gtk.Button("0"), 0, 1, 4, 5)
table.attach(gtk.Button("."), 1, 2, 4, 5)
table.attach(gtk.Button("="), 2, 3, 4, 5)
table.attach(gtk.Button("+"), 3, 4, 4, 5)
vbox.pack_start(gtk.Entry(), False, False, 0)
vbox.pack_end(table, True, True, 0)
self.add(vbox)
self.connect("destroy", gtk.main_quit)
self.show_all()
PyApp()
gtk.main()
我们用Table容器部件创建了一个计算器的框架。
table = gtk.Table(5, 4, True)
我们创建了一个5行4列的table容器部件。第三个参数是同质参数,如果被设置为ture,table中所有的部件将是相同的尺寸。而所有部件的尺寸与table容器中最大的部件的尺寸相同。
table.attach(gtk.Button("Cls"), 0, 1, 0, 1)
我们附加了一个按钮到table容器中,其位置在表格的左上单元(cell)。前面两个参数代表这个单元的左侧和右侧,后两个参数代表这个单元的上部和下部。【译者:此处表述比较难以理解,待研究。】
vbox.pack_end(table, True, True, 0)
我们将table容器部件放置到垂直箱子容器中。
Figure:Calculator skeleton
Windows
下面我们将创建一个更加高级的例子。我们展示了一个窗口,其可以在JDeveloper 集成开发环境(IDE)中被找到。
Code:windows.py
#!/usr/bin/python
# ZetCode PyGTK tutorial
#
# This is a more complicated layout
# example
#
# author: jan bodnar
# website: zetcode.com
# last edited: February 2009
import gtk
import sys
class PyApp(gtk.Window):
def __init__(self):
super(PyApp, self).__init__()
self.set_title("Windows")
self.set_size_request(300, 250)
self.set_border_width(8)
self.set_position(gtk.WIN_POS_CENTER)
table = gtk.Table(8, 4, False)
table.set_col_spacings(3)
title = gtk.Label("Windows")
halign = gtk.Alignment(0, 0, 0, 0)
halign.add(title)
table.attach(halign, 0, 1, 0, 1, gtk.FILL,
gtk.FILL, 0, 0);
wins = gtk.TextView()
wins.set_editable(False)
wins.modify_fg(gtk.STATE_NORMAL, gtk.gdk.Color(5140, 5140, 5140))
wins.set_cursor_visible(False)
table.attach(wins, 0, 2, 1, 3, gtk.FILL | gtk.EXPAND,
gtk.FILL | gtk.EXPAND, 1, 1)
activate = gtk.Button("Activate")
activate.set_size_request(50, 30)
table.attach(activate, 3, 4, 1, 2, gtk.FILL,
gtk.SHRINK, 1, 1)
valign = gtk.Alignment(0, 0, 0, 0)
close = gtk.Button("Close")
close.set_size_request(70, 30)
valign.add(close)
table.set_row_spacing(1, 3)
table.attach(valign, 3, 4, 2, 3, gtk.FILL,
gtk.FILL | gtk.EXPAND, 1, 1)
halign2 = gtk.Alignment(0, 1, 0, 0)
help = gtk.Button("Help")
help.set_size_request(70, 30)
halign2.add(help)
table.set_row_spacing(3, 6)
table.attach(halign2, 0, 1, 4, 5, gtk.FILL,
gtk.FILL, 0, 0)
ok = gtk.Button("OK")
ok.set_size_request(70, 30)
table.attach(ok, 3, 4, 4, 5, gtk.FILL,
gtk.FILL, 0, 0);
self.add(table)
self.connect("destroy", gtk.main_quit)
self.show_all()
PyApp()
gtk.main()
上述代码示例中展示了,我们在PyGTK中怎样创建相似的窗口。
table = gtk.Table(8, 4, False)
table.set_col_spacings(3)
这个例子是基于table容器的。在每一列中间将有3个像素(px)的间隔。
title = gtk.Label("Windows")
halign = gtk.Alignment(0, 0, 0, 0)
halign.add(title)
table.attach(halign, 0, 1, 0, 1, gtk.FILL,
gtk.FILL, 0, 0);
上述代码创建了一个文本标签(label),其被排在左边。这个文本标签(label)被放置在Table容器的第一行。
wins = gtk.TextView()
wins.set_editable(False)
wins.modify_fg(gtk.STATE_NORMAL, gtk.gdk.Color(5140, 5140, 5140))
wins.set_cursor_visible(False)
table.attach(wins, 0, 2, 1, 3, gtk.FILL | gtk.EXPAND,
gtk.FILL | gtk.EXPAND, 1, 1)
上述代码中的文本视图(TextView)部件跨越了两行两列。我们使其不可编辑,并隐藏了光标。
valign = gtk.Alignment(0, 0, 0, 0)
close = gtk.Button("Close")
close.set_size_request(70, 30)
valign.add(close)
table.set_row_spacing(1, 3)
table.attach(valign, 3, 4, 2, 3, gtk.FILL,
gtk.FILL | gtk.EXPAND, 1, 1)
我们将close按钮放进紧接着文本视图部件的第四列中(我们从0数起)。我们将按钮添加进alignment部件,这样我们就能将它排在顶部。
Figure:Windows
PyGTK编程教程的这章是关于布局管理(layout management)。