简体   繁体   中英

How can I change a global variable while using an event handler

I'm very new to python having some experience in C++ from my teenage years so please be gentle.

What I'm trying to do - left click adds a point (to a 2 dimensional array) and increments the pointsCount variable. I'm using Tkinter binding like so:

canvas.bind("<Button-1>", lambda event: leftClick(event,pointsCounter,points))

the left click function is defined like so:

def leftClick(event, numberOfPoints,pointsTable):
print("Left ", event.x ," ", event.y)
x = roundup(event.x, 50)
y = roundup(event.y, 50)
pointsTable.append([x,y])
numberOfPoints = numberOfPoints + 1
print(pointsTable)
print(numberOfPoints)

While the appending of points works fine the numberOfPoints is only incremented after the first click. I understand that Python only passes a value to the function so I can't change it. However it works for the array. Is there any way I can increment the numberOfPoints when I right click.

Here's the entire code

import array
import math
from tkinter import Canvas


def roundup(x, n=10):
    res = math.ceil(x/n)*n
    if (x%n < n/2)and (x%n>0):
        res-=n
    return res

def middleClick(event):
    print("Middle ", event.x ," ", event.y)

def rightClick(event):
    print("Right ", event.x ," ", event.y)
def leftClick(event, numberOfPoints,pointsTable):
    print("Left ", event.x ," ", event.y)
    x = roundup(event.x, 50)
    y = roundup(event.y, 50)
    pointsTable.append([x,y])
    numberOfPoints = numberOfPoints + 1
    print(pointsTable)
    print(numberOfPoints)
    for i in range(1, 5):
        canvas.create_oval(pointsTable[i][0] - radius, pointsTable[i][1] - radius, pointsTable[i][0] + radius, pointsTable[i][1] + radius, fill="red")
    return numberOfPoints

root = Tk()
canvas = Canvas(root, width = 800, height = 800)

radius = 5
points = [[]]
pointsCounter = 1



canvas.bind("<Button-1>", lambda event: leftClick(event,pointsCounter,points))
canvas.bind("<Button-2>",middleClick)
canvas.bind("<Button-3>",rightClick)





canvas.pack()


root.mainloop()```


I'd be really grateful for some pointers. 


The difference between pointsCount and pointsTable as function parameters is that pointsCount is immutable, the variable is assigned to a new object once it is changed. pointsTable is mutable, the object itself is amended when it is changed. That is when the pointsTable is amended in the function the change is reflected in the original variable. For pointsCount a new object with a value of pointsCount + 1 is created and pointCount inside the function now points to it. pointsCount outside the function still points to a zero object.

One solution is to make pointsCount a global variable, leftClick below. The other is not to store pointsCount at all and rely on the length of pointsTable, leftClick1 below.

from random import randint

pointsTable = []
numberOfPoints = 0

class Event:  # Mock up to test code.
    def __init__(self):
        self.x = randint(0,50)
        self.y = randint(0,50)

# Keeping external counter
def leftClick(event, pointsTable):
    global numberOfPoints
    print("Left ", event.x ," ", event.y)
    x = event.x
    y = event.y
    pointsTable.append([x,y])
    numberOfPoints = numberOfPoints + 1
    print(pointsTable)
    print(numberOfPoints)

def number_of_points(): 
# This may be overkill len(pointsTable) could be used instead
    return len(pointsTable)

# Using len(pointsTable)
def leftClick1(event, pointsTable):
    print("Left ", event.x ," ", event.y)
    x = event.x
    y = event.y
    pointsTable.append([x,y])
    print(pointsTable)
    print(number_of_points())

for _ in range(2):
    leftClick( Event(), pointsTable )

for _ in range(2):
    leftClick1( Event(), pointsTable )

""" Output 
Left  5   4
[[5, 4]]
1
Left  49   6
[[5, 4], [49, 6]]
2
Left  44   20
[[5, 4], [49, 6], [44, 20]]
3
Left  6   30
[[5, 4], [49, 6], [44, 20], [6, 30]]
4
"""

I'd choose to rely on the length of the pointsTable as simpler and more robust

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM