3

I am attempting to create a layout using Tkinter for Python3 that involves several buttons and scales. The buttons work fine, but the command that I give to the scale widget is called when I call grid on the scale. Why is this happening and what can I do to stop it?

Here is a simplified version of my code:

import tkinter
import time

WINDOW_HEIGHT = 150
WINDOW_WIDTH = 340

class Player(object):
    def __init__(self):
        self.window = tkinter.Tk()
        self.window.geometry(str(WINDOW_WIDTH) + 'x' + str(WINDOW_HEIGHT))
        self.current_time = tkinter.DoubleVar()

        self.progress_bar = tkinter.Scale(self.window,
                variable = self.current_time,
                command = self.set_current_time,
                orient = tkinter.HORIZONTAL,
                showvalue = 0, resolution=.001)

        self.progress_bar.grid(row=1, column=10)

    def set_current_time(self, time):
        print('setting current time')
        print(time)

    def update(self):
        self.window.update_idletasks()
        self.window.update()

def main():
    media_player = Player()
    while True:
        media_player.update()
        time.sleep(.1)

if __name__ == "__main__":
    main()

The set_current_time function should only be called when the slider is actually clicked and moved, however as soon as grid is executed, set_current_time is called with a time value of 0. How can I place the slider without executing the command? After placement the slider works as expected, but I would like to avoid the initial calling of the set_current_time function.

stovfl
  • 14,998
  • 7
  • 24
  • 51
DMAR
  • 200
  • 1
  • 1
  • 7
  • You can always work around that by making it not set the time when time=0. –  Dec 20 '18 at 01:08
  • Yeah that works as a hack I guess. It doesn't always come in as 0 however, (I often regrid the slider when the app changes so this happens many times during the app lifecycle), but comes in as 100, or a few other values sometimes. I'd rather not have to keep a list of these arbitrary times to not set as. Additionally then in the off chance that someone actually is trying to set it to that time it wouldn't work. Ideally the command should not be fired on grid at all. – DMAR Dec 20 '18 at 01:23
  • Hm, I see your point. I was just imagining that 0 wouldn't be a very useful time to set anyway. –  Dec 20 '18 at 01:46
  • 1
    The `set_current_time()` is called only when the slider bar is moved in my Windows with Python 3.7.1. But the same issue as yours happens when using Python 2.7. So your issue may depends on platform and Python version. – acw1668 Dec 20 '18 at 01:53
  • Currently on a mac. I've tried with 2.7.15, Python 3.6.5, and Python 3.7.1 and I'm seeing the effects on all of them. – DMAR Dec 20 '18 at 02:15
  • 1
    It's **not** a `grid` issue. The `command=...` is called at init `class Scale`, it behave as it should. You have 3 options: **1.**: Don't instantiate with `command=`. **2.**: Instantiate with a valid value. **3.**: Do `.configure(command=..` later. – stovfl Dec 20 '18 at 08:54
  • @stovfl: Why it **should** behave like that? The callback should be called when the slider is **moved**. It's very annoying. I want to send the data via serial interface towards the microcontroller when the slider is moved but the callback is executed when program starts. You mean `.config`, not `.configure`? – Chupo_cro Jul 31 '20 at 23:48
  • ***the callback is executed when program starts.***: Verified your example and can't reproduce, on *Linux*, your issue. It's known that `Tkinter` behave different on *MACOS*. – stovfl Aug 01 '20 at 07:02
  • ***You mean `.config`, not `.configure`?***: It's the same, you can use both as well ... – stovfl Aug 01 '20 at 07:05
  • ***what can I do to stop it?***: Set a `flag` in your callback to skip the first **callback**. – stovfl Aug 01 '20 at 07:07

0 Answers0