Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- '''
- December 23, 2019
- This is an example ( using Python 3.7 / tKinter on Win10 x64 ) application that allows scrolling a canvas and dragging boxes on a canvas.
- The canvas visible area is 300 x 300 px, but the scrollable area is 600 x 600 px.
- This program demonstrates obtaining the final canvas shape object position, and altering it as desired.
- The boxes snap to a grid that is 30px vertically and 100px horizontally.
- '''
- import tkinter as tk
- from tkinter import ttk
- from functools import partial
- root = tk.Tk()
- root.title( "Scroll/Drag Canvas Example 1.0" )
- window_width = 900
- window_height = 700
- root.minsize(window_width, window_height)
- window_position_x = 20
- window_position_y = 20
- root.geometry('%dx%d+%d+%d' % (window_width, window_height, window_position_x, window_position_y))
- root.resizable(True, True)
- window_test_color = '#%02x%02x%02x' % (160, 160, 160)
- root.config(bg=window_test_color)
- label_test_color = '#%02x%02x%02x' % (255, 180, 180)
- # @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- # Below is the scrolling functionality (working)
- canvas_test_color = '#%02x%02x%02x' % (100, 160, 100)
- canvas1 = tk.Canvas(master=root, width=300, height=300, scrollregion=(0,0,600,600), bg=canvas_test_color)
- canvas1.place(x=30, y=30)
- hbar1 = tk.Scrollbar(master=root,orient=tk.HORIZONTAL)
- hbar1.place(x=30, y=360, width=200, height=30)
- vbar1 = tk.Scrollbar(master=root,orient=tk.VERTICAL)
- vbar1.place(x=360, y=30, width=30, height=200)
- def function_hbar1_movement(event, *args):
- option1 = False
- if option1 == True:
- argList = []
- for x in args:
- argList.append(x)
- print (argList)
- canvas1.xview(event, *args)
- def function_vbar1_movement(event, *args):
- option2 = False
- if option2 == True:
- argList = []
- for x in args:
- argList.append(x)
- print (argList)
- canvas1.yview(event, *args)
- def function_hbar1_set(event, *args):
- option1 = False
- if option1 == True:
- argList = []
- for x in args:
- argList.append(x)
- print (argList)
- hbar1.set(event, *args)
- def function_vbar1_set(event, *args):
- option2 = False
- if option2 == True:
- argList = []
- for x in args:
- argList.append(x)
- print (argList)
- vbar1.set(event, *args)
- #hbar1.config(command=canvas1.xview)
- #vbar1.config(command=canvas1.yview)
- hbar1.config(command=function_hbar1_movement)
- vbar1.config(command=function_vbar1_movement)
- #canvas1.config(xscrollcommand=hbar1.set, yscrollcommand=vbar1.set)
- canvas1.config(xscrollcommand=function_hbar1_set, yscrollcommand=function_vbar1_set)
- # @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- def show_canvas_scroll_values(event):
- canvas = event.widget
- x = canvas.canvasx(event.x)
- y = canvas.canvasy(event.y)
- #print canvas.find_closest(x, y)
- canvas_hposition_label.config(text=x)
- canvas_vposition_label.config(text=y)
- #canvas1.bind('<Configure>', show_canvas_scroll_values)
- # @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- # This section is just four labels to read out the canvas scroll values
- # and the last-dragged-box actual xy values, on the 600x600 canvas area.
- xpos=430
- ypos=50
- vspacer425 = 30
- someLabel = tk.Label(master=root, text="canvas vertical scroll:")
- someLabel.place(x=xpos, y=ypos)
- xpos=570
- canvas_hposition_label = tk.Label(master=root, text="???", bg=label_test_color)
- canvas_hposition_label.place(x=xpos, y=ypos)
- xpos=430
- ypos=ypos + vspacer425
- someLabel = tk.Label(master=root, text="canvas horizontal scroll:")
- someLabel.place(x=xpos, y=ypos)
- xpos=570
- canvas_vposition_label = tk.Label(master=root, text="???", bg=label_test_color)
- canvas_vposition_label.place(x=xpos, y=ypos)
- xpos=430
- ypos=ypos + vspacer425 + vspacer425
- someLabel = tk.Label(master=root, text="box xpos:")
- someLabel.place(x=xpos, y=ypos)
- xpos=530
- box_xposition_label = tk.Label(master=root, text="???", bg=label_test_color)
- box_xposition_label.place(x=xpos, y=ypos)
- xpos=430
- ypos=ypos + vspacer425
- someLabel = tk.Label(master=root, text="box ypos:")
- someLabel.place(x=xpos, y=ypos)
- xpos=530
- box_yposition_label = tk.Label(master=root, text="???", bg=label_test_color)
- box_yposition_label.place(x=xpos, y=ypos)
- # @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- # this just draws the grid on the canvas.
- # canvas1 scroll region is 600 x 600
- def draw_test_lines_on_canvas():
- tcolor1 = '#%02x%02x%02x' % (0, 0, 0)
- vspacing = 30
- hspacing = 100
- loopcount = 0
- tValue = vspacing
- while loopcount < 20:
- canvas1.create_line(0, tValue, 600, tValue, fill=tcolor1)
- tValue += vspacing
- loopcount += 1
- loopcount = 0
- tValue = hspacing
- while loopcount < 7:
- canvas1.create_line(tValue, 0, tValue, 600, fill=tcolor1)
- tValue += hspacing
- loopcount += 1
- draw_test_lines_on_canvas()
- # @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- # Below is the code for putting the 3 boxes on the canvas, and dragging them.
- def canvas1_remember(event, *args):
- global canvas1_former_pos
- canvas1_former_pos = event.x, event.y
- #tList = ""
- #for n in args:
- # tList = tList + str(n) + ", "
- #print ("args = " + tList)
- #x = event.x # <--------------- this is just giving the direct (window) coords of the mouse-down.
- #y = event.y # <--------------- this is just giving the direct (window) coords of the mouse-down.
- #canvas = event.widget
- #x = canvas.canvasx(event.x) #<------------ This is giving the scrolled canvas xy coords of the mouse click.
- #y = canvas.canvasy(event.y) #<------------ This is giving the scrolled canvas xy coords of the mouse click.
- #print ("mouse-down:" + str(canvas.find_closest(x, y))) #<------ this is finding the closest tagged item.
- #print ("mouse-down:" + str(x) + ", " + str(y))
- canvas1.bind('<Button>', canvas1_remember)
- def on_mouse1_release(box, event):
- global stored_box
- global canvas1_former_pos
- #canvas1.move(stored_box, -10, -10)
- #stored_box.gettags()
- #itemInfo = canvas1.coords(stored_tags[0])
- print ("mouse released from box")
- stored_tags = canvas1.gettags(box)
- sItems = []
- for n in stored_tags:
- sItems.append(n)
- print ( "tag = " + str(sItems[0]))
- #print (stored_box)
- # Below is showing the ending drag position.
- itemInfo = canvas1.coords(stored_tags[0]) # <-------- this gets the tag itself
- #print (itemInfo[0]) # = x (string/float format)
- #print (itemInfo[1]) # = y
- #print (itemInfo[2]) # = x + width
- #print (itemInfo[3]) # = y + height
- print (str(itemInfo[0]) + "," + str(itemInfo[1]) + "," + str(itemInfo[2]) + "," + str(itemInfo[3]))
- # (Here is where the item's coordinates would be checked for legit settings)
- newxval = check_x_coordinate(str(itemInfo[0]))
- newyval = check_y_coordinate(str(itemInfo[1]))
- canvas1.move(sItems[0], newxval, newyval) # <------ this moves the whole item by tag name, the specified coordinates
- # Below is showing the ending position after 10,10 move.
- itemInfo = canvas1.coords(stored_tags[0]) # <-------- this gets the tag itself
- #print (itemInfo[0]) # = x (string/float format)
- #print (itemInfo[1]) # = y
- #print (itemInfo[2]) # = x + width
- #print (itemInfo[3]) # = y + height
- print (str(itemInfo[0]) + "," + str(itemInfo[1]) + "," + str(itemInfo[2]) + "," + str(itemInfo[3]))
- #new_x = canvas1_former_pos[0] = newxval
- #new_y = canvas1_former_pos[1] = newyval
- new_x = newxval
- new_y = newyval
- canvas1_former_pos = new_x, new_y
- def check_x_coordinate(xValue):
- num_xValue = float(xValue)
- if num_xValue <= 0:
- num_xValue = (num_xValue * -1) # This is checking for a negative x position, and returning it to zero if it exists.
- return num_xValue
- else:
- remainder = num_xValue % 100
- return (remainder * -1)
- def check_y_coordinate(yValue):
- num_yValue = float(yValue)
- if num_yValue <= 0:
- num_yValue = (num_yValue * -1) # This is checking for a negative y position, and returning it to zero if it exists.
- return num_yValue
- else:
- remainder = num_yValue % 30
- return (remainder * -1)
- stored_box = "" # <------- this stores the item ID number, which is just a string of an int value.
- stored_tags = [] # <------ this stores the item tag that you assigned, as item[0]
- def ondrag(box, event):
- global stored_box
- global canvas1_former_pos
- #global stored_tags
- stored_box = box
- canvas1.tag_raise(box)
- #print ("box = " + str(box)) # <--------- this is showing the ID number
- #stored_tags = canvas1.gettags(box)
- #sItems = ""
- #for n in stored_tags:
- # sItems = sItems + n + ", "
- #print ("tag = " + sItems) # <----------- this returns the single tag, and the string "current"
- canvas1.move(box, event.x-canvas1_former_pos[0], event.y-canvas1_former_pos[1]) # This line allows dragging the box in x and y.
- #canvas1.move(box, event.x-canvas1_former_pos[0], 0) # This line only allows dragging the box in the x dimension (left and right along whatever row it is already in).
- canvas1_remember(event)
- def add_box(x_pos, y_pos, color, thisTag):
- box = canvas1.create_rectangle(x_pos, y_pos, x_pos+dragBox_width, y_pos+dragBox_height, outline="black", fill=color, tags=(thisTag))
- canvas1.tag_bind(box, '<B1-Motion>', partial(ondrag, box))
- canvas1.tag_bind(box, '<ButtonRelease-1>', partial(on_mouse1_release, box)) # <ButtonRelease-1>
- '''
- https://stackoverflow.com/questions/2679418/how-to-get-the-coordinates-of-an-object-in-a-tkinter-canvas
- Note about above: whenever you create an item on a canvas, the canvas returns the item ID number.
- So that just needs to be kept with each shift object, and then you have a way to query all the block positions
- and correct them if they don't fall on the snap-to grid spacing.
- '''
- canvas1_former_pos = 0,0
- dragBox_width = 80
- dragBox_height = 20
- add_box(80, 100, 'red', 'shiftbox1')
- add_box(80, 200, 'green', 'shiftbox2')
- add_box(200, 200, 'blue', 'shiftbox3')
- # @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment