FC54 Python编程

出自Full Circle 中文项目主页

跳转到: 导航, 搜索

PYTHON编程-第28部分

作者:Greg Walters

翻译:文宁

校对:吴云 张志宇


我们将要探索由tkinter提供的更多控件。这次我们将关注menus(菜单),combo boxes(组合框),spin boxes(滚动框),separator bar(分隔条),progress bars(进度条)以及notebooks(笔记本)。让我们一次性把它们讨论完吧。


其实,你在几乎所有已用过的应用程序里见到过menus(菜单)了。Tkinter使得我们创建menus变得非常简单。Combo Boxes和我们上次在范例文章中探索过的控件list box很像,只是list box用了一个“下拉框(pops down)”而不是让控件一直显示在外面。Spin box controls对于给出一个固定范围的值来向上或向下“滚动”是非常方便。例如,如果我们想让用户能够选择从1到100的整数,就可以简单地用一个spin box来实现。当某个任务需要花费很长时间,例如从数据库读取记录时,用Process bars来显示你的应用程序没有进入死锁状态是个非常棒的方式。它可以显示出任务完成的百分比。这里会有两种进度条,即确定的(Determinate)和不确定的(Indeterminate)。当你知道要处理多少项目时就用确定进度条,如果你不知道项目的数目或任意一个时刻任务完成的百分比,就应该用不确定的进度条。这两个下面我们都将用到。最后,一个notebook控件(或者叫tabbed控件)是多次用到的像配置窗口这样的东西。你可以按逻辑将一系列控件分组到每一个标签(tab)里。


那么,让我们开始吧。通常,我们将创建一个基本程序,然后在此之上添加每一个额外的控件来构造它。右边展示的就是我们应用程序的第一部分。在此之前你基本上已经看过这个了。


把所有的这些代码保存为widgetdemo2a.py。请记住,我们将用这个作为基础来构建整个示例。现在我们将开始创建菜单的进程。下面是需要做的步骤。首先,我们定义了一个变量来保存menu实例。就像我们用到的任何一个控件,格式是……


OurVariable = Widget(parent, options).


这个例子中,我们将用到Menu控件并把它分配给作为父级控件的master。我们通过BuildWidgets程序来实现。接下来创建另一个menu项目,这次我们称它为filemenu,同时根据需要添加命令和分隔符。最后把它添加到menu bar(菜单条)并从新再做一个,直到做完我们需要的工作。在我们这个例子里, menubar将包含如下部分:一个File(文件)下拉菜单、一个Edit(编辑)下拉菜单和一个Help(帮助)下拉菜单(如右上方图)。让我们开始吧。


接着(中间靠右)我们来关注File菜单。里面包括五个元素:New(新建), Open(打开), Save(保存), 一个 separator(分隔条) 以及 Exit(退出)。我们将用.add_command方法来添加命令。而我们真正所要做的是调用这个带有text(label=)参数的类函数,然后提供一个回调函数来处理用户对项目的点击。最后我们用menubar.add_cascade函数把这个菜单附到工具条上。


注意,Exit命令是用“root.quit”来结束程序。因此不需要回调。接着我们对Edit和Help菜单项进行相同的处理。


注意在每一个菜单组(menu group)的定义部分都有“tearoff=0”。如果你要把“=0”改成“=1”,这个菜单将以看起来像虚线的样式开始,而且如果你拖拽它,它将“脱落”并创建一个属于它自己的窗口。尽管以后某个时刻可能会很有用,但我们现在不需要它。


最后也是最重要的,我们需要放置这个菜单。我们不用.grid()函数去实现正常布局,而只要简单地通过调用parent.config(如右下方图)函数来添加它即可。


所有这些都已经在BuilWidgets程序里了。现在(如下页右上方图)我们需要添加一个普通的窗框并在实现PlaceWidgets函数之前设置返回声明。


最后(如下页右下方图)我们需要创建所有之前定义的回调函数。对于这个示例,我们将要做的是往启动程序的终端内输入一些东西。


这样就够了。保存并运行这个程序。点击每个菜单选项(保存文件|退出)。


现在(如下图)我们要处理combo box。文件保存为widgetdemo2b.py然后我们就开始吧。引入模块,类定义和def __init__函数都是一样作为程序的底层基础。我们在DefineVars函数中将添加两行代码。要么注释掉“pass”语句,要么删除它,然后加入下面这段代码。(我包括了定义行只是为了看起来清楚。)


首先我们定义一个标签,就像之前做的那样。然后定义combo box。我们用“ttk.Combobox”定义父级控件,并把高度(height)设置为19,宽度(width)设为20,以及文字变量设为“self.cmbo1Val”。记得在上个控件示例中我们就设置了它,但只是以防万一,我们就再设置一次……combo box的值在任何时候改变时,它都会改变。我们在DefineVars中将其定义为一个StringVar对象。接着加载可供用户选择的值,同样在DefineVars里定义它。最后把虚拟事件<<ComboboxSelected>>绑定到cmbotest函数上,一会儿我们再填充cmbotest函数。


