我有一个小Tkinter GUI脚本,我很满意,但有一个例外:我的帧似乎在运行时移动,具体取决于其中一个帧中显示的文本大小。它来自于:
......对此:
......而且这个:
...取决于列表框中的选择,即info_message
中显示的文本数量。这是我的代码:
# -*- coding: iso-8859-1 -*-
""" Layout
dice_frame (1,1) list_frame(1,2) info_frame (1,3)
ref_frame (2,1-3)
"""
from tkinter import *
import random
import pandas as pd
root = Tk()
root.wm_title("RP")
root.geometry('500x503')
root.resizable(0, 0)
# ----------------------------------- Dice ------------------------------------
def dice_1():
""" 2d6 generator without modifiers """
dice_result = random.randrange(1, 6) + random.randrange(1, 6)
dice_main.config(text=dice_result)
def dice_2(widget_1, widget_2):
""" Creature 2d6 dice with skill modifier """
dice_result = random.randrange(1, 6) + random.randrange(1, 6)
text = widget_2.cget('text')
if text != '±0':
modifier = int(text)
else:
modifier = 0
widget_1.config(text=dice_result + modifier)
# Dice widgets
dice_frame = Frame(root, bd=5)
dice_frame.grid(row=1, column=1)
dice_label = Label(dice_frame, text='Dice', justify=CENTER)
dice_label.pack()
dice_main = Button(dice_frame, text='2d6', command=dice_1, height=2, width=2,
font=('TkDefaultFont', 10))
dice_main.pack()
# ------------------------------- List & Info ---------------------------------
# Read stats and personalities from file
all_stats = pd.read_excel('Enemies.xlsx', sheetname='Sheet1', sep=';',
keep_default_na=False, encoding='iso-8859-1')
all_traits = pd.read_excel('NPC Traits.xlsx', sheetname='Sheet1', sep=';')
# Create and fill listbox
list_frame = Frame(root, bd=5)
list_frame.grid(row=1, column=2)
list_label = Label(list_frame, text='Enemies', font=('TkFixedFont', 12))
list_label.grid(row=1, column=1)
listbox1 = Listbox(list_frame, height=10, width=20)
for n in range(len(all_stats)):
listbox1.insert(n+1, all_stats.iloc[n][0])
listbox1.grid(row=2, column=1, pady=5)
# Info box for listbox selection
info_message = Message(root, width=300)
info_message.grid(row=1, column=3)
def list_selection(event):
""" Gets selection and info/stats for info_message """
index = int(listbox1.curselection()[0])
stats = all_stats.iloc[index]
info_text = str(stats[0]) + '\n' # just the name
for m in range(int((len(stats)-2)/2)): # rest of the stats
info_text += ('\n' + str(stats[4 + m*2]) + '\t' + str(stats[3 + m*2]))
info_message.config(text=info_text)
listbox1.bind('<ButtonRelease-1>', list_selection)
# -------------------------------- Load Stats ---------------------------------
def reduce(widget_1, widget_2):
""" Function for reducing the value of a skill by 2 """
# Gets current value
text = widget_1.cget('text')
if text == '±0':
value = 0
else:
value = int(text)
value += -2
# Sets new value based on previous value
if value > 0:
widget_1.config(text='+' + str(value))
elif value == 0:
widget_1.config(text='±0')
elif value == -2:
widget_1.config(text='-2')
elif value < -2:
widget_1.config(text='X ', state=DISABLED, relief=SUNKEN,
disabledforeground='red')
if widget_2 != '':
widget_2.config(text='', state=DISABLED, relief=FLAT)
def generate_traits():
""" Generates a random personality for a creature """
t1 = all_traits.iloc[random.randrange(1, 10)][random.randrange(1, 10)]
t2 = all_traits.iloc[random.randrange(1, 10)][random.randrange(1, 10)]
t3 = all_traits.iloc[random.randrange(1, 10)][random.randrange(1, 10)]
return [t1, t2, t3]
def load():
""" Function for loading a creature's stats into a new window """
# Create a new window
top = Toplevel(bd=10)
top.resizable(0, 0)
# Stats based on listbox selection
index = int(listbox1.curselection()[0])
stats = all_stats.iloc[index]
# Name
name = Label(top, text=stats[0], font=('TkDefaultFont', 12))
name.grid(row=1, column=1, columnspan=3)
# Separator line 1
separator_1 = Canvas(top, height=15, width=300)
separator_1.grid(row=2, column=1, columnspan=3)
separator_1.create_line(10, 7.5, 290, 7.5)
# Creates arbitrary number of modifier buttons, labels and associated dice
modifiers = dict()
skills = dict()
dice = dict()
for k in range(int((len(stats) - 4)/2)):
if stats[k*2 + 3] != '':
modifiers[k] = Button(top, text=stats[4 + k*2], command=lambda a=k:
reduce(modifiers[a], dice[a]), width=1)
skills[k] = Label(top, text=stats[3 + k*2], justify=CENTER)
dice[k] = Button(top, width=1, text='Roll', command=lambda a=k:
dice_2(dice[a], modifiers[a]))
modifiers[k].grid(row=k+3, column=1)
skills[k].grid(row=k+3, column=2)
dice[k].grid(row=k+3, column=3)
# Skill padding
padding_row = len(modifiers) + 4
padding_button = Button(top, width=1, text=stats[1])
padding_button.config(command=lambda: reduce(padding_button, ''))
padding_button.grid(row=padding_row, column=1)
padding_label = Label(top, text='Padding', justify=CENTER)
padding_label.grid(row=padding_row, column=2)
# Personality
if stats[2]:
# Separator line 2
separator_2 = Canvas(top, height=15, width=300)
separator_2.grid(row=padding_row + 1, column=1, columnspan=3)
separator_2.create_line(10, 7.5, 290, 7.5)
# Generate three random personality traits
traits = generate_traits()
trait_1 = Label(top, text=traits[0], justify=CENTER)
trait_1.grid(row=padding_row + 2, column=1)
trait_2 = Label(top, text=traits[1], justify=CENTER)
trait_2.grid(row=padding_row + 2, column=2)
trait_3 = Label(top, text=traits[2], justify=CENTER)
trait_3.grid(row=padding_row + 2, column=3)
# Button for loading a creature
load_button = Button(list_frame, text='Load', command=load)
load_button.grid(row=3, column=1, pady=5)
# ----------------------------- Reference sheet -------------------------------
ref_frame = Frame(root)
ref_frame.grid(row=3, column=1, columnspan=3, sticky=W)
image = PhotoImage(file='PDQ Table.gif')
ref_table = Label(ref_frame, image=image)
ref_table.pack()
root.mainloop()
有人知道为什么会这样吗?提前谢谢!
答案 0 :(得分:3)
因为网格布局管理器根据包含的小部件的大小确定行的大小,列。
指定minsize
,weight
(使用grid_columnconfigure
)可以帮助您解决问题。
例如,请尝试以下示例(使用或不使用grid_columnconfigure
):
指定minsize
:
root = Tk()
root.geometry('500x503')
def make_button_wider(): b['text'] += '++++++'
Label(root, text='Dice', justify=CENTER).grid(row=1, column=1)
Listbox(root).grid(row=1, column=2)
b = Button(root, text='make it wider', command=make_button_wider)
b.grid(row=1, column=3)
Label(root, text='a'*70).grid(row=3, column=1, columnspan=3)
root.grid_columnconfigure(1, minsize=200) # <<<
root.grid_columnconfigure(2, minsize=200) # <<<
root.mainloop()
指定weight
:
root = Tk()
root.geometry('500x503')
def make_button_wider(): b['text'] += '++++++'
Label(root, text='Dice', justify=CENTER).grid(row=1, column=1)
Listbox(root).grid(row=1, column=2)
b = Button(root, text='make it wider', command=make_button_wider)
b.grid(row=1, column=3)
Label(root, text='a'*70).grid(row=3, column=1, columnspan=3)
root.grid_columnconfigure(1, weight=0) # <<<
root.grid_columnconfigure(2, weight=0) # <<<
root.grid_columnconfigure(3, weight=1) # <<<
root.mainloop()
答案 1 :(得分:2)
看起来好像是因为你的布局是由内容决定的。您可以尝试锁定控件的大小以避免这种情况。
例如,请注意设置“选项”信息时帧的移动方式。正是这种东西导致你的控件被重新分配。