Python的GUI编程和tkinter,Wxpython

2024-02-28 20:26:41 浏览数 (4)

Python的GUI编程和tkinter,Wxpython

PythonGUI这个内容是我在课程论文准备之初临时去学的一些内容,起初我准备学下tkinter做我课程论文项目的前段显示,但是由于临时的一些变动,我最终是采用了Wxpython的方式进行的可视化。当然这两个库在本质上都属于PythonGul。

[TOC]

PythonGUI介绍:

  • Tkinter: Tkinter 模块(Tk 接口)是 Python 的标准 Tk GUI 工具包的接口 .Tk 和 Tkinter 可以在大多数的 Unix 平台下使用,同样可以应用在 Windows 和 Macintosh 系统里。Tk8.0 的后续版本可以实现本地窗口风格,并良好地运行在绝大多数平台中。
  • wxPython:wxPython 是一款开源软件,是 Python 语言的一套优秀的 GUI 图形库,允许 Python 程序员很方便的创建完整的、功能健全的 GUI 用户界面。
  • Jython:Jython 程序可以和 Java 无缝集成。除了一些标准模块,Jython 使用 Java 的模块。Jython 几乎拥有标准的Python 中不依赖于 C 语言的全部模块。比如,Jython 的用户界面将使用 Swing,AWT或者 SWT。Jython 可以被动态或静态地编译成 Java 字节码。

tkinter

根窗体root:

根窗体是图像化应用程序的根控制器,是tkinter的底层控件的实例。当导入tkinter模块后,调用 Tk()方法可初始化一个根窗体实例 root ,用 title() 方法可设置其标题文字,用geometry()方法可以设置窗体的大小(以像素为单位)。将其置于主循环中,除非用户关闭,否则程序始终处于运行状态。执行该程序,一个窗体就呈现出来了。在这个主循环的根窗体中,可持续呈现中的其他可视化控件实例,监测事件的发生并执行相应的处理程序

主窗口位置和大小通过,geometry(‘wxh ± y ± z’)方法进行设置,w为宽度,h为高度,x用于分隔高度和宽度, x表示距离屏幕左边的距离,-x表示距离屏幕右边的距离,±y同理。

代码语言:javascript复制
#代码实现:
from tkinter import *
root= Tk()
root.title('我的第一个Python窗体')
root.geometry('240x240') # 这里的乘号不是 * ,而是小写英文字母 x
root.mainloop()

GUI组件表:

Tkinter的提供各种控件,如按钮,标签和文本框,一个GUI应用程序中使用。这些控件通常被称为控件或者部件。目前有15种Tkinter的部件。

Button

按钮控件;在程序中显示按钮。

Canvas

画布控件;显示图形元素如线条或文本

Checkbutton

多选框控件;用于在程序中提供多项选择框

Entry

输入控件;用于显示简单的文本内容

Frame

框架控件;在屏幕上显示一个矩形区域,多用来作为容器

Label

标签控件;可以显示文本和位图

Listbox

列表框控件;在Listbox窗口小部件是用来显示一个字符串列表给用户

Menubutton

菜单按钮控件,用于显示菜单项。

Menu

菜单控件;显示菜单栏,下拉菜单和弹出菜单

Message

消息控件;用来显示多行文本,与label比较类似

Radiobutton

单选按钮控件;显示一个单选的按钮状态

Scale

范围控件;显示一个数值刻度,为输出限定范围的数字区间

Scrollbar

滚动条控件,当内容超过可视化区域时使用,如列表框。.

Text

文本控件;用于显示多行文本

Toplevel

容器控件;用来提供一个单独的对话框,和Frame比较类似

Spinbox

输入控件;与Entry类似,但是可以指定输入范围值

PanedWindow

PanedWindow是一个窗口布局管理的插件,可以包含一个或者多个子控件。

LabelFrame

labelframe 是一个简单的容器控件。常用与复杂的窗口布局。

messagebox

用于显示你应用程序的消息框。

Python Tkinter 通用控件属性:
Python Tkinter 按钮组件 (Button)

按钮组件用于在 Python 应用程序中添加按钮,按钮上可以放上文本或图像,按钮可用于监听用户行为,能够与一个 Python 函数关联,当按钮被按下时,自动调用该函数。

