I have a slider and spinbox connected to the same DoubleVar p1. I'm trying to draw an arc that changes position on the canvas as p1 changes.
I tried to draw the arc with arc = myCanvas.create_arc using p1.get() in the parameters, but the arc only draws with p1's initial value of 0, and does not update as the value changes.
Here is an example
import tkinter as tk
from tkinter import ttk
import math
root = tk.Tk()
root.title('Lens')
root.configure(background='#ececec')
root.resizable(False, False)
h = 600
w = 800
myCanvas = tk.Canvas(root, bg="#ececec", height=h, width=w, highlightthickness=0)
y = h/2
x = w/3
r=200
p1 = tk.DoubleVar()
slider1= ttk.Scale(
root,
from_=0,
to=w/2,
orient='horizontal',
variable=p1
)
slider1.pack(ipadx=50, padx=0, anchor=tk.NW, side=tk.LEFT)
spin1 = ttk.Spinbox(
root,
textvariable=p1,
wrap=True,
width=5,
from_=0,
to=w/2,
increment=.01
)
spin1.pack(anchor=tk.NW, side=tk.LEFT)
x1=p1.get()
# lens shape
arc11 = myCanvas.create_arc(x1-1/8*r, y r*math.sqrt(7)/4, x1 7/8*r, y-r*math.sqrt(7)/4, start=90 180/math.pi*math.atan(3/math.sqrt(7)), extent=2*180/math.pi*math.atan(math.sqrt(7)/3), style=tk.ARC)
arc12 = myCanvas.create_arc(x1-7/8*r, y r*math.sqrt(7)/4, x1 1/8*r, y-r*math.sqrt(7)/4, start=90-180/math.pi*math.atan(3/math.sqrt(7)), extent=-2*180/math.pi*math.atan(math.sqrt(7)/3), style=tk.ARC)
myCanvas.pack()
root.mainloop()
CodePudding user response:
You have to explicitly reconfigure the arcs. They won't update just because you update a variable used when initially drawing them.
You can tie a function to the slider, and in that function you can recompute the coordinates and attributes of the arc.
First, create a function to update the coordinates. To keep the example simple I'm just recomputing the data for one arc. Tkinter will pass in the new value, though it will pass it in as a string so it needs to be converted to a float.
def redraw_arcs(*args):
try:
x1 = p1.get()
coords = (x1-7/8*r, y r*math.sqrt(7)/4, x1 1/8*r, y-r*math.sqrt(7)/4)
myCanvas.coords(arc12, *coords)
except:
pass
The try
is there, otherwise you'll get an error if the user deletes the data in the spinbox, resulting in an empty string.
Next, put a trace on the variable to call the function when the value changes.
p1.trace_add("write", redraw_arcs)
If you're unfamiliar with how a trace function is called, see What are the arguments to Tkinter variable trace method callbacks?
p1.trace_add("write", redraw_arcs)
If you want to recompute the other attributes such as extent
and start
, you can use itemconfigure
to change those attributes in the function.
CodePudding user response:
You need to update the coordinates of the two arcs whenever the variable p1
is changed by using p1.trace_add()
:
...
def move_arcs(*args):
x1 = p1.get()
myCanvas.coords(arc11, x1-1/8*r, y r*math.sqrt(7)/4, x1 7/8*r, y-r*math.sqrt(7)/4)
myCanvas.coords(arc12, x1-7/8*r, y r*math.sqrt(7)/4, x1 1/8*r, y-r*math.sqrt(7)/4)
p1.trace_add("write", move_arcs)
root.mainloop()