August 19th, 2006杂
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() |
August 6th, 2006使用PyGTK和Glade创建用户界面
原文: (奇怪, 我把类型选为翻译, 咋看上去啥也没有哪!!)
在花了一些时间使用Tkinter创建用户界面后发现它很简单, 但是在如何把界面和程序代码连接起来上费了些周折. 我决定试一试使用另外的工具包来创建界面. 经过一段时间的搜寻后我决定使用PyGTK和Glade.
使我下决心使用这两个技术的原因是:一. 它们是跨平台的 二. Glade能够我把代码和界面分离开来的愿望.
如果你之前从没听说过Glade, 它就是一个在GTK+和GNOME下的用户界面生成器. 它生成描述用户界面的xml文件.
pyGTK的网站上这样描述PyGTK:
| PyGTK为GTK+库提供了一个在Python程序中便于使用的封装, 它用来负责一些繁杂的细节诸如:管理内存和类型转换. 当把它与PyORBit和gnome-python结合起来时,它可以用来写具有完备功能的Gnome应用程序. |
现在我们从这里开始. 我正在我刚安装的Debian系统上写这些. 如果你也使用Debian或是一个基于Debian的发行版, 那么取得PyGTK和Glade就很简单:
| apt-get install python-gtk2 python-glade2 |
现在让我们创建我们第一个简单的界面, 这是你第一次启动Glade时的界面:
|
|
我们需要做的就是按下Glade面板的上的”Window” 按钮来创建主窗口. 然后就可以编辑这个窗口的属性了:
![]() |
我们把这个窗口命名为MainWindow, 然后再把它的标题设置成”Hello World!”
如果你已经习惯使用集成的界面设计工具像VisualStudio, 可能在最初使用Glade的时候会有些感到奇怪. 特别是当你实际上并不是把控件放到你想放到屏幕上的一些地方而是把它们”打包”. 但更奇怪的是(至少是对我来讲)大多数界面设计工具都是这样做的,而另外的一些程序像Visual studio实际上才是奇怪的.
无论如何我们回到向导上来, 接下来要做的事是添加一个标签来告诉用户去点击按钮(当然我们可以把文字放到按钮上,但是只有一个控件有多少乐趣啊?!). 由于GTK使用容器来打包器件, 我们要做的第一件事就是添加一个容器. 因为我们要把标签放到按钮上,所以使用了一个有两行的纵向盒子(Vertical Box). 你可以通过首先点击它在Glade面板上图标然后再点击一些主窗口把它添加上去. 这时候会有一个小对话框弹出来问你需要多少行, 现在我们需要2行.
接下来就是通过点击Glade面板上的标签按钮然后再点击刚才加上去的窗口的第一行把标签添加上去. 标签的名字就使用默认的名字”label1”, 把它的文字(text)修改为”Please click on the button!”. 修改标签上的文字可以在属性窗口里完成, 你可能还没有注意到这个窗口, 它可以显示并允许修改当前选中的控件.
再接下来就是再使用和添加标签相同的方法把按钮添加到第二行去(当然不能是第一行了). 我们把这个按钮命名为btnHelloworld,把它上面的文字修改为”Click me!”.
现在我们需要设置工程选项了. 我把这个工程命名为PyHelloWorld,并把它保存在”my projects/PyHelloWorld”文件夹中:
|
|
然后你就可以在PyHelloWorld目录里看到有两个文件被创建, 一个是扩展名为.gladep的glade的工程文件,另一个是扩展名为.glade的glade界面XML文件.
现在我们需要创建一个python程序,它装载这个glade文件然后显示它. 正面我就在这个目录里创建了一个名为PyHelloWorld.py的文件:
|
|
现在我们首先需要导入在这个工程里需要的所有库:
#!/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) |
接下来我们要做的就是创建主要的类. 我把它命名为HelloWorldGTK. 我们通过写它的__init__函数来装载glade文件:
class HellowWorldGTK: """This is an Hello World GTK application""" def __init__(self): #Set the Glade file self.gladefile = "pyhelloworld.glade" self.wTree = gtk.glade.XML(self.gladefile) #Get the Main Window, and connect the "destroy" event self.window = self.wTree.get_widget("MainWindow") if (self.window): self.window.connect("destroy", gtk.main_quit) |
上面的代码里, 我们做的第一件事(定义类以后)是指定我们要使用的glade文件并使用它创建一个gtk.glade.XML对象. 正面是pyGTK2参考里对这个对象的描述:
| 这个对象代表一个XML接口描述的实例. 当一个此类对象被创建时, 会读XML文件,接口也会被创建出来. Gtk.glade.XML对象提供了一个可以通过在xml描述中赋给物件的名称访问这些物件的接口. 此gtk.glade.XML对象也可以用来关联在XML描述中已命名的信号和信号处理器. Glade库(libglade)也提供了一个可以在程序的符号表中查找信号处理器名称并自动的把尽可能多的信号处理器关联起来的接口. |
因此当创建完gtk.glade.XML对象后我们就需要创建并装载主界面.
接下来就是实例化主窗口并把它的销毁事件与get.main_quit()函数关联起来.这样就会在关闭主窗口时退出这个程序. 否则的话在主窗口关闭后程序还会继续运行(这显然不是我们所希望的).
这些就是HelloWorldGTK类完成的工作. 接下来我们就需要创建一个这个类的实例然后开始GTK的主循环:
if __name__ == "__main__": hwg = HellowWorldGTK() gtk.main() |
下面就是程序的结果, 现在来说还算是相当简单. 如果你运行这个文件,你会看到这个小的GTK窗口, 现在除了在你关闭窗口时正常退出外它什么也不能做:
|
|
to be continue….(太晚了,回家先)
August 6th, 2006使用PyGTK和Glade创建用户界面(part 2)
首先在主窗口中选中这个按钮对象然后再在属性窗口中选择”信号”标签页. 在这里我们需要通过点击信息浏览按钮(…)然后选择”Clicked”来添加一个信号.这就默认创建了一个名字为”on_btnHelloWorld_clicked”的处理器”. 我们可以修改这个处理器的名字但是现在使用默认的名字就可以了.
gtk.glade.XML.signal_autoconnect函数来实现.
#Create our dictionay and connect it dic = { "on_btnHelloWorld_clicked" : self.btnHelloWorld_clicked, "on_MainWindow_destroy" : gtk.main_quit } self.wTree.signal_autoconnect(dic) |
简单的讲, 这个词典是由事件名和所要关联的函数构成的. 你可以看到我们把按钮的点击事件和一个函数关联起来,然后再把”on_MainWindow_destory”事件和gtk.mainquit()函数关联起来. 这个是我们原来在关闭掉窗口时程序代码的一个替换, 如果你还想使用原来的词典, 你应当在glade中为主窗口添加一个destory事件.
下一件事就是为类HeloowWolrdGTK创建btnHelloWorld_clicked函数:
def btnHelloWorld_clicked(self, widget): print "Hello World!" |
真是太简单了! 现在当你运行它的时候, 点击一下”Click Me!”按钮你可以看到在命令行中输出了”Hello World!”.
这就是本节课的内容, 但是现在我真的喜欢上了使用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 HellowWorldGTK: """This is an Hello World GTK application""" def __init__(self): #Set the Glade file self.gladefile = "pyhelloworld.glade" self.wTree = gtk.glade.XML(self.gladefile) #Create our dictionay and connect it dic = { "on_btnHelloWorld_clicked" : self.btnHelloWorld_clicked, "on_MainWindow_destroy" : gtk.main_quit } self.wTree.signal_autoconnect(dic) def btnHelloWorld_clicked(self, widget): print "Hello World!" if __name__ == "__main__": hwg = HellowWorldGTK() gtk.main() |
有用的链接:
http://www.linuxjournal.com/article/6586
http://www.async.com.br/~kiko/pygtk-web/articles/bitpodder/BitPodder.htm
http://www.linuxjournal.com/article/7421
http://www.pygtk.org/articles.html
http://www.pygtk.org/tutorial.html











