简体   繁体   中英

Unable to bind tkinter slider properly to functions

I am trying to make a naive city generator. I have been successful at making the blocks of specified heights.

Also, I have been able to write a script that changes the height of a block using the slider.

Problem

  1. I am not able to do both things together. (I think I can solve this because the error is only about referencing before assignment)
  2. Using a horizontal slider, I want to increase the number of buildings (visualize as increasing the number of bars on the x-axis by reducing the width). But this code just does not work, I mean, it is not even raising errors.

Code so far

from tkinter import *
import random

bars = 5
margin = 30
heights= [5, 2, 1, 8, 4]
blocks = []
length = 600
breadth = 360

def draw():
    aligner = margin
    width = (breadth - margin*2)/bars
    for height in heights :
        block = {"height" : height }
        block['rect'] = canvas.create_rectangle(aligner,550-50*height,aligner+width,550, fill="green")
        block['color'] = 'green'
        blocks.append(block)
        aligner += width
    root.update()


def wid(e):
    bars = int(e)
    blocks = []
    heights = []
    for i in range(bars):
        h = random.random()*10
        heights.append(h)
    draw()

def h_rand(e):
    factor = e
    heights = [i * factor for i in heights]
    draw()

root = Tk()


width = 60
aligner = 30

slider_y = Scale(root, from_=1 , to=8, bg="blue",command = h_rand)
slider_y.pack(side=LEFT)

canvas = Canvas(root,height=length,width=breadth)
canvas.pack()

for height in heights :
    block = {"height" : height }
    block['rect'] = canvas.create_rectangle(aligner,550-50*height,aligner+width,550, fill="green")
    block['color'] = 'green'
    blocks.append(block)
    aligner += width


slider_x = Scale(root, from_=50 , to=200, orient = HORIZONTAL, bg="blue",command = wid)
slider_x.pack(side=TOP)

root.mainloop()

I am sorry for the "not so descriptive formatting" of the question ( happy to give further details in the comments ). It is bothering me for a while now and I am just frustrated.

The problem is that heights in wid is a local variable. You're changing the value inside the function, but the global variable is left unchanged.

You either need to declare heights as global inside the function, or use the global variable without replacing it with a new list.

To declear it as global, add global heights at the top of the function where it's being modified:

def wid(e):
    global heights, blocks
    ...

You can use the clear method of a list to remove the contents without resetting the variable itself. To do that, replace heights = [] with heights.clear() and the same for blocks :

def wid(e):
    bars = int(e)
    print("bars:", bars)
    blocks.clear()
    heights.clear()
    ...

You also have the problem that you're not deleting the old canvas items before creating the new. Your draw function needs to destroy the old elements. You can do that with canvas.delete("all") .

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