如何在tkinter窗体上动态创建组件以及销毁组件的方法。
import tkinter
import tkinter.messagebox
import tkinter.simpledialog
btnList = []
# 动态创建组件,并计算组件在窗体上的位置
def place(n):
for i in range(n):
exec('btn'+str(i)+'=tkinter.Button(root,text='+str(i)+')')
eval('btn'+str(i)).place(x=80, y=10+i*30, width=60, height=20)
btnList.append(eval('btn'+str(i)))
root.geometry('200x'+str((n)*30+70)+'+400+300')
return n*30 + 10
# 创建tkinter应用程序
root = tkinter.Tk()
# 窗口标题
root.title('动态创建组件')
# 窗口初始大小和位置
root.geometry('200x180+400+300')
# 不允许改变窗口大小
root.resizable(False, False)
# 增加按钮的按钮
def btnSetClick():
n = tkinter.simpledialog.askinteger(title='输入一个整数',
prompt='想动态增加几个按钮:',
initialvalue=3)
if n and n>0:
startY = place(n)
modify(startY)
# 根据需要禁用和启用“增加按钮”和“清空按钮”
btnSet['state'] = 'disabled'
btnClear['state'] = 'normal'
btnSet = tkinter.Button(root,
text='增加按钮',
command=btnSetClick)
def btnClearClick():
global btnList
# 删除动态创建的按钮
for btn in btnList:
btn.destroy()
btnList = []
modify(20)
btnClear['state'] = 'disabled'
btnSet['state'] = 'normal'
btnClear = tkinter.Button(root,
text='清空按钮',
command=btnClearClick)
# 默认处于禁用状态
btnClear['state'] = 'disabled'
# 动态调整“增加按钮”和“清空按钮”的位置
def modify(startY):
btnSet.place(x=10, y=startY, width=80, height=20)
btnClear.place(x=100, y=startY, width=80, height=20)
modify(20)
root.mainloop()
代码运行后初始状态为:单击“增加按钮”后,在d出的窗口中输入5,然后窗体变为下面的样子:
单击“清空按钮“后恢复到初始状态。
您可以通过my_btn = Button(master, ...) 记住每个按钮的id,其中my_btn 将是按钮的id。然后将它们收集到列表中,并在每次要调用按其 ID 添加的所有按钮时使用 for 循环。见:import tkinter as tk
button_list = []
master = tk.Tk()
def change_color():
for button in button_list:
button.config(bg='red')
my_btn = tk.Button(master, text="Button 1")
my_btn.pack()
button_list.append(my_btn)
my_btn = tk.Button(master, text="Button 2")
my_btn.pack()
button_list.append(my_btn)
my_btn = tk.Button(master, text="Button 3")
my_btn.pack()
button_list.append(my_btn)
my_btn = tk.Button(master, text="CHANGE COLOR", command=change_color)
my_btn.pack()
master.mainloop()
您可以使用字典而不是列表来选择您需要的按钮,这将是更好的做法。
当然你可以参考上面代码中的所有按钮,但我认为你永远不需要它。
顺便说一句,您不需要使用is not None,因为if btn connected variable 已经返回布尔值,所以您的循环应该如下所示:
for btn in btns_list:
if btn connected variable:
btn.config(text='Press to reconfig', fg='green')
编辑 1:
用字典代替列表的例子:
import tkinter as tk
# dictionary with buttons
d = {}
master = tk.Tk()
def change_color():
# for loop for dict keys
for button in d.keys():
# here we refer to each button(value of button key)
# and change the color
#
# here you can add some if statements to edit particular group
# of buttons
d[button].config(bg='red')
my_btn = tk.Button(master, text="Button 1")
my_btn.pack()
d['group1_btn_name1'] = my_btn
my_btn = tk.Button(master, text="Button 2")
my_btn.pack()
d['group2_btn_name2'] = my_btn
my_btn = tk.Button(master, text="Button 3")
my_btn.pack()
d['group1_btn_name3'] = my_btn
my_btn = tk.Button(master, text="CHANGE COLOR", command=change_color)
my_btn.pack()
master.mainloop()
但请记住 - 字典中的每个键都应该是唯一的,因此按钮名称(键)都应该不同 (btn_name1, btn_name2, btn_name3)。您可以通过添加诸如some_group_btn1, some_group_btn2 ... other_group_btnnnn... 之类的前缀来对它们进行分组
您可以创建具有任何名称的按钮和组,但某些东西(例如_)应该划分组前缀和按钮名称,以便在字典键中定义特定的组名称。例如,您可以添加这样的 if 语句:
if 'group1' in button.split('_'):
d[button].config(bg='red')
它将修改仅引用group1 组的按钮。但是请记住,由于拆分 *** 作,您想要的除号_ 或- 应该始终相同。
检查字典键here
关于拆分here
from tkinter import *#2.获取到小圆移动的圆心坐标(x2, y2)
#3.把小圆从坐标(x1, y1)移动到坐标(x2, y2)
__author__ = {'name' : 'Hongten',
'mail' : 'hongtenzone@foxmail.com',
'blog' : 'http://www.cnblogs.com/',
'QQ': '648719819',
'created' : '2013-09-20'}
class Eay(Frame):
def createWidgets(self):
## The playing field
self.draw = Canvas(self, width=500, height=500)
#鼠标位置
self.mouse_x = 450
self.mouse_y = 250
#圆心坐标(x,y)
self.oval_zero_x = 250
self.oval_zero_y = 250
#外面大圆半径
self.oval_r = 100
#里面小圆半径
self.oval_R = 30
self.oval_r1 = self.oval_r - self.oval_R + 0.5
self.oval_r2 = self.oval_r - self.oval_R - 0.5
#小圆
self.letter_ball_x1 = 250
self.letter_ball_y1 = 250
# The ball 外面大圆
self.ball = self.draw.create_oval((self.oval_zero_x - self.oval_r),
(self.oval_zero_y - self.oval_r),
(self.oval_zero_x + self.oval_r),
(self.oval_zero_y + self.oval_r),
fill="white")
self.ball = self.draw.create_oval((self.oval_zero_x - self.oval_r1),
(self.oval_zero_y - self.oval_r1),
(self.oval_zero_x + self.oval_r1),
(self.oval_zero_y + self.oval_r1),
fill="blue")
self.ball = self.draw.create_oval((self.oval_zero_x - self.oval_r2),
(self.oval_zero_y - self.oval_r2),
(self.oval_zero_x + self.oval_r2),
(self.oval_zero_y + self.oval_r2),
fill="white")
#里面小圆
self.ball_over = self.draw.create_oval((self.oval_zero_x - self.oval_R),
(self.oval_zero_y - self.oval_R),
(self.oval_zero_x + self.oval_R),
(self.oval_zero_y + self.oval_R),
fill="red")
self.draw.pack(side=LEFT)
def mouseMove(self, event):
self.mouse_x = event.x
self.mouse_y = event.y
if SHOW_LOG:
print('#' * 50)
print('鼠标的坐标为:({}, {})'.format(self.mouse_x, self.mouse_y))
print('小圆当前坐标为:({}, {})'.format(self.letter_ball_x1, self.letter_ball_y1))
'''获取到小圆移动的圆心坐标(x2, y2)'''
ax_x = abs(self.mouse_x - self.oval_zero_x)
ax_y = abs(self.mouse_y - self.oval_zero_y)
if SHOW_LOG:
print('坐标A(oval_zero_x, oval_zero_y)到坐标X(mouse_x, mouse_y)的距离为AX')
print('AX中ax_x = {}, ax_y = {}'.format(ax_x, ax_y))
ax_len = ((ax_x ** 2) + (ax_y ** 2))**0.5
if SHOW_LOG:
print('AX的长度为:{}'.format(ax_len))
#如果鼠标坐标在(ax_len > |r-R|)
if ax_len > abs(self.oval_r - self.oval_R):
ac_len = abs(self.oval_r - self.oval_R)
if SHOW_LOG:
print('AC的产度为:{}'.format(ac_len))
if int(self.mouse_x - self.oval_zero_x) != 0:
if int(self.mouse_y - self.oval_zero_y) != 0:
#求直线斜率 y = kx + b
k = (self.mouse_y - self.oval_zero_y)/(self.mouse_x - self.oval_zero_x)
if SHOW_LOG:
print('鼠标到大圆圆心的直线的斜率为:{}'.format(k))
b = self.mouse_y - (k * self.mouse_x)
###################################################
#小圆移动后的坐标
#这里有三个条件:
# 1.小圆的圆心坐标(x1, y1)在直线AC上(y = kx + b)
# 2.(r-R)^2 = x1^2 + y1^2 由1,2可以得到 => (r-R)^2 = x1^2 + 2*x1*k*b + b^2 => x1有两个值,通过3判断x1的符号,从而求出y1
# 3.if self.mousex_x > 0:
# x1 > 0
#这是一个二元二次方程,方程的解有两组,不过通过鼠标的位置self.mouse_x(self.mouse_y)可以判断圆心坐标x1(y1)
letter_ball_x2 = ((ac_len * (abs(self.mouse_x - self.oval_zero_x)))/ax_len) + self.letter_ball_x1
letter_ball_y2 = (letter_ball_x2 * k) + b
if SHOW_LOG:
print('小圆当前坐标为:({}, {})'.format(self.letter_ball_x1, self.letter_ball_y1))
print('小圆移动后坐标为:({}, {})'.format(letter_ball_x2, letter_ball_y2))
#把小圆从坐标(x1, y1)移动到坐标(x2, y2)
self.moved_x2 = letter_ball_x2 - self.letter_ball_x1
self.moved_y2 = letter_ball_y2 - self.letter_ball_y1
if SHOW_LOG:
print('需要移动的距离是:({}, {})'.format(int(self.moved_x2), int(self.moved_y2)))
self.draw.move(self.ball_over, int(self.moved_x2), int(self.moved_y2))
self.letter_ball_x1 = letter_ball_x2
self.letter_ball_y1 = letter_ball_y2
else:
print('鼠标在X轴上')
else:
print('鼠标在Y轴上')
else:
if SHOW_LOG:
print('小圆的移动后的坐标就是鼠标坐标')
#小圆移动后的坐标
letter_ball_x2 = self.mouse_x
letter_ball_y2 = self.mouse_y
if SHOW_LOG:
print('小圆移动后坐标为:({}, {})'.format(letter_ball_x2, letter_ball_y2))
#把小圆从坐标(x1, y1)移动到坐标(x2, y2)
self.moved_x2 = letter_ball_x2 - self.letter_ball_x1
self.moved_y2 = letter_ball_y2 - self.letter_ball_y1
if SHOW_LOG:
print('需要移动的距离是:({}, {})'.format(int(self.moved_x2), int(self.moved_y2)))
self.draw.move(self.ball_over, int(self.moved_x2), int(self.moved_y2))
self.letter_ball_x1 = letter_ball_x2
self.letter_ball_y1 = letter_ball_y2
def move_ball(self, *args):
#当鼠标在窗口中按下左键拖动的时候执行
Widget.bind(self.draw, "<B1-Motion>", self.mouseMove)
#当鼠标在大圆内移动的时候执行
#self.draw.tag_bind(self.ball, "<Any-Enter>", self.mouseMove)
def __init__(self, master=None):
global letter_ball_x2
letter_ball_x2 = 0
global letter_ball_y2
letter_ball_y2 = 0
global SHOW_LOG
SHOW_LOG = True
Frame.__init__(self, master)
Pack.config(self)
self.createWidgets()
self.after(10, self.move_ball)
game = Eay()
game.mainloop()
效果
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)