Python 提供了多个图形开发界面的库,几个常用 Python GUI 库如下:
Tkinter: Tkinter 模块(Tk 接口)是 Python 的标准 Tk GUI 工具包的接口 .Tk 和 Tkinter 可以在大多数的 Unix 平台下使用,同样可以应用在 Windows 和 Macintosh 系统里。Tkinter 是 Python 的标准 GUI 库。Python 使用 Tkinter 可以快速的创建 GUI 应用程序。由于 Tkinter 是内置到 python 的安装包中、只要安装好 Python 之后就能 import Tkinter 库、而且 IDLE 也是用 Tkinter 编写而成、对于简单的图形界面 Tkinter 还是能应付自如。
wxPython:wxPython 是一款开源软件,是 Python 语言的一套优秀的 GUI 图形库,允许 Python 程序员很方便的创建完整的、功能健全的 GUI 用户界面。
Jython:Jython 程序可以和 Java 无缝集成。除了一些标准模块,Jython 使用 Java 的模块。Jython 几乎拥有标准的Python 中不依赖于 C 语言的全部模块。比如,Jython 的用户界面将使用 Swing,AWT或者 SWT。Jython 可以被动态或静态地编译成 Java 字节码。
Tkinter 是 Python 的标准 GUI 库。Python 使用 Tkinter 可以快速的创建 GUI 应用程序。
先看一个简单的hello world!小例子:
from tkinter import *
root = Tk()
myLabel = Label(root,text='hello world!')
myLabel.grid()
root.mainloop()
结果:
Tkinter 的GUI由一些小部件(Widget)组成。所谓小部件,指的是文本框(TextBox)、按钮(Button)、标 签(Label)和复选按钮(CheckButton)等对象。在刚才的hello world例子中,标签myLabel就是其中唯一的小部件。当调用myLabel的.grid()方法时, 就等于把myLabel的位置告诉了布局管理器( Geometry Manager)。Tkinter中提供了几种不同的布局管理器,其中的.grid()方法会把小部件安排在一个二维的表格中。用户可以设定每个小部件所在的行列位置。上例中没有做任何设定,myLabel 会默认显示在0行0列。
三、集成Matplotlib 和Tkinter
Matplotlib的构建程序包含一个前端,也就是面向用户的一些代码,如plot()和scatter()方法等。事实上,它同时创建了一个后端,用于实现绘图和不同应用之间接口。通过改变后端可以将图像绘制在PNG,PDF,SVG等格式的文件上。下面将设置后端为TkAgg(Agg是一个C++的库,可以从图像创建光栅图(光栅图是位图,点阵图放大会失真,与之相对的是矢量图,又称向量图))。TkAgg可以在所选GUI框架上调用Agg,把Agg呈现在画布上。
3.1 代码实现
# -*- coding: utf-8 -*-
"""
Created on Tue May 8 20:19:51 2018
@author: lizihua
"""
from numpy import *
from tkinter import *
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
#加载数据
def loadDataSet(fileName):
dataMat = []
fr = open(fileName)
for line in fr.readlines():
curLine = line.strip().split("\t")
fltLine = list(map(float,curLine))
dataMat.append(fltLine)
return dataMat
#在给定的特征和特征值的情况下,通过数组过滤的方式将上述数据分成二个子集返回
def binSplitDataSet(dataSet, feature, value):
mat0 = dataSet[nonzero(dataSet[:,feature]>value)[0],:]
mat1 = dataSet[nonzero(dataSet[:,feature]<=value)[0],:]
return mat0,mat1
#创建叶结点,此时数据不能继续切分
def regLeaf(dataSet):
return mean(dataSet[:,-1])
#创建
def regErr(dataSet):
return var(dataSet[:,-1])*shape(dataSet)[0]
#errType:计算总方差(平方误差和)函数 = regErr
#ops:用户定义的参数构成的元组,用来完成树的构建,
#ops=(tolS,tolN),tolS:容许的误差下降值;tolN:切分的最小样本
#chooseBestSplit的目的是找到数据的最佳二元切分方式,若无,则返回None,并同时调用createTree产生叶结点
def chooseBestSplit(dataSet,leafType = regLeaf,errType = regErr,ops = (1,4)):
tolS = ops[0];tolN = ops[1]
#停止切分的条件1:若剩余的不同特征数目=1时,则退出
if len(set(dataSet[:,-1].T.tolist()[0])) ==1:
return None,leafType(dataSet)
m,n = shape(dataSet)
S = errType(dataSet)
bestS = inf; bestIndex = 0; bestValue = 0
for featIndex in range(n-1):
#for splitVal in set(dataSet[:,featIndex].T.A.tolist()[0]):
for splitVal in dataSet[:,featIndex]:
mat0,mat1 = binSplitDataSet(dataSet,featIndex,splitVal)
#当切分的数据集小于切分的最小样本tolN时,则退出循环
if (shape(mat0)[0] tree['spVal']:
if isTree(tree['left']): return treeForeCast(tree['left'], inData, modelEval)
else: return modelEval(tree['left'], inData)
else:
if isTree(tree['right']): return treeForeCast(tree['right'], inData, modelEval)
else: return modelEval(tree['right'], inData)
def createForeCast(tree, testData, modelEval=regTreeEval):
m=len(testData)
yHat = mat(zeros((m,1)))
for i in range(m):
yHat[i,0] = treeForeCast(tree, mat(testData[i]), modelEval)
return yHat
def reDraw(tolS,tolN):
reDraw.f.clf() # clear the figure
reDraw.a = reDraw.f.add_subplot(111)
if chkBtnVar.get():
if tolN < 2: tolN = 2
myTree=createTree(reDraw.rawDat, modelLeaf,modelErr, (tolS,tolN))
yHat = createForeCast(myTree, reDraw.testDat, modelTreeEval)
else:
myTree=createTree(reDraw.rawDat, ops=(tolS,tolN))
yHat = createForeCast(myTree, reDraw.testDat)
reDraw.a.scatter(reDraw.rawDat[:,0].A, reDraw.rawDat[:,1].A, s=5) #use scatter for data set
reDraw.a.plot(reDraw.testDat, yHat, linewidth=2.0) #use plot for yHat
reDraw.canvas.show()
def getInputs():
try: tolN = int(tolNentry.get())
except:
tolN = 10
print("enter Integer for tolN")
tolNentry.delete(0, END)
tolNentry.insert(0,'10')
try: tolS = float(tolSentry.get())
except:
tolS = 1.0
print("enter Float for tolS")
tolSentry.delete(0, END)
tolSentry.insert(0,'1.0')
return tolN,tolS
def drawNewTree():
tolN,tolS = getInputs()#get values from Entry boxes
reDraw(tolS,tolN)
root = Tk()
#用画布来替换绘制占位符,并删掉对应标签,即下面的Plot Place Holder那句
reDraw.f = Figure(figsize = (5,4),dpi = 100)
reDraw.canvas = FigureCanvasTkAgg(reDraw.f, master=root)
reDraw.canvas.show()
reDraw.canvas.get_tk_widget().grid(row = 0,columnspan = 3)
#待删除,只是代替图片占一个位置
#Label(root,text='Plot Place Holder').grid(row = 0, columnspan = 3)
#tolN
Label(root,text = 'tolN').grid(row = 1, column = 0)
tolNentry = Entry(root) #Entry:单行文本输入框
tolNentry.grid(row=1, column = 1)
tolNentry.insert(0,'10') #默认值为10
#tolS
Label(root,text = 'tolS').grid(row = 2, column = 0)
tolSentry = Entry(root)
tolSentry.grid(row=2, column = 1)
tolSentry.insert(0,'1.0') #默认值为1.0
#按钮
Button(root,text = 'ReDraw',command = drawNewTree).grid(row = 1, column = 2,rowspan = 3)
#按钮整数值
chkBtnVar = IntVar()
#复选按钮
chkBtn = Checkbutton(root,text = 'Model Tree',variable = chkBtnVar)
chkBtn.grid(row = 3, column = 0,columnspan = 2)
#初始化数据
reDraw.rawDat = mat(tree.loadDataSet('sine.txt'))
reDraw.testDat = arange(min(reDraw.rawDat[:,0]),max(reDraw.rawDat[:,0]),0.01)
reDraw(1.0,10)
root.mainloop()
3.2 结果显示