examples - tkinter python 3
Los widgets de envoltura de Python Tkinter en el marco si alcanzan el final de la pantalla (2)
AFAIK no existe una forma incorporada de crear interfaces dinámicas en tkinter. Su mejor opción es obtener la resolución de la pantalla y luego la cuadrícula / paquete de forma adecuada.
user32 = ctypes.windll.user32
get_screensize = (user32.GetSystemMetrics(0), user32.GetSystemMetrics(1))
Así por ejemplo....
widget1 = tkinter.Entry(root,width=20,etc)
widget2 = tkinter.Label(root,text=''Hello'',etc)
## Now perform update_idletasks() which will force
## Tkinter to calculate their size.
widget1.update_idletasks()
widget2.update_idletasks()
## Now calculate whether they''ll fit.
if widget1.winfo_width() + widget2.winfo_width() > screensize[0]:## Not enough space
widget1.grid(row=0)
widget2.grid(row=1)
else:## Both will fit on one line.
widget1.grid(row=0,column=0)
widget2.grid(row=0,column=1)
¿Hay algo así como empaquetar una nueva línea para Tk Geometry Manager? Estoy usando paquete para poner widgets dentro de un marco. En una pantalla de alta resolución, los widgets encajan uno al lado del otro. Sin embargo, si lo coloca en una pantalla más pequeña, los widgets se quedarán sin espacio en el marco.
Básicamente, vamos desde:
a:
Puedes ver cómo se corta en el campo de entrada de mi procesador. El código relevante:
options_frame = ttk.LabelFrame(
parent_frame, text="Blast Options")
options_frame.pack(side=TOP, fill=X, expand=1, padx=5, pady=5)
self._set_up_blast_options(options_frame)
def _set_up_blast_options(self, options_frame):
self.evalue = Tkinter.DoubleVar()
self.evalue.set(1)
self.word_size = Tkinter.IntVar()
self.word_size.set(4)
self.penalty_mismatch = Tkinter.DoubleVar()
self.penalty_mismatch.set(-4)
self.min_d_match = Tkinter.IntVar()
self.min_d_match.set(5)
self.proc_count = Tkinter.IntVar()
self.proc_count.set(cpu_count())
# evalue
e_value_label = ttk.LabelFrame(
options_frame, text="e-Value Threshold")
e_value_entry = ttk.Entry(e_value_label)
e_value_entry.insert(0, self.evalue.get())
e_value_entry.bind(''<Return>'', self._validate_e_value)
e_value_entry.bind(''<FocusOut>'', self._validate_e_value)
e_value_label.pack(side=LEFT, expand=1, pady=5, padx=5, fill=X)
e_value_entry.pack(side=TOP, expand=1, pady=5, padx=5, fill=X)
# word size
word_size_label = ttk.LabelFrame(
options_frame, text="Word Size")
word_size_entry = ttk.Entry(word_size_label)
word_size_entry.insert(0, self.word_size.get())
word_size_entry.bind(''<Return>'', self._validate_word_value)
word_size_entry.bind(''<FocusOut>'', self._validate_word_value)
word_size_label.pack(side=LEFT, expand=1, pady=5, padx=5, fill=X)
word_size_entry.pack(side=TOP, expand=1, pady=5, padx=5, fill=X)
penalty_mismatch_label = ttk.LabelFrame(
options_frame, text="Penalty Mismatch")
penalty_mismatch_entry = ttk.Entry(penalty_mismatch_label)
penalty_mismatch_entry.insert(0, self.penalty_mismatch.get())
penalty_mismatch_entry.bind(
''<Return>'', self._validate_penalty_mismatch_value)
penalty_mismatch_entry.bind(
''<FocusOut>'', self._validate_penalty_mismatch_value)
penalty_mismatch_label.pack(side=LEFT, expand=1, pady=5,
padx=5, fill=X)
penalty_mismatch_entry.pack(side=TOP, expand=1, pady=5,
padx=5, fill=X)
# Min D Nucleotides
min_d_match_label = ttk.LabelFrame(
options_frame, text="Minimal Number of D Nucleotides")
min_d_match_entry = ttk.Entry(min_d_match_label)
min_d_match_entry.insert(0, self.min_d_match.get())
min_d_match_entry.bind(
''<Return>'', self._validate_min_match_value)
min_d_match_entry.bind(
''<FocusOut>'', self._validate_min_match_value)
min_d_match_label.pack(side=LEFT, expand=1, pady=5, padx=5, fill=X)
min_d_match_entry.pack(side=TOP, expand=1, pady=5, padx=5, fill=X)
# how many cpus to use
proc_count_label = ttk.LabelFrame(
options_frame, text="Processors")
proc_count_entry = ttk.Entry(proc_count_label)
proc_count_entry.insert(0, self.proc_count.get())
proc_count_entry.bind(
''<Return>'', self._validate_proc_count_value)
proc_count_entry.bind(
''<FocusOut>'', self._validate_proc_count_value)
proc_count_label.pack(side=LEFT, expand=1, pady=5, padx=5, fill=X)
proc_count_entry.pack(side=TOP, expand=1, pady=5, padx=5, fill=X)
Mucho del encuadernado del evento y la configuración de las opciones pueden no ser relevantes, pero pensé que debería incluir ... por las dudas. ¿La mejor opción sería cambiar a un administrador de red? El problema sería que este marco está dentro de otro ... y así sucesivamente. ¿No es que si comienzas a usar el administrador de la cuadrícula, tienes que usarlo para todo porque no puedes mezclar el administrador de la cuadrícula y el empaquetado en el mismo marco?
En general, estoy de acuerdo con la respuesta de I_do_python, pero haría una pequeña modificación. Pondría todos los widgets en un nuevo Frame, y utilizaría el ancho del Frame como la prueba de fuego en cuanto a si envolverlos. Y puede vincular un controlador de eventos para el evento "<Configure>"
que luego verifica si el contenido del Marco debe ser ajustado cuando la ventana de la aplicación (y por lo tanto el Marco) se redimensiona.
Escribí la siguiente función que usa el método de cuadrícula para insertar inteligentemente widgets en un marco. Ciertamente puede mejorarse, pero funciona para mí. Por lo general, si utiliza .grid()
para llenar un elemento primario, puede obtener espacio en blanco desperdiciado cuando los widgets de relleno varían en ancho. La función siguiente aborda esto dividiendo el padre en columnas lógicas ( divisions
en el código) y permitiendo que los widgets abarquen múltiples columnas. El resultado es un diseño de cuadrícula con mucho espacio blanco desperdiciado. Cuanto más altas sean las divisions
, mejor será el resultado, pero el valor predeterminado debería funcionar para la mayoría de las situaciones.
def smart_grid(parent, *args, **kwargs): # *args are the widgets!
divisions = kwargs.pop(''divisions'', 100)
force_f = kwargs.pop(''force'', False)
if ''sticky'' not in kwargs:
kwargs.update(sticky=''w'')
try:
parent.win_width
except:
parent.win_width = -1
winfo_width = parent.winfo_width()
if 1 < winfo_width != parent.win_width or force_f:
parent.win_width = winfo_width
row = col = width = 0
argc = len(args)
for i in range(argc):
widget_width = args[i].winfo_width()
columns = max(1, int(widget_width * float(divisions) / winfo_width))
width += widget_width
if width > winfo_width:
width = widget_width
row += 1
col = 0
args[i].grid(row=row, column=col, columnspan=columns, **kwargs)
col += columns
parent.update_idletasks() # update() #
return row + 1
Eventualmente tomaré unos minutos para reescribirlo con w.winfo_reqwidth()
y actualizaré mi publicación.