代码语言:javascript复制
w = Button ( master, option=value, ... )
# master 组件的父容器
# option 可选项,这个包括很多内容这些选项可以用键 = 值的形式设置,并以逗号分隔
# 包括command(按钮的关联函数),font(文本字体),height(按钮的高度),image(按钮的背景图片),width,text(文本),underline(下划线)等内容

Button按钮的状态有:normal , active , disabled

代码语言:javascript复制
import tkinter
import tkinter.messagebox 
top = tkinter.Tk()
def helloCallBack():
    tkinter.messagebox.showinfo("Hello Python", "Hello Runoob")
B = tkinter.Button(top, text="点我", command=helloCallBack)
B.pack()
top.mainloop()

这里稍微做一点说明,这个实例来自于菜鸟教程,而在菜鸟教程上的写法是 import tkMessageBox ,还是有很多区别的,在python3以后的版本中,tkinter应该首字母小写,而tkMessageBox及库中对应的函数应该相应改为tkinter.messagebox

在具体使用按钮组件进行函数调用时也有对应内容:

  • 直接调用函数。参数表达式为“command=函数名”,注意函数名后面不要加括号,也不能传递参数。如下面的command=run1:
  • 利用匿名函数调用函数和传递参数。参数的表达式为“command=lambda”:函数名(参数列表)
Python Tkinter 单选按钮控件(Radiobutton)

是为了响应故乡排斥的若干单选项的单击事件以触发运行自定义函数所设的,该控件排除具有共有属性外,还具有显示文本(text)、返回变量(variable)、返回值(value)、响应函数名(command)等重要属性。响应函数名“command=函数名”的用法与Button相同,函数名最后也要加括号。返回变量variable=var通常应预先声明变量的类型var=IntVar()或var=StringVar(),在所调用的函数中方可用var.get()方法获取被选中实例的value值。

代码语言:javascript复制
from tkinter import *
def Mysel():
      dic = {0:'甲',1:'乙',2:'丙'}
      s = "您选了"   dic.get(var.get())   "项"
      lb.config(text = s)

root = Tk()
root.title('单选按钮')
lb = Label(root)
lb.pack()
var = IntVar()
rd1 = Radiobutton(root,text="甲",variable=var,value=0,command=Mysel)
rd1.pack()
rd2 = Radiobutton(root,text="乙",variable=var,value=1,command=Mysel)
rd2.pack()
rd3 = Radiobutton(root,text="丙",variable=var,value=2,command=Mysel)
rd3.pack()
root.mainloop()
Python Tkinter 复选框(Checkbutton)
代码语言:javascript复制
# 定义方法
w = tkinter.Checkbutton( master, option=value, ... )
# 在python3中,复选框的定义方式发生了略微改变

复选框:(Checkbutton) 是为了返回多个选项值的交互控件,通常不直接触发函数的执行。该控件除具有共有属性外,还具有显示文本(text)、返回变量(variable)、选中返回值(onvalue)和未选中默认返回值(offvalue)等重要属性。返回变量variable=var 通常可以预先逐项分别声明变量的类型var=IntVar() (默认)或 var=StringVar(), 在所调用的函数中方可分别调用 var.get()方法 取得被选中实例的 onvalue或offvalue值。复选框实例通常还可分别利用 select()、deselect()和 toggle() 方法对其进行选中、清除选中和反选操作。

代码语言:javascript复制
#简单样例:
import tkinter.messagebox
import tkinter
top = tkinter.Tk()
CheckVar1 = tkinter.IntVar()
CheckVar2 = tkinter.IntVar()
C1 = tkinter.Checkbutton(top, text="RUNOOB", variable=CheckVar1,onvalue=1, offvalue=0, height=5,width=20)
C2 = tkinter.Checkbutton(top, text="GOOGLE", variable=CheckVar2,onvalue=1, offvalue=0, height=5, width=20)
C1.pack()
C2.pack()
top.mainloop()
Python Tkinter 标签控件(Label)及消息控件(Message)

Python Tkinter 标签控件(Label)指定的窗口中显示的文本和图像。如果需要使用一行或多行且不应该被用户更改的标签控件需要用label控件。

代码语言:javascript复制
w = Label ( master, option, ... )
# option 可选项内容与Button的可选项内容相近,但也有wraplength(标签文本显示行数)
代码语言:javascript复制
#一个简单样例:
import tkinter as tk
root = tk.Tk()
w = tk.Label(root, text="Hello RUNOOB!")
w.pack()
root.mainloop()

