您的位置:首页 > 编程语言 > Python开发

《机器学习实战》第九章学习笔记(使用Python的Tkinter库创建GUI)

2018-05-09 19:45 896 查看

一、GUI(Graphical User Interface,图像用户界面)编程

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 创建GUI

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]<tolN) or (shape(mat1)[0] <tolN):
continue
newS = errType(mat0) + errType(mat1)
if newS <bestS:
bestIndex = featIndex
bestValue = splitVal
bestS = newS
#停止切分的条件2:若误差减小在容许下降误差值tolS内,则退出
if (S - bestS) < tolS:
return None,leafType(dataSet)
mat0,mat1 = binSplitDataSet(dataSet,bestIndex,bestValue)
#停止切分的条件3:当切分的数据集小于切分的最小样本tolN时,则退出
if (shape(mat0)[0]<tolN) or (shape(mat1)[0] <tolN):
return None,leafType(dataSet)
return bestIndex,bestValue

#创建树:递归函数
def createTree(dataSet,leafType=regLeaf,errType = regErr,ops = (1,4)):
feat,val =chooseBestSplit(dataSet,leafType,errType,ops)
if feat == None:
return val
retTree={}
retTree['spInd']=feat
retTree['spVal']=val
lSet,rSet = binSplitDataSet(dataSet,feat,val)
retTree['left']=createTree(lSet,leafType,errType,ops)
retTree['right']=createTree(rSet,leafType,errType,ops)
return retTree

#树回归
#线性模型函数,将被以下两个函数调用,其余过程与简单的线性回归函数过程一般
def linearSolve(dataSet):
m,n = shape(dataSet)
#初始化X,Y
X = mat(ones((m,n))); Y = mat(ones((m,1)))#create a copy of data with 1 in 0th postion
X[:,1:n] = dataSet[:,0:n-1]; Y = dataSet[:,-1]
xTx = X.T*X
if linalg.det(xTx) == 0.0:
raise NameError('This matrix is singular, cannot do inverse,\n\
try increasing the second value of ops')
ws = xTx.I * (X.T * Y)
return ws,X,Y
#生成叶结点模型
def modelLeaf(dataSet):#create linear model and return coeficients
ws,X,Y = linearSolve(dataSet)
return ws

#线性模型误差
def modelErr(dataSet):
ws,X,Y = linearSolve(dataSet)
yHat = X * ws
return sum(power(Y - yHat,2))
def regTreeEval(model, inDat):
return float(model)

def modelTreeEval(model, inDat):
n = shape(inDat)[1]
X = mat(ones((1,n+1)))
X[:,1:n+1]=inDat
return float(X*model)

def treeForeCast(tree, inData, modelEval=regTreeEval):
if not isTree(tree): return modelEval(tree, inData)
if inData[tree['spInd']] > 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)

1cca7
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 结果显示

 


阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: