#python #tkinter #combobox
Вопрос:
Цель состоит в том, чтобы позволить пользователю выбрать из выпадающего списка выпадающих окон, а затем нажать кнопку «Выбрать файлы». Кнопка получит тип продукта (значение из списка) и откроет правильный каталог, основанный на том, что выбрано в списке. Проблема в том, что я, похоже, не могу получить это значение, так как кнопка и выпадающий список находятся в разных кадрах. Я чувствую, что упускаю здесь что-то основное.
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog as fd
def select_files(prod_type):
path = f"\\10.10.3.7\Production\Test_Folder\{prod_type}"
filetypes = (
('PDF Files', '*.pdf'),
)
filenames = fd.askopenfilenames(
title='Open files',
initialdir=path,
filetypes=filetypes)
for file in filenames:
print(file)
class InputFrame(ttk.Frame):
def __init__(self, parent):
super().__init__(parent)
# setup the grid layout manager
self.columnconfigure(0, weight=1)
self.columnconfigure(0, weight=3)
self.__create_widgets()
def __create_widgets(self):
# Product
ttk.Label(self, text='Product:').grid(column=0, row=0, sticky=tk.W)
self.product_type = tk.StringVar()
self.product_combo = ttk.Combobox(self, width=30, textvariable=self.product_type)
self.product_combo['values'] = ('Notepad', 'Flat Notecard', 'Folded Notecard', 'Journal')
self.product_combo.set('Notepad')
self.product_combo['state'] = 'readonly'
self.product_combo.grid(column=1, row=0, sticky=tk.W)
# Algorithm:
ttk.Label(self, text='Algorithm:').grid(column=0, row=1, sticky=tk.W)
algo_var = tk.StringVar()
algo_combo = ttk.Combobox(self, width=30)
algo_combo['values'] = ('panel', 'fuzzy')
algo_combo.set('panel')
algo_combo.grid(column=1, row=1, sticky=tk.W)
# Orientation:
ttk.Label(self, text='Orientation:').grid(column=0, row=2, sticky=tk.W)
orientation_var = tk.StringVar()
orientation_combo = ttk.Combobox(self, width=30, textvariable=orientation_var)
orientation_combo['values'] = ('auto', 'portrait', 'landscape')
orientation_combo.set('auto')
orientation_combo.grid(column=1, row=2, sticky=tk.W)
# Margin:
ttk.Label(self, text='Margin:').grid(column=0, row=3, sticky=tk.W)
margin = ttk.Entry(self, width=30)
margin.grid(column=1, row=3, sticky=tk.W)
# Gap:
ttk.Label(self, text='Gap:').grid(column=0, row=4, sticky=tk.W)
gap = ttk.Entry(self, width=30)
gap.grid(column=1, row=4, sticky=tk.W)
# Repeat:
ttk.Label(self, text='Repeat:').grid(column=0, row=5, sticky=tk.W)
repeat_number = tk.StringVar()
repeat = ttk.Spinbox(self, from_=1, to=10, width=30, textvariable=repeat_number)
repeat.set(1)
repeat.grid(column=1, row=5, sticky=tk.W)
for widget in self.winfo_children():
widget.grid(padx=0, pady=5)
class ButtonFrame(ttk.Frame):
def __init__(self, parent):
super().__init__(parent)
# setup the grid layout manager
self.columnconfigure(0, weight=1)
self.__create_widgets()
def __create_widgets(self):
ttk.Button(self, text='Select Files', command=self.on_go_pressed).grid(column=0, row=0)
ttk.Button(self, text='Generate PDF').grid(column=0, row=1)
for widget in self.winfo_children():
widget.grid(padx=0, pady=3)
def on_go_pressed(self):
select_files(InputFrame.product_type.get())
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title("PDF n-up")
self.eval('tk::PlaceWindow . center')
self.geometry('400x200')
self.resizable(0, 0)
self.attributes('-toolwindow', True)
# layout on the root window
self.columnconfigure(0, weight=4)
self.columnconfigure(1, weight=1)
self.__create_widgets()
def __create_widgets(self):
# create the input frame
input_frame = InputFrame(self)
input_frame.grid(column=0, row=0)
# create the button frame
button_frame = ButtonFrame(self)
button_frame.grid(column=1, row=0)
if __name__ == '__main__':
app = App()
app.mainloop()
Ответ №1:
Вы можете передать переменную типа продукта ButtonFrame
при ее создании, так как вы создаете ее ButtonFrame
после создания InputFrame
. Вот код, с измененными и добавленными строками, отмеченными соответствующим образом:
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog as fd
def select_files(prod_type):
path = f"/home/sam/Pictures/Test/{prod_type}"
filetypes = (
('PDF Files', '*.pdf'),
)
filenames = fd.askopenfilenames(
title='Open files',
initialdir=path,
filetypes=filetypes)
for file in filenames:
print(file)
class InputFrame(ttk.Frame):
def __init__(self, parent):
super().__init__(parent)
# setup the grid layout manager
self.columnconfigure(0, weight=1)
self.columnconfigure(0, weight=3)
self.__create_widgets()
def __create_widgets(self):
# Product
ttk.Label(self, text='Product:').grid(column=0, row=0, sticky=tk.W)
self.product_type = tk.StringVar()
self.product_combo = ttk.Combobox(self, width=30, textvariable=self.product_type)
self.product_combo['values'] = ('Notepad', 'Flat Notecard', 'Folded Notecard', 'Journal')
self.product_combo.set('Notepad')
self.product_combo['state'] = 'readonly'
self.product_combo.grid(column=1, row=0, sticky=tk.W)
# Algorithm:
ttk.Label(self, text='Algorithm:').grid(column=0, row=1, sticky=tk.W)
algo_var = tk.StringVar()
algo_combo = ttk.Combobox(self, width=30)
algo_combo['values'] = ('panel', 'fuzzy')
algo_combo.set('panel')
algo_combo.grid(column=1, row=1, sticky=tk.W)
# Orientation:
ttk.Label(self, text='Orientation:').grid(column=0, row=2, sticky=tk.W)
orientation_var = tk.StringVar()
orientation_combo = ttk.Combobox(self, width=30, textvariable=orientation_var)
orientation_combo['values'] = ('auto', 'portrait', 'landscape')
orientation_combo.set('auto')
orientation_combo.grid(column=1, row=2, sticky=tk.W)
# Margin:
ttk.Label(self, text='Margin:').grid(column=0, row=3, sticky=tk.W)
margin = ttk.Entry(self, width=30)
margin.grid(column=1, row=3, sticky=tk.W)
# Gap:
ttk.Label(self, text='Gap:').grid(column=0, row=4, sticky=tk.W)
gap = ttk.Entry(self, width=30)
gap.grid(column=1, row=4, sticky=tk.W)
# Repeat:
ttk.Label(self, text='Repeat:').grid(column=0, row=5, sticky=tk.W)
repeat_number = tk.StringVar()
repeat = ttk.Spinbox(self, from_=1, to=10, width=30, textvariable=repeat_number)
repeat.set(1)
repeat.grid(column=1, row=5, sticky=tk.W)
for widget in self.winfo_children():
widget.grid(padx=0, pady=5)
class ButtonFrame(ttk.Frame):
def __init__(self, parent, product_type): ### EDITED THIS LINE
super().__init__(parent)
# setup the grid layout manager
self.columnconfigure(0, weight=1)
self.product_type = product_type ### ADDED THIS LINE
self.__create_widgets()
def __create_widgets(self):
ttk.Button(self, text='Select Files', command=self.on_go_pressed).grid(column=0, row=0)
ttk.Button(self, text='Generate PDF').grid(column=0, row=1)
for widget in self.winfo_children():
widget.grid(padx=0, pady=3)
def on_go_pressed(self):
select_files(self.product_type.get()) ### EDITED THIS LINE
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title("PDF n-up")
self.eval('tk::PlaceWindow . center')
self.geometry('400x200')
self.resizable(0, 0)
# self.attributes('-toolwindow', True)
# layout on the root window
self.columnconfigure(0, weight=4)
self.columnconfigure(1, weight=1)
self.__create_widgets()
def __create_widgets(self):
# create the input frame
input_frame = InputFrame(self)
input_frame.grid(column=0, row=0)
# create the button frame
button_frame = ButtonFrame(self, input_frame.product_type) ### EDITED THIS LINE
button_frame.grid(column=1, row=0)
if __name__ == '__main__':
app = App()
app.mainloop()
Обратите внимание , как в строке button_frame = ButtonFrame(self, input_frame.product_type)
я даю его input_frame.product_type
в качестве аргумента, чтобы он мог получить к нему доступ в любое время, когда захочет.
Изменения ButtonFrame
, необходимые для этого: я изменил __init__()
метод, чтобы он мог получать другой аргумент. Затем он присваивает значение product_type
аргумента переменной, чтобы она могла использовать его позже. Когда он звонит select_files()
, он просто использует self.product_type
.
Относительно того, почему вызов select_files(InputFrame.product_type.get())
не работает: product_type
это переменная, которая создается только при InputFrame
инициализации. В приведенной выше строке вы ссылаетесь на сам класс, а не на экземпляр класса, поэтому он не был инициализирован. Следовательно, все, что создано в InputFrame.__init__()
, не определено, потому __init__()
что не было вызвано.
Комментарии:
1. Очень признателен!!