Можете ли вы вызвать функцию из tk.Командный параметр OptionMenu без передачи аргумента

#python #tkinter

#python #tkinter

Вопрос:

Я хочу проверить, изменил ли пользователь какие-либо значения в виджетах tkinter, а затем предложить сохранить эти значения или потерять изменения.

У многих приложений есть 3 кнопки в правом нижнем углу их рамки настроек OK , Cancel , и Apply где Apply отключено, пока не будет внесено изменение. Я имитирую эту функцию в своей программе.

Когда я использую tk.OptionMenu(command=function) , по умолчанию он отправляет текущий пользовательский выбор в функцию, однако мне не нужно знать текущий выбор, потому что независимо от того, что это такое, я хочу предложить пользователю сохранить настройки.

Запуск программы приведет к следующей ошибке:

Ошибка типа: функция() принимает 0 позиционных аргументов, но был задан 1

Простым обходным решением, о котором я подумал, было бы присвоить произвольному параметру значение function() like so:

 def function(param=None):
    value_change.status = True
 

Смотрите Пример кода для value_change.status использования.

Однако PyCharm указывает, что param это не используется, и помечает его как слабое предупреждение. Я не могу использовать переданное значение, поэтому я ничего не могу сделать, param кроме как игнорировать его и предупреждение PyCharm. Технически здесь нет ничего плохого, но мне нравится видеть эту зеленую галочку в правом верхнем углу экрана, поэтому я придумал другое обходное решение:

 def function(param=None):
    value_change.status = True if param else False
 

Оба param=None и if param else False являются избыточными, поскольку они являются только заполнителями, чтобы код выполнялся плавно и не выдавал никаких предупреждений.

Другая проблема возникает, когда я хочу использовать function() для других команд виджета, которые не передают аргументы, такие как tk.Checkbutton(command=function) и я должен изменить свой код на следующие строки, что делает код еще более избыточным, чем раньше.

 def function(param=True):
    value_change.status = True if param else False
 

Есть ли способ не передавать аргумент через tk.OptionMenu(command=function) ?

Пример кода

 import time
import tkinter as tk
from threading import Thread

def value_change():
    value_change.count = 0
    value_change.status = False

    print('Has the user changed settings in the past 3 seconds?')

    while value_change.status != 'exit':
        if value_change.status:
            value_change.count  = 1
            
            # Reset count if no change after 3 seconds
            if value_change.count > 3:
                value_change.count = 0
                value_change.status = False

        print(value_change.status)
        time.sleep(1)

def function(param=True):
    value_change.status = True if param else False
    value_change.count = 0


gui = tk.Tk()
gui.geometry('100x100')

"""Setup OptionMenu"""
menu_options = ['var1', 'var2', 'var3']

menu_string = tk.StringVar()
menu_string.set(menu_options[0])

option_menu = tk.OptionMenu(gui, menu_string, *menu_options, command=function)
option_menu.pack()

"""Setup CheckButton"""
check_int = tk.IntVar()

check = tk.Checkbutton(gui, variable=check_int, command=function)
check.pack()

"""Turn On Thread and Run Program"""
Thread(target=value_change).start()
gui.mainloop()

"""Signal Threaded Function to Exit"""
value_change.status = 'exit'
 

Приведенный выше пример представляет собой минимальное воспроизведение, я не включил OK Cancel Apply кнопки и их функции, поскольку они не нужны и только сделают код длинным.

Ответ №1:

Вы можете использовать lambda :

 option_menu = tk.OptionMenu(gui, menu_string, *menu_options, command=lambda v: function())
 

Комментарии:

1. Идеально! Большое спасибо