为 Tkinter 小部件启用 "setgrid" 选项
Enabling the "setgrid" option for a Tkinter widget
我正在使用 Tkinter 的 grid
几何管理器在第 2 列中生成带有水平滚动文本的 table。我尝试创建一个位于第 2 列中的 Listbox
小部件(作为整个框架的子项)并跨越所有行。这看起来很有希望,直到列表框中的文本行明显没有与父网格的行对齐。我一直在徒劳地寻找一种方法来填充列表框中的每一行文本,以便行匹配;但即使那是可能的,我也更喜欢更通用、更简单的解决方案。
我最近偶然发现了一个 description 的网格几何管理,它暗示了一个小部件的 setgrid 选项。它声称完全按照我的意愿行事:即“[确定] 此小部件是否控制其顶级 window 的调整网格大小。”我尝试在 Listbox
小部件中启用此选项,但无济于事。我是不是误解了 setgrid 的 purpose/usage?
(为了查看下面代码的问题,请使用 Select File
或 Select Folder
按钮将多个音频文件加载到文件列表中。)
#! /usr/bin/env python
#################################################
# This tool allows the user to select audio files
# (or folders containing audio files) and subject
# them to loudness analysis.
#################################################
import sys
import os
import codecs
import re
import Tkinter
from Tkinter import *
import tkFileDialog
from os import walk
from os import path
from Tkinter import Tk, Text, BOTH, W, N, E, S
from ttk import Frame, Button, Label, Style, Progressbar
from ScrolledText import *
from progressbar import ProgressBar
class Leveler_tk(Frame):
fileList = []
allowedExtensions = ['mp3','mp2','m4a','aiff','wav']
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initialize()
def initialize(self):
self.style = Style()
self.style.theme_use("default")
self.pack(fill=BOTH, expand=1)
self.columnconfigure(1, weight=1)
self.columnconfigure(2, weight=1)
self.columnconfigure(2, pad=250)
self.columnconfigure(3, weight=1)
self.columnconfigure(4, weight=1)
self.columnconfigure(5, weight=1)
lbl1 = Label(self, text="Analyze")
lbl1.grid(pady=4, padx=5,row=0,column=0)
lbl2 = Label(self, text="Adjust")
lbl2.grid(pady=4, padx=5,row=0,column=1)
lbl3 = Label(self, text="File")
lbl3.grid(pady=4, padx=5,row=0,column=2)
lbl4 = Label(self, text="Integrated\nLoudness")
lbl4.grid(pady=4, padx=5,row=0,column=3)
lbl5 = Label(self, text="LRA")
lbl5.grid(pady=4, padx=5,row=0,column=4)
lbl6 = Label(self, text="Peak")
lbl6.grid(pady=4, padx=5,row=0,column=5)
lbl7 = Label(self, text="Progress")
lbl7.grid(pady=4, padx=5,row=0,column=6)
lbl8 = Label(self, text="Meets\nSpecs?")
lbl8.grid(sticky=W, pady=4, padx=5,row=0,column=7)
file_btn = Button(self, text="Select File",command=self.selectFile)
file_btn.grid(row=1,rowspan=2, column=8,padx=5,pady=4)
folder_btn = Button(self, text="Select Folder", command=self.selectFolder)
folder_btn.grid(row=3, rowspan=2, column=8,padx=5,pady=4)
def render(self):
count = 0
filebox = Listbox(self,selectmode=EXTENDED,setgrid=1)
scrollbar = Scrollbar(filebox, orient=HORIZONTAL)
scrollbar.config(command=filebox.xview)
filebox.grid(row=1, column=2, rowspan=len(self.fileList), columnspan=1, sticky=N+S+E+W)
filebox.config(xscrollcommand=scrollbar.set)
scrollbar.pack(side=BOTTOM, fill=X)
for file in self.fileList:
analyze = IntVar()
adjust = IntVar()
Radiobutton(self, text="", variable=analyze, value=count, borderwidth=0).grid(row=count+1, column=0)
Radiobutton(self, text="", variable=adjust, value=count, borderwidth=0).grid(row=count+1, column=1)
filebox.insert(END, file + "\n")
Progressbar(self, orient=HORIZONTAL,length=100, mode='determinate').grid(row=count+1, column=6)
count += 1
def addToList(self, name):
dot = re.search("\.(?=[^.]*$)",name)
extension = name[dot.end():]
if extension in self.allowedExtensions and not name in self.fileList:
self.fileList.append(name)
def selectFile(self):
input = tkFileDialog.askopenfilename(filetypes = [('MP3', '*.mp3'), ('MP2', '*.mp2'), ('M4A', '*.m4a'), ('AIFF', '*.aiff'), ('WAV', '*.wav')], multiple = 1)
for el in input:
if os.path.isfile(el) and ".DS_Store" not in el:
try:
self.addToList(el)
except:
tkMessageBox.showerror("Some error")
self.render()
def selectFolder(self):
input = tkFileDialog.askdirectory()
for (dirpath, dirnames, filenames) in walk(input):
for name in filenames:
if name != ".DS_Store":
self.addToList(dirpath + "/" + name)
self.render()
def main():
root = Tk()
app = Leveler_tk(root)
root.mainloop()
if __name__ == "__main__":
main()
我觉得你误会了setgrid
。
这是为了让具有基于像素以外的其他东西的自然大小的小部件(例如文本小部件,其大小基于字符)可以防止父级将其设置为不自然的大小(例如:20.5 个字符)。使用 setgrid
,当您以交互方式调整 window 大小时,它将以网格单位(例如:字符高度或宽度)而不是像素调整大小。
setgrid
不会阻止调整大小,因为它确保调整大小发生在其他单位的倍数。
这里是 setgrid
选项的完整权威参考,来自 tcl/tk 手册:
Specifies a boolean value that determines whether this widget controls
the resizing grid for its top-level window. This option is typically
used in text widgets, where the information in the widget has a
natural size (the size of a character) and it makes sense for the
window's dimensions to be integral numbers of these units. These
natural window sizes form a grid. If the setGrid option is set to true
then the widget will communicate with the window manager so that when
the user interactively resizes the top-level window that contains the
widget, the dimensions of the window will be displayed to the user in
grid units and the window size will be
constrained to integral numbers of grid units. See the section GRIDDED
GEOMETRY MANAGEMENT in the wm manual entry for more details.
我正在使用 Tkinter 的 grid
几何管理器在第 2 列中生成带有水平滚动文本的 table。我尝试创建一个位于第 2 列中的 Listbox
小部件(作为整个框架的子项)并跨越所有行。这看起来很有希望,直到列表框中的文本行明显没有与父网格的行对齐。我一直在徒劳地寻找一种方法来填充列表框中的每一行文本,以便行匹配;但即使那是可能的,我也更喜欢更通用、更简单的解决方案。
我最近偶然发现了一个 description 的网格几何管理,它暗示了一个小部件的 setgrid 选项。它声称完全按照我的意愿行事:即“[确定] 此小部件是否控制其顶级 window 的调整网格大小。”我尝试在 Listbox
小部件中启用此选项,但无济于事。我是不是误解了 setgrid 的 purpose/usage?
(为了查看下面代码的问题,请使用 Select File
或 Select Folder
按钮将多个音频文件加载到文件列表中。)
#! /usr/bin/env python
#################################################
# This tool allows the user to select audio files
# (or folders containing audio files) and subject
# them to loudness analysis.
#################################################
import sys
import os
import codecs
import re
import Tkinter
from Tkinter import *
import tkFileDialog
from os import walk
from os import path
from Tkinter import Tk, Text, BOTH, W, N, E, S
from ttk import Frame, Button, Label, Style, Progressbar
from ScrolledText import *
from progressbar import ProgressBar
class Leveler_tk(Frame):
fileList = []
allowedExtensions = ['mp3','mp2','m4a','aiff','wav']
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initialize()
def initialize(self):
self.style = Style()
self.style.theme_use("default")
self.pack(fill=BOTH, expand=1)
self.columnconfigure(1, weight=1)
self.columnconfigure(2, weight=1)
self.columnconfigure(2, pad=250)
self.columnconfigure(3, weight=1)
self.columnconfigure(4, weight=1)
self.columnconfigure(5, weight=1)
lbl1 = Label(self, text="Analyze")
lbl1.grid(pady=4, padx=5,row=0,column=0)
lbl2 = Label(self, text="Adjust")
lbl2.grid(pady=4, padx=5,row=0,column=1)
lbl3 = Label(self, text="File")
lbl3.grid(pady=4, padx=5,row=0,column=2)
lbl4 = Label(self, text="Integrated\nLoudness")
lbl4.grid(pady=4, padx=5,row=0,column=3)
lbl5 = Label(self, text="LRA")
lbl5.grid(pady=4, padx=5,row=0,column=4)
lbl6 = Label(self, text="Peak")
lbl6.grid(pady=4, padx=5,row=0,column=5)
lbl7 = Label(self, text="Progress")
lbl7.grid(pady=4, padx=5,row=0,column=6)
lbl8 = Label(self, text="Meets\nSpecs?")
lbl8.grid(sticky=W, pady=4, padx=5,row=0,column=7)
file_btn = Button(self, text="Select File",command=self.selectFile)
file_btn.grid(row=1,rowspan=2, column=8,padx=5,pady=4)
folder_btn = Button(self, text="Select Folder", command=self.selectFolder)
folder_btn.grid(row=3, rowspan=2, column=8,padx=5,pady=4)
def render(self):
count = 0
filebox = Listbox(self,selectmode=EXTENDED,setgrid=1)
scrollbar = Scrollbar(filebox, orient=HORIZONTAL)
scrollbar.config(command=filebox.xview)
filebox.grid(row=1, column=2, rowspan=len(self.fileList), columnspan=1, sticky=N+S+E+W)
filebox.config(xscrollcommand=scrollbar.set)
scrollbar.pack(side=BOTTOM, fill=X)
for file in self.fileList:
analyze = IntVar()
adjust = IntVar()
Radiobutton(self, text="", variable=analyze, value=count, borderwidth=0).grid(row=count+1, column=0)
Radiobutton(self, text="", variable=adjust, value=count, borderwidth=0).grid(row=count+1, column=1)
filebox.insert(END, file + "\n")
Progressbar(self, orient=HORIZONTAL,length=100, mode='determinate').grid(row=count+1, column=6)
count += 1
def addToList(self, name):
dot = re.search("\.(?=[^.]*$)",name)
extension = name[dot.end():]
if extension in self.allowedExtensions and not name in self.fileList:
self.fileList.append(name)
def selectFile(self):
input = tkFileDialog.askopenfilename(filetypes = [('MP3', '*.mp3'), ('MP2', '*.mp2'), ('M4A', '*.m4a'), ('AIFF', '*.aiff'), ('WAV', '*.wav')], multiple = 1)
for el in input:
if os.path.isfile(el) and ".DS_Store" not in el:
try:
self.addToList(el)
except:
tkMessageBox.showerror("Some error")
self.render()
def selectFolder(self):
input = tkFileDialog.askdirectory()
for (dirpath, dirnames, filenames) in walk(input):
for name in filenames:
if name != ".DS_Store":
self.addToList(dirpath + "/" + name)
self.render()
def main():
root = Tk()
app = Leveler_tk(root)
root.mainloop()
if __name__ == "__main__":
main()
我觉得你误会了setgrid
。
这是为了让具有基于像素以外的其他东西的自然大小的小部件(例如文本小部件,其大小基于字符)可以防止父级将其设置为不自然的大小(例如:20.5 个字符)。使用 setgrid
,当您以交互方式调整 window 大小时,它将以网格单位(例如:字符高度或宽度)而不是像素调整大小。
setgrid
不会阻止调整大小,因为它确保调整大小发生在其他单位的倍数。
这里是 setgrid
选项的完整权威参考,来自 tcl/tk 手册:
Specifies a boolean value that determines whether this widget controls the resizing grid for its top-level window. This option is typically used in text widgets, where the information in the widget has a natural size (the size of a character) and it makes sense for the window's dimensions to be integral numbers of these units. These natural window sizes form a grid. If the setGrid option is set to true then the widget will communicate with the window manager so that when the user interactively resizes the top-level window that contains the widget, the dimensions of the window will be displayed to the user in grid units and the window size will be constrained to integral numbers of grid units. See the section GRIDDED GEOMETRY MANAGEMENT in the wm manual entry for more details.