Можно ли динамически изменять значение » до » шкалы с помощью tkinter?

#python #tkinter

Вопрос:

Интересно, можно ли динамически изменять максимальное значение шкалы с помощью другой шкалы с помощью tkinter.

У меня есть пример с двумя шкалами, где первая шкала sc_maxVal имеет переменную maxVal , которая является максимальным значением второй шкалы.

Я могу установить его в первую очередь, но я не знаю, как изменить to аргумент sc_var во время выполнения сценария sc_max .

 import tkinter as tk
    
mainApp = tk.Tk()
   
mainApp.title("Windows")
mainApp.geometry("800x600")
    
maxVal = tk.DoubleVar()
maxVal.set(20)
    
var = tk.DoubleVar()
var.set(int(maxVal.get()/2))
    
sc_max = tk.Scale(mainApp, label= 'maxVal', from_= 10, to= 40, orient= tk.HORIZONTAL, length= 500, variable= maxVal).pack()
sc_var = tk.Scale(mainApp, label= 'var', from_= 1, to= int(maxVal.get()), orient= tk.HORIZONTAL, length= 500, variable= var).pack()
    
mainApp.mainloop()
 

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

1. Допустимо ли просто использовать математику для преобразования значения, которое вы читаете из «динамической» шкалы, в значение, которое вы хотите получить в контексте?

2. @KarlKnechtel Я боюсь, что это невозможно в моем контексте, проблема на самом деле в том, как изменить значение после того, как я его установил

3. На самом деле не совсем ясно, в чем проблема. Вы можете изменить практически любой атрибут любого виджета в любое время. Вы знакомы с configure этим методом? Знаете ли вы, что вы можете вызывать функцию всякий раз, когда значение меняется?

4. @GazzokS Вам, вероятно, следует опубликовать ответ на свой вопрос. Это имеет немного больше смысла, чем помещать ответ в вопрос, и это позволит другим пользователям узнать, что на вопрос был дан удовлетворительный ответ, без необходимости читать весь вопрос.

5. Хорошая идея, просто сделал это

Ответ №1:

Вы можете настроить масштаб для вызова функции при изменении ее значения. В этой функции вы можете использовать configure метод для настройки другого масштаба.

Вы также допускаете очень распространенную ошибку, вызывая pack ту же инструкцию, что и при создании виджета. Вам нужно разделить их, иначе переменная, которой вы назначаете, будет иметь значение с None момента .pack(...) возврата None .

примечание: command новое значение передается в качестве аргумента.

 def update_scale(new_max):
    sc_var.configure(to=new_max)

sc_var = tk.Scale(...)
sc_max = tk.Scale(..., command=update_scale)

sc_var.pack()
sc_max.pack()
 

Ответ №2:

Возможно, вы захотите создать цикл while и обновить mainApp его во время. Затем вы можете изменять атрибуты виджетов во время работы приложения, не требуя, чтобы оно было вызвано событием или чем-то еще. Например, используйте:

 while True:
    try:
        mainApp.update()
        if you_want_to_change_the_to_value:
            sc_var.config(to=your_value)
    except tkinter.TclError:
        break
 

на месте

 mainApp.mainloop()
 

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

1. Я пытался, и у меня была проблема, что sc_var не был типом, но я понял, что sc_var.pack() должен быть в цикле, а не до него. Теперь это работает. Так что большое вам спасибо за вашу помощь !

Ответ №3:

Я нашел решение с помощью Сильвестра Круина.

Основной цикл должен быть заменен чем-то подобным

 while True:
    mainApp.update()
    if you_want_to_change_the_to_value:
        sc_var.config(to=your_value)
 

Я также понял, что мы должны поместить sc_var.pack() в цикл.
Это дает нам сценарий

 import tkinter as tk

mainApp = tk.Tk()


mainApp.title("Windows")
mainApp.geometry("800x600")


maxVal = tk.DoubleVar()
maxVal.set(40)

changement = int(maxVal.get())

var = tk.DoubleVar()
var.set(int(maxVal.get()/2))


sc_max = tk.Scale(mainApp, label= 'maxVal', from_= 10, to= 40, orient= tk.HORIZONTAL, length= 500, variable= maxVal).pack()
sc_var = tk.Scale(mainApp, label= 'var', from_= 1, to= int(maxVal.get()), orient= tk.HORIZONTAL, length= 500, variable= var)



while True:
    sc_var.pack()
    mainApp.update()

    sc_var.config(to=int(maxVal.get()))
 

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

1. Вы не должны использовать root.update() в while True цикле. Вместо этого вам следует обратить внимание на отслеживание переменных tkinter. Попробуйте это: maxVal.trace("w", lambda *args: print(maxVal.get()))

2. @TheLizzard Что делает trace атрибут tkinter переменной? И как его следует использовать в приложении с циклом?