2019-12-18 19:31:43 +00:00
|
|
|
import PySimpleGUI as sg
|
2019-12-24 14:52:26 +00:00
|
|
|
from PIL import ImageGrab
|
2019-12-18 19:31:43 +00:00
|
|
|
|
|
|
|
"""
|
|
|
|
Demo - Drawing and moving demo
|
|
|
|
|
|
|
|
This demo shows how to use a Graph Element to (optionally) display an image and then use the
|
|
|
|
mouse to "drag" and draw rectangles and circles.
|
2021-02-03 20:48:59 +00:00
|
|
|
|
|
|
|
Copyright 2020 PySimpleGUI.org
|
2019-12-18 19:31:43 +00:00
|
|
|
"""
|
|
|
|
|
2019-12-24 16:33:06 +00:00
|
|
|
def save_element_as_file(element, filename):
|
|
|
|
"""
|
|
|
|
Saves any element as an image file. Element needs to have an underlyiong Widget available (almost if not all of them do)
|
|
|
|
:param element: The element to save
|
|
|
|
:param filename: The filename to save to. The extension of the filename determines the format (jpg, png, gif, ?)
|
|
|
|
"""
|
|
|
|
widget = element.Widget
|
|
|
|
box = (widget.winfo_rootx(), widget.winfo_rooty(), widget.winfo_rootx() + widget.winfo_width(), widget.winfo_rooty() + widget.winfo_height())
|
|
|
|
grab = ImageGrab.grab(bbox=box)
|
|
|
|
grab.save(filename)
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-12-18 19:31:43 +00:00
|
|
|
def main():
|
|
|
|
|
2019-12-24 16:33:06 +00:00
|
|
|
sg.theme('Dark Blue 3')
|
2019-12-18 19:31:43 +00:00
|
|
|
|
2019-12-19 16:00:17 +00:00
|
|
|
col = [[sg.T('Choose what clicking a figure does', enable_events=True)],
|
|
|
|
[sg.R('Draw Rectangles', 1, key='-RECT-', enable_events=True)],
|
|
|
|
[sg.R('Draw Circle', 1, key='-CIRCLE-', enable_events=True)],
|
|
|
|
[sg.R('Draw Line', 1, key='-LINE-', enable_events=True)],
|
2020-05-07 10:22:59 +00:00
|
|
|
[sg.R('Draw points', 1, key='-POINT-', enable_events=True)],
|
2019-12-19 16:00:17 +00:00
|
|
|
[sg.R('Erase item', 1, key='-ERASE-', enable_events=True)],
|
|
|
|
[sg.R('Erase all', 1, key='-CLEAR-', enable_events=True)],
|
|
|
|
[sg.R('Send to back', 1, key='-BACK-', enable_events=True)],
|
|
|
|
[sg.R('Bring to front', 1, key='-FRONT-', enable_events=True)],
|
|
|
|
[sg.R('Move Everything', 1, key='-MOVEALL-', enable_events=True)],
|
2021-02-03 20:48:59 +00:00
|
|
|
[sg.R('Move Stuff', 1, key='-MOVE-', enable_events=True)],
|
2019-12-24 14:52:26 +00:00
|
|
|
[sg.B('Save Image', key='-SAVE-')],
|
2019-12-18 19:31:43 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
layout = [[sg.Graph(
|
2020-05-07 10:22:59 +00:00
|
|
|
canvas_size=(400, 400),
|
|
|
|
graph_bottom_left=(0, 0),
|
|
|
|
graph_top_right=(800, 800),
|
|
|
|
key="-GRAPH-",
|
|
|
|
enable_events=True,
|
|
|
|
background_color='lightblue',
|
2021-02-04 18:33:13 +00:00
|
|
|
drag_submits=True,
|
|
|
|
right_click_menu=[[],['Erase item',]]
|
|
|
|
), sg.Col(col, key='-COL-') ],
|
2021-02-03 20:48:59 +00:00
|
|
|
[sg.Text(key='-INFO-', size=(60, 1))]]
|
2019-12-18 19:31:43 +00:00
|
|
|
|
2019-12-19 03:43:45 +00:00
|
|
|
window = sg.Window("Drawing and Moving Stuff Around", layout, finalize=True)
|
2019-12-18 19:31:43 +00:00
|
|
|
|
|
|
|
# get the graph element for ease of use later
|
|
|
|
graph = window["-GRAPH-"] # type: sg.Graph
|
|
|
|
graph.draw_image(data=logo200, location=(0,400))
|
|
|
|
|
|
|
|
dragging = False
|
|
|
|
start_point = end_point = prior_rect = None
|
2021-02-04 18:33:13 +00:00
|
|
|
# graph.bind('<Button-3>', '+RIGHT+')
|
2021-02-03 20:48:59 +00:00
|
|
|
|
2019-12-18 19:31:43 +00:00
|
|
|
while True:
|
|
|
|
event, values = window.read()
|
2020-05-07 10:22:59 +00:00
|
|
|
print(event, values)
|
|
|
|
if event == sg.WIN_CLOSED:
|
2019-12-18 19:31:43 +00:00
|
|
|
break # exit
|
2021-02-03 20:48:59 +00:00
|
|
|
|
2019-12-19 16:00:17 +00:00
|
|
|
if event in ('-MOVE-', '-MOVEALL-'):
|
2021-02-03 20:48:59 +00:00
|
|
|
graph.set_cursor(cursor='fleur') # not yet released method... coming soon!
|
2019-12-19 16:00:17 +00:00
|
|
|
elif not event.startswith('-GRAPH-'):
|
2021-02-03 20:48:59 +00:00
|
|
|
graph.set_cursor(cursor='left_ptr') # not yet released method... coming soon!
|
2019-12-19 16:00:17 +00:00
|
|
|
|
2019-12-18 19:31:43 +00:00
|
|
|
if event == "-GRAPH-": # if there's a "Graph" event, then it's a mouse
|
|
|
|
x, y = values["-GRAPH-"]
|
|
|
|
if not dragging:
|
|
|
|
start_point = (x, y)
|
|
|
|
dragging = True
|
|
|
|
drag_figures = graph.get_figures_at_location((x,y))
|
|
|
|
lastxy = x, y
|
|
|
|
else:
|
|
|
|
end_point = (x, y)
|
|
|
|
if prior_rect:
|
|
|
|
graph.delete_figure(prior_rect)
|
2019-12-19 03:43:45 +00:00
|
|
|
delta_x, delta_y = x - lastxy[0], y - lastxy[1]
|
2019-12-18 19:31:43 +00:00
|
|
|
lastxy = x,y
|
|
|
|
if None not in (start_point, end_point):
|
|
|
|
if values['-MOVE-']:
|
|
|
|
for fig in drag_figures:
|
|
|
|
graph.move_figure(fig, delta_x, delta_y)
|
|
|
|
graph.update()
|
|
|
|
elif values['-RECT-']:
|
|
|
|
prior_rect = graph.draw_rectangle(start_point, end_point,fill_color='green', line_color='red')
|
|
|
|
elif values['-CIRCLE-']:
|
|
|
|
prior_rect = graph.draw_circle(start_point, end_point[0]-start_point[0], fill_color='red', line_color='green')
|
2019-12-19 03:43:45 +00:00
|
|
|
elif values['-LINE-']:
|
|
|
|
prior_rect = graph.draw_line(start_point, end_point, width=4)
|
|
|
|
elif values['-POINT-']:
|
2020-05-07 10:22:59 +00:00
|
|
|
graph.draw_point((x,y), size=8)
|
2019-12-19 03:43:45 +00:00
|
|
|
elif values['-ERASE-']:
|
|
|
|
for figure in drag_figures:
|
|
|
|
graph.delete_figure(figure)
|
|
|
|
elif values['-CLEAR-']:
|
|
|
|
graph.erase()
|
|
|
|
elif values['-MOVEALL-']:
|
|
|
|
graph.move(delta_x, delta_y)
|
2019-12-19 16:00:17 +00:00
|
|
|
elif values['-FRONT-']:
|
|
|
|
for fig in drag_figures:
|
|
|
|
graph.bring_figure_to_front(fig)
|
|
|
|
elif values['-BACK-']:
|
|
|
|
for fig in drag_figures:
|
|
|
|
graph.send_figure_to_back(fig)
|
2021-02-03 20:48:59 +00:00
|
|
|
window["-INFO-"].update(value=f"mouse {values['-GRAPH-']}")
|
2019-12-18 19:31:43 +00:00
|
|
|
elif event.endswith('+UP'): # The drawing has ended because mouse up
|
2021-02-03 20:48:59 +00:00
|
|
|
window["-INFO-"].update(value=f"grabbed rectangle from {start_point} to {end_point}")
|
2019-12-18 19:31:43 +00:00
|
|
|
start_point, end_point = None, None # enable grabbing a new rect
|
|
|
|
dragging = False
|
|
|
|
prior_rect = None
|
2021-02-03 20:48:59 +00:00
|
|
|
elif event.endswith('+RIGHT+'): # Righ click
|
|
|
|
window["-INFO-"].update(value=f"Right clicked location {values['-GRAPH-']}")
|
2021-02-04 18:33:13 +00:00
|
|
|
elif event.endswith('+MOTION+'): # Righ click
|
|
|
|
window["-INFO-"].update(value=f"mouse freely moving {values['-GRAPH-']}")
|
2019-12-24 14:52:26 +00:00
|
|
|
elif event == '-SAVE-':
|
2019-12-24 16:33:06 +00:00
|
|
|
# filename = sg.popup_get_file('Choose file (PNG, JPG, GIF) to save to', save_as=True)
|
|
|
|
filename=r'test.jpg'
|
|
|
|
save_element_as_file(window['-GRAPH-'], filename)
|
2021-02-04 18:33:13 +00:00
|
|
|
elif event == 'Erase item':
|
|
|
|
window["-INFO-"].update(value=f"Right click erase at {values['-GRAPH-']}")
|
|
|
|
if values['-GRAPH-'] != (None, None):
|
|
|
|
drag_figures = graph.get_figures_at_location(values['-GRAPH-'])
|
|
|
|
for figure in drag_figures:
|
|
|
|
graph.delete_figure(figure)
|
2019-12-24 16:33:06 +00:00
|
|
|
|
2019-12-18 19:31:43 +00:00
|
|
|
window.close()
|
|
|
|
|
|
|
|
logo200 = b'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
|
|
|
|
|
|
|
|
main()
|