August 19th, 2006使用PyGtk和Glade构建应用程序
我的想法是创建一个可以让我记录我喝过酒的种类以及我对它们的喜好程度. 我写想这个程序很久了, 因此我想把学习PyGTK和写它结合起来会是一个好主意.
我把这个项目命名为PyWine. 本例程的全部代码和Glade文件可以从这里下载.
|
我们要做的第一件事情是在项目目录下创建一个名为PyWine的新Glade项目. 然后创建一个名为”mainWindow”的窗口, 并把它的标题设置成”PyWine”. 然后像在例程1里那样为它添加一个销毁的信息处理器.
然后我添加了一个有4行的垂直盒子(Vertical Box), (从上到下): 一行放置菜单栏,一行放工具栏,一行放一个树状或列表视图, 最后一行旋转一个状态栏. 把树状视图命名为”wineView”.
使用PyGTK和Glade创建用户界面>中拿来的).
#!/usr/bin/env python import sys try: import pygtk pygtk.require("2.0") except: pass try: import gtk import gtk.glade except: sys.exit(1) class pyWine: """This is the PyWine application""" def __init__(self): #Set the Glade file self.gladefile = "pywine.glade" self.wTree = gtk.glade.XML(self.gladefile, "mainWindow") #Create our dictionay and connect it dic = {"on_mainWindow_destroy" : gtk.main_quit , "on_AddWine" : self.OnAddWine} self.wTree.signal_autoconnect(dic) def OnAddWine(self, widget): """Called when the use wants to add a wine""" print "OnAddWine" if __name__ == "__main__": wine = pyWine() gtk.main() |
下一步是创建一个用来存储酒信息的类:
class Wine: """This class represents all the wine information""" def __init__(self, wine="", winery="", grape="", year=""): self.wine = wine self.winery = winery self.grape = grape self.year = year |
class wineDialog: """This class is used to show wineDlg""" def __init__(self, wine="", winery="", grape="", year=""): #setup the glade file self.gladefile = "pywine.glade" #setup the wine that we will return self.wine = Wine(wine,winery,grape,year) |
这个就是run 函数:
def run(self): """This function will show the wineDlg""" #load the dialog from the glade file self.wTree = gtk.glade.XML(self.gladefile, "wineDlg") #Get the actual dialog widget self.dlg = self.wTree.get_widget("wineDlg") #Get all of the Entry Widgets and set their text self.enWine = self.wTree.get_widget("enWine") self.enWine.set_text(self.wine.wine) self.enWinery = self.wTree.get_widget("enWinery") self.enWinery.set_text(self.wine.winery) self.enGrape = self.wTree.get_widget("enGrape") self.enGrape.set_text(self.wine.grape) self.enYear = self.wTree.get_widget("enYear") self.enYear.set_text(self.wine.year) #run the dialog and store the response self.result = self.dlg.run() #get the value of the entry fields self.wine.wine = self.enWine.get_text() self.wine.winery = self.enWinery.get_text() self.wine.grape = self.enGrape.get_text() self.wine.year = self.enYear.get_text() #we are done with the dialog, destroy it self.dlg.destroy() #return the result and the wine return self.result,self.wine |
|
你还可以看到我们从对话框里得到GTKEntry物件来取/设置它们的文字. 总得来说这个函数还是相当简单的.
树状视图和列表存储(List Stores)
GTKTreeViews的主要特性就是它们按照模型指定的任何方式来显示它们的数据. 数据模型可以用gtk_ListStore, gtk_TreeStore, gtk_TreeModelSort,或是gtk_GenericTreeModel. 在本例子中我们将使用 gkt_ListStore.
树状视图与模型的关系有些复杂,但是一旦你可以使用它你就会理解为什么它们是这样的. 很简单的讲模型表现数据,而树状视图则是一个简单的显示数据的方法. 所以对于同一份数据(模型)你可以有多个完全不同的视图. 下面是GTK+参考手册中的内容:
|
在GTK+中要创建一个树或列表可以使用结合使用GtkTreeModel接口和GtkTreeView物件. 这个物件使用模型/视图/控制器模式设计, 它由以下四个主要部分组成: 树状视图物件(GtkTreeView) 视图是由前面的三组对象组成, 最后一个是模型. MVC设计模式的一个主要收益是可以使用单个模型创建多个视图. 例如:由文件系统映射的模型(可能由一个文件管理器创建), 可以创建多种视图来显示文件系统的各个部分, 但仅需要在内存中保存一份拷贝 |
#Here are some variables that can be reused later self.cWine = 0 self.cWinery = 1 self.cGrape = 2 self.cYear = 3 self.sWine = "Wine" self.sWinery = "Winery" self.sGrape = "Grape" self.sYear = "Year" #Get the treeView from the widget Tree self.wineView = self.wTree.get_widget("wineView") #Add all of the List Columns to the wineView self.AddWineListColumn(self.sWine, self.cWine) self.AddWineListColumn(self.sWinery, self.cWinery) self.AddWineListColumn(self.sGrape, self.cGrape) self.AddWineListColumn(self.sYear, self.cYear) |
| def AddWineListColumn(self, title, columnId): “””This function adds a column to the list view. First it create the gtk.TreeViewColumn and then set some needed properties””” column = gtk.TreeViewColumn(title, gtk.CellRendererText() |
| 一旦GtkTreeView物件有了一个模型, 它需要知道如何显示这个模型. 它通过列和单元渲染器来完成这项工作. 单元渲染器是用来使用某种方法在树状模型中绘图这些数据. 在GTK+2.x中有很多单元渲染器, 包括: GtkCellRenderText, GtkCellRendererPixbuf 和GtkCellRendererToggle. 写一个自定义的渲染器也相对简单. GtkTreeView使用GtkTreeViewColumn对象来组织在树状视图中纵的列. 它需要知道列的名字用来以标签的形式显示给用户, 使用单元渲染器的类型和对于一个给定的行它需要得到的数据块. |
好了, 我们完成了模型的创建. 我们要再回到pyWine类的__init__函数里继续:
#Create the listStore Model to use with the wineView self.wineList = gtk.ListStore(str, str, str, str) #Attatch the model to the treeView self.wineView.set_model(self.wineList) |
把所有合并到一起
我们要做的最后一件事是完成pyWine类中的OnAddWine函数(从菜单或工具栏按钮调用). 这个函数很简单:
| OnAddWine(self, widget): “”"Called when the use wants to add a wine“”" #Create the dialog, show it, and store the results wineDlg = wineDialog(); result,newWine = wineDlg.run() if (result == gtk.RESPONSE_OK): “”"The user clicked Ok, so let’s add this wine to the wine list“”" self.wineList.append(newWine.getList()) |
这里我们创建了一个wineDialog的实例, 然后运行它并把用户输入的酒的信息保存.然后我们检查result是不是gtk_RESPONSE_OK(用户点击了Ok按钮), 如果是我们就把酒的信息添加到gtk_ListStore中, 它会自动的在gtk_TreeView中显示出来因此它们是连接在一起的.
在wine类中我使用简单的getList函数以使阅读代码变得简单一些:
def getList(self): """This function returns a list made up of the wine information. It is used to add a wine to the wineList easily""" return [self.wine, self.winery, self.grape, self.year] |
这里下载,你也可心浏览下面的完整程序:
#!/usr/bin/env python import sys try: import pygtk pygtk.require("2.0") except: pass try: import gtk import gtk.glade except: sys.exit(1) class pyWine: """This is an Hello World GTK application""" def __init__(self): #Set the Glade file self.gladefile = "pywine.glade" self.wTree = gtk.glade.XML(self.gladefile, "mainWindow") #Create our dictionay and connect it dic = {"on_mainWindow_destroy" : gtk.main_quit , "on_AddWine" : self.OnAddWine} self.wTree.signal_autoconnect(dic) #Here are some variables that can be reused later self.cWine = 0 self.cWinery = 1 self.cGrape = 2 self.cYear = 3 self.sWine = "Wine" self.sWinery = "Winery" self.sGrape = "Grape" self.sYear = "Year" #Get the treeView from the widget Tree self.wineView = self.wTree.get_widget("wineView") #Add all of the List Columns to the wineView self.AddWineListColumn(self.sWine, self.cWine) self.AddWineListColumn(self.sWinery, self.cWinery) self.AddWineListColumn(self.sGrape, self.cGrape) self.AddWineListColumn(self.sYear, self.cYear) #Create the listStore Model to use with the wineView self.wineList = gtk.ListStore(str, str, str, str) #Attache the model to the treeView self.wineView.set_model(self.wineList) def AddWineListColumn(self, title, columnId): """This function adds a column to the list view. First it create the gtk.TreeViewColumn and then set some needed properties""" column = gtk.TreeViewColumn(title, gtk.CellRendererText() , text=columnId) column.set_resizable(True) column.set_sort_column_id(columnId) self.wineView.append_column(column) def OnAddWine(self, widget): """Called when the use wants to add a wine""" #Cteate the dialog, show it, and store the results wineDlg = wineDialog(); result,newWine = wineDlg.run() if (result == gtk.RESPONSE_OK): """The user clicked Ok, so let's add this wine to the wine list""" self.wineList.append(newWine.getList()) class wineDialog: """This class is used to show wineDlg""" def __init__(self, wine="", winery="", grape="", year=""): #setup the glade file self.gladefile = "pywine.glade" #setup the wine that we will return self.wine = Wine(wine,winery,grape,year) def run(self): """This function will show the wineDlg""" #load the dialog from the glade file self.wTree = gtk.glade.XML(self.gladefile, "wineDlg") #Get the actual dialog widget self.dlg = self.wTree.get_widget("wineDlg") #Get all of the Entry Widgets and set their text self.enWine = self.wTree.get_widget("enWine") self.enWine.set_text(self.wine.wine) self.enWinery = self.wTree.get_widget("enWinery") self.enWinery.set_text(self.wine.winery) self.enGrape = self.wTree.get_widget("enGrape") self.enGrape.set_text(self.wine.grape) self.enYear = self.wTree.get_widget("enYear") self.enYear.set_text(self.wine.year) #run the dialog and store the response self.result = self.dlg.run() #get the value of the entry fields self.wine.wine = self.enWine.get_text() self.wine.winery = self.enWinery.get_text() self.wine.grape = self.enGrape.get_text() self.wine.year = self.enYear.get_text() #we are done with the dialog, destory it self.dlg.destroy() #return the result and the wine return self.result,self.wine class Wine: """This class represents all the wine information""" def __init__(self, wine="", winery="", grape="", year=""): self.wine = wine self.winery = winery self.grape = grape self.year = year def getList(self): """This function returns a list made up of the wine information. It is used to add a wine to the wineList easily""" return [self.wine, self.winery, self.grape, self.year] if __name__ == "__main__": wine = pyWine() gtk.main() |






