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

一、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] 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 结果显示

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


你可能感兴趣的:(机器学习)