2
\$\begingroup\$

I'm trying to devise a tkinter gui, that, among others, lets users choose a 'working folder' and a 'destination folder (and there is more coming). I stripped the code to its bare functionality hereunder.

I found myself duplicating code for the selection of both the 'working folder' and the 'destination' folder. I came up with the solution to put these variables in a dictionary (I could pass them as mutable objects along with the lambda). Although it is a working solution, I have the feeling there is more standard way of achieving this objective.

My question therefore is: how can I make my_browsefile() function work whilst changing the value ofself.working_dir andself.destination_dir, without using an artificial dictionary structure, hence avoiding duplicate code? This would implicate that I can generalize the_browsefile func somehow.

I have seen very advanced reusage features in text books, but currently this is out of my league. If I can learn to tackle this 'easy' one, it would possibly help me on my journey.

Thank you for giving me advice in doing it the Pythonic way...

import tkinter as tkfrom tkinter import filedialogclass View():    def __init__(self, parent):        self.parent = parent                self.gui_variables = {'working dir': '',                              'destination dir': ''}                self.menu()        def menu(self):        self.folder_button1 = tk.Button(self.parent, text="Choose Working Folder",                                       command=lambda: self._browsefile(self.gui_variables['working dir']))        self.folder_button1.pack()        self.folder_button2 = tk.Button(self.parent, text="Choose Dest. Folder",                                       command=lambda: self._browsefile(self.gui_variables['destination dir']))        self.folder_button2.pack()    def _browsefile(self, directory):        answer = tk.filedialog.askdirectory()        self.gui_variables[directory] = answerif __name__ == '__main__':    root = tk.Tk()    View(root)    root.mainloop()
Reinderien's user avatar
Reinderien
71.2k5 gold badges76 silver badges257 bronze badges
askedJan 28, 2021 at 22:01
grrfield's user avatar
\$\endgroup\$

1 Answer1

1
\$\begingroup\$

Don't use a dictionary. You can just refer to the attrs of a class by their name. Something like:

import tkinter as tkfrom tkinter import filedialogfrom typing import Optionalclass View:    def __init__(self, parent: tk.Tk):        self.parent = parent        self.working_dir: Optional[str] = None        self.dest_dir: Optional[str] = None        self.menu('Working', 'working_dir')        self.menu('Dest.', 'dest_dir')    def menu(self, title: str, attr: str):        def browse():            setattr(self, attr, tk.filedialog.askdirectory())        button = tk.Button(            self.parent,            text=f'Choose {title} Folder',            command=browse,        )        button.pack()if __name__ == '__main__':    root = tk.Tk()    View(root)    root.mainloop()

Notes:

  • Do not add a() suffix to your class
  • Do not assign those buttons as members on your class
  • Centralize the creation of the buttons and the associated command
  • For the command handler, use a simple closure
  • To target a specific member variable, accept a parameter that's used withsetattr
  • Use type hints
answeredJan 29, 2021 at 4:50
Reinderien's user avatar
\$\endgroup\$
3
  • \$\begingroup\$Thank you for reviewing my code and for the additional advice.\$\endgroup\$CommentedJan 29, 2021 at 10:40
  • \$\begingroup\$What's wrong with using() ?\$\endgroup\$CommentedFeb 1, 2021 at 22:36
  • 1
    \$\begingroup\$@CoolCloud it's a Python 2 construct, not needed these days\$\endgroup\$CommentedFeb 1, 2021 at 23:38

You mustlog in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.