There is an image button, when clicked, the self.ANX (True / False) state and the image on the button itself change (for the True state, one, for False, another).

Which of these options is better suited for my task and what are the differences in their work?

The first option with self.button and self.methodom for the button:

 def create_frames(self): sidebar_frame = tk.Frame(self) ... # Кнопка: ANX (on/off) self.ANX = False ANXon_button_image = tk.PhotoImage(file='./img/sidebar/ANX_on.png') ANXoff_button_image = tk.PhotoImage(file='./img/sidebar/ANX_off.png') self.ANX_button = tk.Button(sidebar_frame, image=ANXoff_button_image, bd=0, command=self.ANX_button_clicked) self.ANX_button.onimg = ANXon_button_image self.ANX_button.offimg = ANXoff_button_image self.ANX_button.place(width=137, height=31, x=17, y=13) def ANX_button_clicked(self): if self.ANX is False: self.ANX = True self.ANX_button['image'] = self.ANX_button.onimg else: self.ANX = False self.ANX_button['image'] = self.ANX_button.offimg 

The second option is with the button (without self) and the usual function inside the method:

 def create_frames(self): sidebar_frame = tk.Frame(self) ... # Кнопка: ANX (on/off) self.ANX = False def ANX_button_clicked(): if self.ANX is False: self.ANX = True ANX_button['image'] = ANX_button.onimg else: self.ANX = False ANX_button['image'] = ANX_button.offimg ANXon_button_image = tk.PhotoImage(file='./img/sidebar/ANX_on.png') ANXoff_button_image = tk.PhotoImage(file='./img/sidebar/ANX_off.png') ANX_button = tk.Button(sidebar_frame, image=ANXoff_button_image, bd=0, command=ANX_button_clicked) ANX_button.onimg = ANXon_button_image ANX_button.offimg = ANXoff_button_image ANX_button.place(width=137, height=31, x=17, y=13) 

Tried to use tkinter.Checkbutton , but this method does not work as it should.

  • if you are sure that both code examples work and answers that suggest any improvements are acceptable, then add a code-review tag (read its description to be sure that the question meets the requirements) ¶ If you are not sure that the code works, then the question is better set in the form: "How to implement the on / off button with pictures in tkinter". - jfs
  • @jfs Added a label, thanks, did not know about it. Do I need to supplement the code for this label with all the necessary details ( import , class , etc) so that the code can be immediately run? Because the code is working here, but the details have been omitted so that the excess does not have to be read. - Trajectory
  • The code-review task is for the author to learn something. Lack of context (... in code) or an artificial example can hide real problems in the code. Read more: Why is the hypothetical code example for Code Review? - jfs

1 answer 1

The function inside the method is called closure . I do not think that its use is justified in a particular case. My version is:

 import tkinter as tk class WIND(tk.Tk): def __init__(self): super().__init__() self.ANX = False # поместив все фото в словарь, ключами которого будут значения self.ANX, # можно избавится от проверок if self.ANX is..., особенно для более чем двух состояний(True/False) self.ANX_photo = {True: tk.PhotoImage(file='1.png'), False: tk.PhotoImage(file='2.png')} self.button = tk.Button(self, command=self.button_cmd) # можно определить self.ANX = tk.BooleanVar() и задать в checkbutton(variable=tk.BooleanVar) # тогда чекбокс автоматически бы изменял состояние self.ANX, но при этом в self.set_ANX выполнять self.ANX = not self.ANX не надо self.checkbutton = tk.Checkbutton(self, command=self.set_ANX) self.button.pack() self.checkbutton.pack() self.set_ANX() def set_ANX(self, *args): # должно меняться состояние self.ANX self.ANX = not self.ANX # состояние self.button self.button.config(image=self.ANX_photo[self.ANX], # можно избавится от проверок if self.ANX is... state='normal' if self.ANX else 'disabled') def button_cmd(self): '''кнопка может изменять состояние self.ANX и выполнить дополнительную работу, если бы set_ANX было замыканием, то сослатся на нее отсюда, стало бы невозможно''' self.set_ANX() print(self.ANX) WIND().mainloop()