标签(Label)消息(Message):除了单行与多行的不同外,属性和用法基本一致,用于呈现文本信息。

值得注意的是:属性text通常用于实例在第一次呈现时的固定文本,而如果需要在程序执行后发生变化,则可以使用下列方法之一实现:

1、用控件实例的configure()方法来改变属性text的值,可使显示的文本发生变化;

代码语言:javascript复制
import tkinter
import time

def gettime():
      timestr = time.strftime("%H:%M:%S") # 获取当前的时间并转化为字符串
      lb.configure(text=timestr)   # 重新设置标签文本
      root.after(1000,gettime) # 每隔1s调用函数 gettime 自身获取时间

root = tkinter.Tk()
root.title('时钟')

lb = tkinter.Label(root,text='',fg='blue',font=("黑体",80))
lb.pack()
gettime()
root.mainloop()

2、先定义一个tkinter的内部类型变量var=StringVar() 的值也可以使显示文本发生变化。

代码语言:javascript复制
import tkinter
import time

def gettime():
      var.set(time.strftime("%H:%M:%S"))   # 获取当前时间
      root.after(1000,gettime)   # 每隔1s调用函数 gettime 自身获取时间

root = tkinter.Tk()
root.title('时钟')
var=tkinter.StringVar()
lb = tkinter.Label(root,textvariable=var,fg='blue',font=("黑体",80))
lb.pack()
gettime()
root.mainloop()
Python Tkinter 文本组件 (Text)

上表位置的取值可为整数,浮点数或END(末尾),例如0.0表示第0列第0行

代码语言:javascript复制
from tkinter import *
import time
import datetime
def gettime():
       s=str(datetime.datetime.now()) 'n'
       txt.insert(END,s)
       root.after(1000,gettime)  # 每隔1s调用函数 gettime 自身获取时间
root=Tk()
root.geometry('320x240')
txt=Text(root)
txt.pack()
gettime()
root.mainloop()
  • 输入框(Entry):通常作为功能比较单一的接收单行文本输入的控件,虽然也有许多对其中文本进行操作的方法,但通常用的只有取值方法get()和用于删除文本的delete(起始位置,终止位置),例如:清空输入框为delete(0,END)。

GUI应用程序类的通常写法

通过类application组织整个GUI程序,类application及继承了frame,及通过继承拥有了父类的特性。通过构造函数_init_()初始化窗口中的对象,通过createwidgets()方法创建窗口中的对象。

Frama框架是一个tkinter组件,表示一个矩形的区域。frame一般作为容器使用,可以放置其他组件,从而实现复杂的布局。

