I want to create a slider with two sliding knobs using PySimpleGUI. I decide to use the graph element to create two circles (knob 1 and knob 2) by dragging them. The slider element in PySimpleGUI does not support two knobs.
I modified the code based on this demo. https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures.py
My problem is, how do I get the location of the circle? Can I read the location value of the drawn circle (the center of the circle) directly rather than the mouse location?
Thank you.
import PySimpleGUI as sg
layout = [[sg.Graph(
canvas_size=(400, 20),
graph_bottom_left=(0, 0),
graph_top_right=(800, 40),
key="-GRAPH-",
enable_events=True,
drag_submits=True,
motion_events=True,
right_click_menu=[[''],['Erase item','Send to back']]
)],
[sg.Text(key='-INFO-', size=(60, 1))]]
window = sg.Window("Drawing and Moving Stuff Around", layout, finalize=True)
# get the graph element for ease of use later
graph = window["-GRAPH-"]
knob1 = graph.draw_circle((20, 20), 20, fill_color='red')
knob2 = graph.draw_circle((50, 20), 20, fill_color='blue')
dragging = False
start_point = end_point = prior_rect = None
crosshair_lines = []
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break # exit
if event == "-GRAPH-": # if there's a "Graph" event, then it's a mouse
x, y = values["-GRAPH-"]
if not dragging:
start_point = (x)
dragging = True
drag_figures = graph.get_figures_at_location((x,y))
lastx = x
else:
end_point = (x)
delta_x = x - lastx
lastx = x
circle_loc = 0
if None not in (start_point, end_point):
if end_point <= 800 and end_point >= 0:
for fig in drag_figures:
graph.move_figure(fig, delta_x, 0)
graph.update()
window["-INFO-"].update(value=f"mouse {values['-GRAPH-']}")
elif event.endswith('+UP'): # The drawing has ended because mouse up
window["-INFO-"].update(value=f"grabbed rectangle from {start_point} to {end_point}")
start_point, end_point = None, None # enable grabbing a new rect
dragging = False
prior_rect = None
window.close()
There's no method provided in PySimpleGUI to get any attribute of the item you drawn on the graph, tkinter code is required to get what you want if you need something special.
def get_center(element, id_):
"""
Return the coordinate of center for the circle id_ in the element.
- args
- element: The Graph element.
- id_: id of the circle item drawn on Graph.
- Return
- (x0, y0): center of circle
"""
# bbox in tkinter
x1, y1, x2, y2 = element.widget.bbox(id_)
# bbox in PySimpleGUI
x3, y3 = element._convert_canvas_xy_to_xy(x1, y1)
x4, y4 = element._convert_canvas_xy_to_xy(x2, y2)
# Using operator '/' here to avoid calculation error
return (x3+x4)/2, (y3+y4)/2
You can use it like
drag_figures = graph.get_figures_at_location((x,y))
if drag_figures:
# index 0 for botton one and -1 for top one in the figure list
print(get_center(graph, drag_figures[-1]))