下面我们将combo box和label放进我们的表格(form)(如右上方图)。


保存所有代码并测试它。


现在将代码另存为widgetdemo2c.py,然后我们开始编写separator bar(分隔条)。这个超级简单。虽然升级后的tkinter提供了一个分隔条控件,但是我却没能让它工作起来。这儿有一个简单的活儿,我们需要一个高度为2的边框。对于我们程序唯一改变的是BuildWidgets函数中combo box bind声明之后的边框定义,然后将此窗框放进PlaceWidgets函数中。因此,在BuildWidgets函数里添加如下代码(如右边中间代码所示)……


再重复一次,你之前已经看过这个了。保存然后测试吧。现在你可能必须展开最上面的窗口来看这个分隔条,但在下一个范例中它将变得更加明显。代码另存为widgetdemo2d.py,然后我们将添加spin control(滚动控制)。


在函数DefineVars下添加如下代码……

self.spinval = StringVar()


至此,你应该知道这个是为了让我们可以在任何时候获得我们想要的值。接着,我们将在BuildWidgets函数中添加一些代码……就在“return frame”这行前面(如右下方图)。


这里我们定义了一个label和spin control。spin control的定义如下:

ourwidget = Spinbox(parent,low value, high value, width, textvariable, wrap)


低价值(low value)必须被命名为“from_”,因为“from”是关键字,倘若使用它只会混淆一切。“from_”和“to”的值必须定义为(float)浮点型。在这个例子中,我们想要它包含一个为1的低值和一个为10的高值。最后,轮回(wrap)选项是指如果这个值(在本例中)为10同时用户点击向上箭头,表示我们要它轮回到低值并继续。对于低值同样原理,如果用户点击向下的箭头并且这个值为1时,它将轮回到10并继续。如果你设置成“wrap=False”,这个控制将停在用户要点击的任何方向。


现在,我们将这些控件放到PlaceWidgets函数里(如下图)。


对,就是这样,保存并运行。现在你将真正注意到分隔条了。将代码另存为idgetdemo2e.py,然后我们将处理进程条。


同样,我们需要定义一些变量,因此在DefineVars函数里添加如下代码……

self.spinval2 = StringVar()

self.btnStatus = False

self.pbar2val = StringVar()


期中,两个StringVar变量是做什么的应该非常明显了。我们将在后面讨论“self.btnStatus”。现在,让我们继续然后在BuildWidgets函数里定义这部分的控件(如右图)。


再次回到“return frame”这行前面。我们将要做的是建立一个能够放置控件的窗框,然后,我们设置两个标签作为向导。接着定义第一个进度条。这里唯一陌生的或许是宽度(length),模式(mode)和最大值(maximum)。宽度是我们进度条的像素大小。最大值是我们将看到的最大值,这里是100,因为我们要看的是百分比。模式在这里是“indeterminate”。请记住,当我们不知道一个任务进度如何但只想让用户知道它正在做某件事时,我们就用这个模式。


接着,我们添加一个button(你之前已经做过的),另一个label、另一个progress bar以及另一个spin control。第二个进度条的模式为“determinate”。我们将用这个spin control来设置完成的百分比。接着在PlaceWidgets函数里添加下列代码(如下页左上图)。


最后,我们添加两个函数来控制这些进度条(如右下图)。


TestPBar函数控制indeterminate(非确定)进度条。基本上,我们即将开始或停止一个置入到进度条的内部定时器。“self.pbar.start(10)”这一行设置定时器为10毫秒。这使得进度条运行得非常快。你可以自己调整这个值的大小来玩玩儿。Spin2Do函数简单地将进度条设置成任何在spin control中的值。我们也把它打印到终端。


所有的变化就是这些了。保存并运行。


现在将代码另存为widgetdemo2f.py,然后我们将处理notebook标签控件。在BuildWidgets函数里 “return frame”这行前面添加如下代码(如下图)……


让我们来看看我们做了什么。首先,我们为notebook控件定义了一个窗框。现在我们来定义这个控件。所有的选项都是我们之前看过的。接着,我们定义两个叫self.p1和self.p2的窗框。这些将作为我们的页面。接下来的两行(self.notebook.add)将窗框添加到notebook控件中并且它们获得一个附属的标签。我们也要为这些标签设置文字。最后,在第一页放置一个标签。当然为了好玩,我们放置controls时,在第二页也可以添加一个标签。


在PlaceWidgets函数里放置下列代码(如下图)。


你唯一感觉奇怪的东西可能是第二页上的标签。我们用相同的命令把定义和网格定位结合在一起。我们在第一个控件范例应用中做过这样的事儿


这样就行了。保存并运行。


一如往常,完整程序的代码放在了pastebin上,网址http://pastebin.com/qSPkSNU1。


祝你愉快,下次我们将更多的处理一些关于数据库的东西。

个人工具