代码语言:javascript复制
import tkinter as tk
class Application(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        self.pack()
        self.create_widgets()
    def create_widgets(self):
        self.hi_there = tk.Button(self)
        self.hi_there["text"] = "Hello Worldn(click me)"
        self.hi_there["command"] = self.say_hi
        self.hi_there.pack(side="top")
        self.quit = tk.Button(self, text="QUIT", fg="red",
                              command=self.master.destroy)
        self.quit.pack(side="bottom")
    def say_hi(self):
        print("hi there, everyone!")
root = tk.Tk()
app = Application(master=root)
app.mainloop()

几何管理(控件布局)

Tkinter控件有特定的几何状态管理方法,管理整个控件区域组织,以下是Tkinter公开的几何管理类:包、网格、位置

几何方法

描述

pack()

包装;

grid()

网格;

place()

位置;

Pack()布局方式:

Pack()方法: 是一种简单的布局方法,如果不加参数的默认方式,将按布局语句的先后,以最小占用空间的方式自上而下地排列控件实例,并且保持控件本身的最小尺寸。

使用pack()方法可设置 fill、side 等属性参数。

pack()函数的属性

取值的对应意义

fill=X/y/BOTH

允许控件向水平方向、垂直方向或二维伸展填充未被占用控件

side=left/right/bottom

表示本控件实例的布局相对于下一个控件实例的方位

代码语言:javascript复制
from tkinter import  *
root = Tk()
lbred = Label(root,text="Red",fg="Red",relief=GROOVE)
lbred.pack()
lbgreen = Label(root,text="绿色",fg="green",relief=GROOVE)
lbgreen.pack(side=RIGHT)
lbblue = Label(root,text="蓝",fg="blue",relief=GROOVE)
lbblue.pack(fill=X)
root.mainloop()
grid()布局方式:

grid()方法:是基于网格的布局。先虚拟一个二维表格,再在该表格中布局控件实例。由于在虚拟表格的单元中所布局的控件实例大小不一,单元格也没有固定或均一的大小,因此其仅用于布局的定位。pack()方法与grid()方法不能混合使用。 grid()方法常用布局参数如下:

  • column: 控件实例的起始列,最左边为第0列。
  • columnspan: 控件实例所跨越的列数,默认为1列。
  • ipadx,ipady: 控件实例所呈现区域内部的像素数,用来设置控件实例的大小。
  • padx,pady: 控件实例所占据空间像素数,用来设置实例所在单元格的大小。
  • row: 控件实例的起始行,最上面为第0行。
  • rowspan: 控件实例的起始行数,默认为1行。
place()布局方法:

place()方法:根据控件实例在父容器中的绝对或相对位置参数进行布局。其常用布局参数如下:

  • x,y:控件实例在根窗体中水平和垂直方向上的其实位置(单位为像素)。注意,根窗体左上角为0,0,水平向右,垂直向下为正方向。
  • relx,rely:控件实例在根窗体中水平和垂直方向上起始布局的相对位置。即相对于根窗体宽和高的比例位置,取值在0.0~1.0之间。
  • height,width:控件实例本身的高度和宽度(单位为像素)。
  • relheight,relwidth:控件实例相对于根窗体的高度和宽度比例,取值在0.0~1.0之间。
  • 利用place()方法配合relx,rely和relheight,relwidth参数所得的到的界面可自适应根窗体尺寸的大小。place()方法与grid()方法可以混合使用。如下例子:利用place()方法排列消息(多行标签)。
代码语言:javascript复制
#参考样例:
from tkinter import *
root = Tk()
root.geometry('320x240')
msg1 = Message(root,text='''我的水平起始位置相对窗体 0.2,垂直起始位置为绝对位置 80 像素,我的高度是窗体高度的0.4,宽度是200像素''',relief=GROOVE)
msg1.place(relx=0.2,y=80,relheight=0.4,width=200)
root.mainloop()

Wxpython

Wxpython这个是我最后采用的gui库,倒不是因为有多大去别,主要是我找到了一个自动生成Wxpython的代码段的小程序,我最后选择了wxpython。

代码语言:javascript复制
# -*- coding:utf-8 -*-
import wx.lib.agw.hyperlink as lib_hyperlink
import wx

class Frame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title='网站源代码下载器', size=(800, 300),name='frame',style=541072384)
        self.qdck = wx.Panel(self)
        self.Centre()
        self.an1 = wx.Button(self.qdck,size=(100, 46),pos=(350, 135),label='下载',name='button')
        self.an1.SetAuthNeeded(True)
        self.an1.Bind(wx.EVT_BUTTON,self.an1_anbdj)
        self.bjk1 = wx.TextCtrl(self.qdck,size=(500, 30),pos=(150, 85),value='',name='text',style=4096)
        self.bjk1.SetMaxLength(50)
        self.bq1 = wx.StaticText(self.qdck,size=(365, 30),pos=(235, 30),label='请输入需要下载的链接',name='staticText',style=2321)
        bq1_字体 = wx.Font(16,74,90,700,False,'Microsoft YaHei UI',28)
        self.bq1.SetFont(bq1_字体)
        self.cjljkL1 = lib_hyperlink.HyperLinkCtrl(self.qdck,size=(100, 28),pos=(380, 200),name='staticText',label='使用说明',URL='https://im-so-scared-2.gitee.io/shier_jinghuang/')
        self.cjljkL1.SetToolTip(wx.ToolTip('使用说明'))
        cjljkL1_字体 = wx.Font(9,70,90,400,True,'Microsoft YaHei UI',-1)
        self.cjljkL1.SetFont(cjljkL1_字体)
        self.cjljkL1.SetForegroundColour((0, 0, 255, 255))
    def an1_anbdj(self,event):
        #print('an1,按钮被单击')
        pass
class myApp(wx.App):
    def  OnInit(self):
        self.frame = Frame()
        self.frame.Show(True)
        return True

if __name__ == '__main__':
    app = myApp()
    app.MainLoop()

1 人点赞