文章目录:
文章目录
一、Python GUI界面设计
1、所需的模块——tkinter
我在写代码的时候,并没有主动去下载这个模块,所以可以直接去引用。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import Tkinter
top = Tkinter.Tk()
# 进入消息循环
top.mainloop()
以上是一个实例,其主要过程为:
- 导入 Tkinter 模块
- 创建控件
- 指定这个控件的 master, 即这个控件属于哪一个
- 告诉 GM(geometry manager) 有一个控件产生了。
2、tkinter组件
Tkinter的提供各种控件,如按钮,标签和文本框,一个GUI应用程序中使用。这些控件通常被称为控件或者部件。
目前有15种Tkinter的部件。我们提出这些部件以及一个简短的介绍,在下面的表:
控件 | 描述 |
---|---|
Button | 按钮控件;在程序中显示按钮。 |
Canvas | 画布控件;显示图形元素如线条或文本 |
Checkbutton | 多选框控件;用于在程序中提供多项选择框 |
Entry | 输入控件;用于显示简单的文本内容 |
Frame | 框架控件;在屏幕上显示一个矩形区域,多用来作为容器 |
Label | 标签控件;可以显示文本和位图 |
Listbox | 列表框控件;在Listbox窗口小部件是用来显示一个字符串列表给用户 |
Menubutton | 菜单按钮控件,由于显示菜单项。 |
Menu | 菜单控件;显示菜单栏,下拉菜单和弹出菜单 |
Message | 消息控件;用来显示多行文本,与label比较类似 |
Radiobutton | 单选按钮控件;显示一个单选的按钮状态 |
Scale | 范围控件;显示一个数值刻度,为输出限定范围的数字区间 |
Scrollbar | 滚动条控件,当内容超过可视化区域时使用,如列表框。. |
Text | 文本控件;用于显示多行文本 |
Toplevel | 容器控件;用来提供一个单独的对话框,和Frame比较类似 |
3、标准属性
标准属性也就是所有控件的共同属性,如大小,字体和颜色等等。
属性 | 描述 |
---|---|
Dimension | 控件大小; |
Color | 控件颜色; |
Font | 控件字体; |
Anchor | 锚点; |
Relief | 控件样式; |
Bitmap | 位图; |
Cursor | 光标; |
4、几何管理
Tkinter控件有特定的几何状态管理方法,管理整个控件区域组织,一下是Tkinter公开的几何管理类:包、网格、位置
几何方法 | 描述 |
---|---|
pack() | 包装; |
grid() | 网格; |
place() | 位置; |
二、python随机数产生
因为此文章主要是解释如何写出一个界面猜数游戏,数字要随机产生,那么随机生成数的方法有很多种,我只介绍几种。
1、random.random()函数
用于生成一个的随机符点数.
2、random.uniform(a,b)函数
两个参数其中一个是上限,一个是下限。如果a > b,则生成随机数
n: a <=n <=b。如果 a <b, 则 b <=n <=a
print random.uniform(10, 20)
print random.uniform(20, 10)
#----
#18.7356606526
#12.5798298022
3、random.randint(a,b)函数
用于生成一个指定范围内的整数。其中参数a是下限,参数b是上限,Python生成其中随机数.
print random.randint(12, 20) #生成的随机数n: 12 <= n <= 20
print random.randint(20, 20) #结果永远是20
#print random.randint(20, 10) #该语句是错误的。
意思就是说,在这个函数当中,a只能小于b,否则达不到产生随机数的效果。
4、random.randrange(a,b,step)函数
按步长随机在上下限范围内取一个随机数
print random.randrange(20,100,5)
三、猜数游戏
准备工作大致都做完了,我们就来看看如何做一个gui界面的游戏。其实很简单,游戏规则是:这是一个闯关的游戏,每一个都有三次机会,如果猜对了就可以闯入下一关,如果三次机会都猜错了,就会重新回到第一关再进行游戏。当然,每次猜错后都会有提示,告诉你大了还是小了,或者说你输入的不太正确。其实听起来,挺简单的,做起来也不难。
1、写出一个界面
这个我在第一个标题就写了,不多加赘述。因为我的代码是根据其他人的代码修改的,所以有些复杂,其实写出一个gui界面很简单。
# 主窗
class MyApp(tk.Tk):
def __init__(self):
super().__init__()
#self.pack() # 若继承 tk.Frame ,此句必须有!
self.title('猜数游戏')
# 程序参数/数据
self.setupUI()
def setupUI(self):
# 第一行(两列)
self.geometry("400x300")
row1 = tk.Frame(self)
row1.pack(fill="x")
# 第二行
row2 = tk.Frame(self)
row2.pack(fill="x")
tk.Label(row2, text='游戏规则: 输入一个数字,每一轮有三次机会来猜测0-15中的任意数字.', width=150).pack(side=tk.LEFT)
# 第三行
row3 = tk.Frame(self)
row3.pack(fill="x")
tk.Label(row3, text='可以为小数,看看你能闯到第几关~', width=150).pack(side=tk.LEFT)
#row8 = tk.Frame(self)
#row8.pack(fill="x")
tk.Button(text="开始游戏", command=self.setup_config).pack(side=tk.BOTTOM)
# 设置参数
def setup_config(self):
# 接收弹窗的数据
res = self.ask_userinfo()
# 弹窗
def ask_userinfo(self):
inputDialog = MyDialog()
self.wait_window(inputDialog) # 这一句很重要!!!
return inputDialog.userinfo
其中写了一个MyApp的类,同时定义了一个界面 (tk.Tk),然后定义了他的标题。但是,可能你定义的时候,窗口太小了,那么可以用_tk.geometry(“400x300”)_等代码来设计一个合适的尺寸.需要注意的一点是,这个x是英文字母x,当时自作主张写成了*。
然后,在界面中添加了三行,第二行和第三行添加了标签,最后添加了一个按钮。当然,也可以使用函数来移动位置。
2、图形位置
2.1 pack()
pack 使用很简单,就是w.pack(option)。常用的option有:
side 表示把组件放到哪一边,TOP(上),BOTTOM(下),LEFT,RIGHT
Padx 和pady 表示parcel的每一个边和组件的预留空间。
ipadx 和ipady,表示组件的每一个边和他包含的内容之间的预留空间。
Anchor 表示在parcel放置组件的方式,缺省时CENTER。
2.2 grid()
使用方法和pack类似。
2.3 place()
精确的摆放一个组件的位置,一般不太用。
3、获取文本框中的数据
遇到了一些问题,说是text不存在,到现在仍然不太清楚为什么。我就将其写成了self.text,就可以在别的函数使用了.
self.text = tk.Entry(row2, width=20)
self.text.pack(side=tk.LEFT)
def ok(self):
...
self.userinfo = self.text.get() # 设置数据
另外,还要如果要get到文本框数据,就要分离pack,不可以写成
self.text=tk.Entry(row2,width=20).pack(side=tk.LEFT)
要分开写,目前不知道为什么。
4、按钮触发事件
tk.Button( row4,text="退出游戏",command=self.cancel).pack(side=tk.RIGHT)
command后面接要进入的函数.
5、检测游戏轮数和机会次数(全局变量)
游戏轮数和机会次数都用全局变量表示。
def ok(self):
global i
global a
global h
i = i+1
print(a)
print ("第"+str(i)+"次机会")
self.userinfo = self.text.get() # 设置数据
if(self.userinfo == ''):
#tk.Label(text="第"+str(i)+"次机会", width=10).pack(side=tk.LEFT)
tk.messagebox.showerror("Error", "第"+str(h)+"轮 "+"第"+str(i)+"次机会"+" 输入不能为空")
elif not re.findall('[0-9]+',str(self.userinfo)):
tk.messagebox.showerror("Error", "请输入数字")
else:
self.userinfo = int(self.userinfo)
if(self.userinfo == a):
#tk.Label(text="第"+str(i)+"次机会", width=10).pack(side=tk.LEFT)
tk.messagebox.showinfo("Corret", "第"+str(h)+"轮 "+"第"+str(i)+"次机会"+" 输入正确")
h = h+1
i = 0
a = random.randint(0, 15)
elif(self.userinfo < a):
#tk.Label(text="第"+str(i)+"次机会", width=10).pack(side=tk.LEFT)
tk.messagebox.showerror("Error", "第"+str(h)+"轮 "+"第"+str(i)+"次机会"+" 小了一点点")
elif(self.userinfo > a):
#tk.Label(text="第"+str(i)+"次机会", width=10).pack(side=tk.LEFT)
tk.messagebox.showerror("Error", "第"+str(h)+"轮 "+"第"+str(i)+"次机会"+" 大了一点点")
if(i == 3):
i=0
h = 1
a = random.randint(0, 15)
print(a)
每次猜对,就将轮数加一,猜一次i(一关的游戏次数)都要加1,当到3时,就代表这一关的机会都用完了,没有机会继续猜了,就会重新再给一个随机数,代表闯关失败,重新到第一关,并且这一轮的游戏次数也会变成第一次。当然了,无论是次数还是轮数都要及时的进行初始化。
在以上代码中i代表次数,a代表随机数,h代表轮数。
四、完整代码
import tkinter as tk
import random
import re
import tkinter.messagebox
class MyDialog(tk.Toplevel):
def __init__(self):
super().__init__()
self.title('猜数游戏')
# 弹窗界面
self.setup_UI()
a = random.randint(0, 15)
def setup_UI(self):
self.geometry("400x100")
row2 = tk.Frame(self)
row2.pack(fill="x", ipadx=1, ipady=1)
tk.Label(row2, text='请输入数据: ', width=8).pack(side=tk.LEFT)
#self.number = tk.IntVar()
self.text = tk.Entry(row2, width=20)
self.text.pack(side=tk.LEFT)
#text = tk.Entry(row2, textvariable=self.number, width=20).pack(side=tk.LEFT)
#self.number = text.get()
# 第三行
row3 = tk.Frame(self)
row3.pack(fill="x", ipadx=1, ipady=1)
tk.Label(row3, text=' ', width=8).pack(side=tk.LEFT)
row4 = tk.Frame(self)
row4.pack(fill="x", ipadx=1, ipady=1)
tk.Button( row4,text="退出游戏", command=self.cancel).pack(side=tk.RIGHT)
tk.Button(row4, text="确定", command=self.ok).pack(side=tk.RIGHT)
def ok(self):
global i
global a
global h
i = i+1
print(a)
print ("第"+str(i)+"次机会")
self.userinfo = self.text.get() # 设置数据
if(self.userinfo == ''):
#tk.Label(text="第"+str(i)+"次机会", width=10).pack(side=tk.LEFT)
tk.messagebox.showerror("Error", "第"+str(h)+"轮 "+"第"+str(i)+"次机会"+" 输入不能为空")
elif not re.findall('[0-9]+',str(self.userinfo)):
tk.messagebox.showerror("Error", "请输入数字")
else:
self.userinfo = int(float(self.userinfo))
if(self.userinfo == a):
#tk.Label(text="第"+str(i)+"次机会", width=10).pack(side=tk.LEFT)
tk.messagebox.showinfo("Corret", "第"+str(h)+"轮 "+"第"+str(i)+"次机会"+" 输入正确")
h = h+1
i = 0
a = random.randint(0, 15)
elif(self.userinfo < a):
#tk.Label(text="第"+str(i)+"次机会", width=10).pack(side=tk.LEFT)
tk.messagebox.showerror("Error", "第"+str(h)+"轮 "+"第"+str(i)+"次机会"+" 小了一点点")
elif(self.userinfo > a):
#tk.Label(text="第"+str(i)+"次机会", width=10).pack(side=tk.LEFT)
tk.messagebox.showerror("Error", "第"+str(h)+"轮 "+"第"+str(i)+"次机会"+" 大了一点点")
if(i == 3):
i=0
h = 1
a = random.randint(0, 15)
print(a)
#self.destroy() # 销毁窗口
def cancel(self):
self.userinfo = None # 空!
self.destroy()
# 主窗
class MyApp(tk.Tk):
def __init__(self):
super().__init__()
#self.pack() # 若继承 tk.Frame ,此句必须有!
self.title('猜数游戏')
# 程序参数/数据
self.setupUI()
def setupUI(self):
# 第一行(两列)
self.geometry("400x300")
row1 = tk.Frame(self)
row1.pack(fill="x")
# 第二行
row2 = tk.Frame(self)
row2.pack(fill="x")
tk.Label(row2, text='游戏规则: 输入一个数字,每一轮有三次机会来猜测0-15中的任意数字.', width=150).pack(side=tk.LEFT)
# 第三行
row3 = tk.Frame(self)
row3.pack(fill="x")
tk.Label(row3, text='可以为小数,看看你能闯到第几关~', width=150).pack(side=tk.LEFT)
#row8 = tk.Frame(self)
#row8.pack(fill="x")
tk.Button(text="开始游戏", command=self.setup_config).pack(side=tk.BOTTOM)
# 设置参数
def setup_config(self):
# 接收弹窗的数据
res = self.ask_userinfo()
# 弹窗
def ask_userinfo(self):
inputDialog = MyDialog()
self.wait_window(inputDialog) # 这一句很重要!!!
return inputDialog.userinfo
if __name__ == '__main__':
a = random.randint(0, 15)
i = 0
h = 1
app = MyApp()
app.mainloop()
五、呈现效果
开始界面
输入空白弹出提示框
输入小了弹出提示框
输入大了弹出提示框
输入小数弹出提示框
输入正确弹出提示框
当进入输入正确,进入下一轮
六、参考文章
AttributeError: ‘NoneType’ object has no attribute ‘get’ [duplicate]