Раньше я работал с этим способом кодирования, и он работал нормально, но после того, как я вернулся к нему через несколько недель, он больше не работает. Я упростил свой код, чтобы его было легко набирать здесь.
import tkinter as tk
from tkinter import ttk
class wind(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
# id shutter
self.SOURCE_SHUTTER = "/dev/ttyUSB0"
# menu deroulant
self.listeFlux = ["/dev/ttyUSB0", "/dev/ttyUSB1", "/dev/ttyUSB2", "/dev/ttyUSB3"]
self.listeCombo = ttk.Combobox(self, values=self.listeFlux)
self.listeCombo.current(0)
self.listeCombo.bind("<<ComboboxSelected>>", self.action)
self.listeCombo.pack(side = "top")
def action(self):
self.SOURCE_SHUTTER = self.listeCombo.get()
print(self.SOURCE_SHUTTER)
if __name__ == "__main__":
win = wind()
win.geometry("800x600")
win.mainloop()
Этот код дает мне ошибку: TypeError: action() принимает 1 позиционный аргумент, но было задано 2. Кто-нибудь знает, почему? Я видел, как люди делают эту ошибку, но их ошибка заключалась в том, что где-то в их коде отсутствовал параметр «я», и я не думаю, что забыл здесь.
Большое спасибо за вашу помощь. Валентин
Пробовал искать в другой теме, в которой была та же проблема, но здесь моя выглядит иначе.
Да, в конце концов это сработало с небольшими манипуляциями, но это совсем не удобно, решение с *args, приведенное ниже, работало лучше. В любом случае спасибо !
Быстрым и грязным решением было бы изменить определение action на:
def action(self, *args):
Основная проблема здесь заключается в том, что <<ComboboxSelected>>, кажется, возвращает кортеж, поэтому, когда событие запускается, и объект self, и кортеж передаются в функцию action, что вызывает ошибку.
Приведенное выше решение является «грязным исправлением», потому что оно позволяет функции принимать любое количество аргументов больше одного.
Это решение отлично работает, я понимаю, что вы подразумеваете под «грязным исправлением», но спасибо, оно помогло более чем хорошо.
Рад слышать, что это работает @Valentin. Если это решение, которое вы собираетесь использовать, отметьте его как принятый ответ.
Привязки событий в tkinter по своей сути передают параметр event связанной функции, поэтому вам нужно будет так или иначе с этим справиться.
Добавьте параметр _event в метод action.
Ведущее подчеркивание _ является соглашением, чтобы люди знали, что значение не используется функцией, а event — это обычное имя для аргумента события, используемого функциями, управляемыми событиями, в tkinter. Значение по умолчанию None не является строго обязательным, но это хорошая практика.
def action(self, _event=None):
self.SOURCE_SHUTTER = self.listeCombo.get()
print(self.SOURCE_SHUTTER)
Используйте *_args в определении вашего метода, чтобы он мог принимать любое количество аргументов (как предложено в ответе @3ddavies!). Опять же, _ является соглашением для неиспользуемых значений, а args является соглашением для этого типа параметра. Как уже упоминалось, предостережение здесь заключается в том, что теперь ваш метод action будет принимать любое количество аргументов — вряд ли это будет проблемой в данном конкретном случае, но имейте это в виду!
def action(self, *_args):
self.SOURCE_SHUTTER = self.listeCombo.get()
print(self.SOURCE_SHUTTER)
Используйте лямбду, чтобы поглотить событие и вызвать action как анонимную функцию.
def __init__(self):
... # code omitted for brevity
self.listeCombo.bind("<<ComboboxSelected>>", lambda event: self.action)
...
def action(self, _event = None):
self.SOURCE_SHUTTER = self.listeCombo.get()
print(self.SOURCE_SHUTTER)
Спасибо за этот полный ответ, теперь все становится яснее!
Помогают ли вообще ответы на этот вопрос?