Im trying to do a function (Inside another function wich is a Toplevel() window on tkinter) That takes different args from different objects and move them acording to the args. Using global variables.
The thing is that for every object, I need different global variables and I dont know how to put the necessary globals for every single object.
Im trying to move images created with canvas.create_image() and I had already done that, but with an specific case.
Let me see if I can explain better:
from tkinter import *
import os
import Threading
def CargarImagen(nombre):
ruta = os.path.join('Imagenes',nombre)
imagen = PhotoImage(file=ruta)
return imagen
Space= Tk()
Space.title("Invaders! Give Some Space!")
Space.geometry ("540x540")
Space.resizable (width=NO, height=NO)
CanvSpace= Canvas(Space, width=540, height= 540)
CanvSpace.config(cursor="dotbox")
CanvSpace.pack()
ImagenFondoInicio= CargarImagen('Pantalla Inicio.gif')
FondoCanvSpace= Label(CanvSpace,image=ImagenFondoInicio)
FondoCanvSpace.pack()
DxInvader0=1 #direction x #These are the globals I need to switch on every case
DyInvader0=0 #directtion y
DxInvader1=1
DyInvader1=0
def VentanaPlayy():
Space.withdraw()
VentanaPlay= Toplevel()
VentanaPlay.title("Kill'em all!'")
VentanaPlay.resizable(width=NO, height=NO)
VentanaPlay.geometry("540x540")
def MoverInvader(numInvader, Global1, Global2, Invader): #This is where I want to put the globals as variables
global Global1, Global2 #So this would work
x,y= CanvPlay.coords(Invader)
if Global1+x<=Listaif1[numInvader]:
Global1+=-0.5
Global1= -Global1
y+=20
elif Global1+x>=Listaif2[numInvader]:
Global1+=0.5
Global1= -Global1
y+=20
print("Maximo Limite a la Derecha", CanvPlay.coords(Invader))
elif y>= 500:
print("Game Over")
CanvPlay.coords(Invader, x+Global1, y+Global2)
VentanaPlay.after(50,MoverInvader(numInvader, Global1, Global2, Invader))
def ThreadMoverInvader(numeromover):
b=Thread(target=numeromover, args=())
b.start()
CanvPlay= Canvas(VentanaPlay, width=540, height=540, bg="white")
CanvPlay.config(cursor="dotbox")
CanvPlay.place(x=-1,y=-1)
ImagenNave= CargarImagen("Ship.gif")
Nave= CanvPlay.create_image(260, 520, image=ImagenNave)
ImagenHowTo= CargarImagen("HowTo.gif")
HowTo= CanvPlay.create_image(260, 250, image=ImagenHowTo)
ImagenNave0= CargarImagen("InvaderJuego.gif")
Nave0= CanvPlay.create_image(21, 300, image=ImagenNave0)
CanvPlay.after(0, ThreadMoverInvader(MoverInvader(0, DxInvader0, DyInvader0, Nave0))) #I call the function here
ImagenNave1= CargarImagen("InvaderJuego.gif")
Nave1= CanvPlay.create_image(51, 300, image=ImagenNave1)
CanvPlay.after(0, ThreadMoverInvader(MoverInvader(1, DxInvader1, DyInvader1, Nave1))) #And here with their own globals and variables
Listaif1=[20, 50] #these are the lists I'm using for every if on the function I need
Listaif2=[490, 520]
VentanaPlay.mainloop()
Space.mainloop()
So is there any way to do this?
basically what I need to do is this:
A=1
B=2
def getglobals(global1):
global global1
and call it like :
getglobals(A)
getglobals(B)
Thank You!!
EDIT: I define VentanaPlayy() Because I use that function as a command on a button.
And btw, escuse my poor english skills... As you may notice in the code... My main languaje is spanish :)
Regards from Costa Rica :D
EDIT2: Forgot to put the error message:
def MoverInvader(numInvader, Global1, Global2, Invader):
SyntaxError: name 'Global1' is parameter and global
Related
I am currently working an a snake game, but I first want a settings window to show up.i used tkinter for this. In smaller projekts I just wrote all of the code into the pressButton function, but I want to have non spagetti code now, so im not going with that. The problem is, that I have no idea how to get the entered values in the entry brackets into my main code, as global variables, out of the pressButton function and the settingsWin function. The problem is that I use the function as a command for the Button, so I cannt use "return". Can you change global variables in the main code direcktly from inside of a function? If yes how? Or is there another way to solve this?
My Code:
def settingsWin():
def pressButton():
len = entryLen.get()
wid = entryWid.get()
speed = entrySpeed.get()
print(len+wid+speed)
SettingsWin.destroy()
return len
SettingsWin = Tk()
SettingsWin.geometry("600x600")
SettingsWin.title("Settings")
label1 = Label(SettingsWin, text="playing field [tiles]")
label1.pack()
entryLen = Entry(SettingsWin, bd=2, width=20)
entryLen.pack()
label2 = Label(SettingsWin, text="X")
label2.pack()
entryWid = Entry(SettingsWin, bd=2, width=20)
entryWid.pack()
labelblanc = Label(SettingsWin, text="")
labelblanc.pack()
label3 = Label(SettingsWin, text="Speed [ms per tick]")
label3.pack()
entrySpeed = Entry(SettingsWin, bd=2, width="20")
entrySpeed.pack()
okButton = Button(SettingsWin, text="OK", command=pressButton)
okButton.pack()
SettingsWin.mainloop()
len = "len"
wid = "wid"
speed = "speed"
It is often indicative of code smell to require that a function alter variables at scopes outside the function (except possibly in the case of closures, which are quite useful), it is possible to do so using the global keyword:
greeting = "Hello world!"
def greet():
global greeting
greeting = "Goodbye world!"
print(greeting)
greet()
print(greeting)
By declaring the variable greeting to be of global scope, altering the variable within the function definition allows the function to affect the global variable.
If you are working within nested subs, the nonlocal keyword will provide access within the inner sub, to the variable in the outer sub. It works similar to global, except that it is for broader lexical scope, not global scope.
i try to create a Flappy Bird clone. When i try to define some Global variables visual studio said me that this variables aren't defined in global scope.
Some could help me??
I tried to move the variables in the global scope and it works, but i don't understand why this solution doesn 't work.
This is my code
Thanks in advance
import pygame
import random
pygame.init()
background = pygame.image.load('img/background.png')
base = pygame.image.load('img/base.png')
bird = pygame.image.load('img/bird.png')
gameover = pygame.image.load('img/gameover.png')
pipe_down = pygame.image.load('img/pipe.png')
pipe_up = pygame.transform.flip(pipe_down, False, True)
windowX = 288
winwowY = 512
frame_rate = 50
display_surface = pygame.display.set_mode((windowX, winwowY))
FPS = frame_rate
pygame.display.set_caption('Flappy Bird')
def drawObject():
display_surface.blit(background, (0, 0))
display_surface.blit(bird, (birdX, birdY))
def update():
pygame.display.update()
pygame.time.Clock().tick(FPS)
# Here is where define my global vars
def initializes():
global birdX, birdY, birdSpeedY
birdX = 60
birdY = 150
birdSpeedY = 0
initializes()
while True:
birdSpeedY += 1
birdY += birdSpeedY
drawObject()
update()
The message is telling you exactly what the issue is. The global variables aren't defined in global scope.
That means that for these variables that you are telling it you want to use from the global namespace global birdX, birdY, birdSpeedY, it expects to find a definition of those in that uppermost namespace. The global keyword does NOT create them in the global namespace just because you use it. They must exist there independent of that.
For them to be defined in the global scope there needs to be an assignment to them in the global namespace, not inside a function or a class. That cannot be something a += either since that is a reference and an assignment and so it assumes that the definition must be elsewhere (or it would be being referenced before a value was assigned).
So somewhere in the global namespace you need an assignment. If you want to handle the initialization in a function (as you are doing) it must still be defined/assigned outside that function, but it can be any value, like None. So you could add this near the top of you program:
birdX = None
birdY = None
birdSpeedY = None
Then still use your initializes() as you are.
Or in your case you would probably just take the stuff inside initializes() and put it at the top /global level.
I'm working hard to solve this problem, can someone help me ?
There is what I mean by 'set' an argument:
from tkinter import *
window = Tk()
I=1
def add():
global I
menu1.add_command(label=I, command=lambda:Text(I))
I=I+1
def Text(I):
print(I)
menubar = Menu(window)
menu1 = Menu(menubar, tearoff=0)
menu1.add_command(label="Add", command=add)
menu1.add_separator()
menu1.add_command(label="Quit", command=window.quit)
menubar.add_cascade(label="Files", menu=menu1)
window.config(menu=menubar)
window.mainloop()
I want when we click on add and after on '1' it print '1', and when we add '2' and click on it, it print '2' but it always print the value of I, how can I set the argument by
menu1.add_command(label=I, command=lambda:Text(1))
for exemple ?
I don't know if I'm clear but I don't know how explain it !
Change your Text function to be a closure:
def Text(I):
def inner():
print(I)
return inner
Then change your add function to be this:
def add():
global I
text = Text(I)
menu1.add_command(label=I, command=text)
I=I+1
This will save the I in the text variable. The text variable is actually a function, inner, that will print I when called.
Or you could make your closure inline if you wanted to use the Text function somewhere else:
import functools
...
menu1.add_command(label=I, command=functools.partial(Text, i))
I think your problem is the lambda:Text(I). In this case, you have created a closure, but the closure knows I to be a global and is evaluating it at a later date.
You probably want to immediately evaluate Text(I) and use that as your result:
texti = Text(I) # Immediate evaluation
menu1.add_command(label=I, command=lambda:texti) # Return prior value of "I"
The idea of this code is, the user presses the first button and enters what they want, then they press the second button and it prints it out. Can someone please tell me why my return statement is not working? It says that 'variable' is not defined. Thanks in advance for taking the time to read my question.
from tkinter import*
def fun():
variable = input('Enter Here:')
return variable
def fun_2():
print(variable)
window = Tk()
button = Button(text = 'Button', command = fun )
button2 = Button(text = 'Button2', command = fun_2 )
button.pack()
button2.pack()
window.mainloop()
In python when you create a variable inside of a function, it is only defined within that function. Therefore other functions will not be able to see it.
In this case, you will probably want some shared state within an object. Something like:
class MyClass:
def fun(self):
self.variable = input('Enter Here:')
def fun_2(self):
print(self.variable)
mc = MyClass()
window = Tk()
button = Button(text = 'Button', command = mc.fun )
button2 = Button(text = 'Button2', command = mc.fun_2 )
button.pack()
button2.pack()
fun() may return a value, but Tkinter buttons don't do anything with that return value.
Note that I used the phrase return a value, not return a variable. The return statement passes back the value of an expression, not the variable variable here. As such, the variable variable is not made into a global that other functions then can access.
Here, you can make variable a global, and tell fun to set that global:
variable = 'No value set just yet'
def fun():
global variable
variable = input('Enter Here:')
Since you did use any assignment in fun2, variable there is already looked up as a global, and it'll now successfully print the value of variable since it now can find that name.
The problem is in in fun2(). It does not get variable as an input parameter.
def fun_2(variable):
print(variable)
But note that you have to call fun_2 now with the appropriate argument. Also, as the function stands right now, there is little point in having the function if you just do a print inside of it.
Take away message: variable is not global in Python, and as such you must pass it to each function that wants to use it.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 8 years ago.
Improve this question
I have been trying to use a variable which I defined within a function within a another but I don't want to use a Global.
import sys
from tkinter import *
from tkinter import messagebox
from tkinter import colorchooser
from tkinter import filedialog
x = "#000000"
#colour chooser
def mColour():
color = colorchooser.askcolor()
mlabel2 = Label(mGui,text=color).pack()
messagebox.showinfo(title = "Colour",message = "This feature has not been fully added yet.")
x = color[1]
print (color[1])
return x
#printing message
def mhello():
mtext = ment.get()
mlabel2 = Label(mGui,text=mtext, fg = (b)) # color varible = x
mlabel2.pack()
#message
def mNew():
messagebox.showerror(title = "(New) Error",message = "This feature has not been added yet.")
def mAbout():
messagebox.showinfo(title = "About",message = "This Jono's susure personal data base. (Will be)")
#question message
def mQuit():
mExit = messagebox.askokcancel(title = "Quit",message = "Are you sure")
if mExit > 0:
mGui.destroy()
#open
def mOpen():
myopen = filedialog.askopenfile()
mlabel3 = Label(mGui,text=myopen).pack()
messagebox.showinfo(title = "Open",message = "This feature has not been fully added yet.")
mGui = Tk()
ment = StringVar()
mGui.geometry("300x200+100+100")
mGui.title("Jono's Clock")
mlable = Label(mGui,text="My Label",fg = "red").pack()
mbutton = Button(mGui,text ="OK",command = mhello,fg = "red").pack()
mEntry = Entry(mGui,textvariable=ment).pack()
# Menu
menubar = Menu(mGui)
filemenu = Menu(menubar, tearoff = 0)
filemenu.add_command(label = "New",command = mNew)
filemenu.add_command(label = "Open",command = mOpen)
filemenu.add_command(label = "Colour",command = mColour)
filemenu.add_command(label = "About",command = mAbout)
filemenu.add_command(label = "Quit",command = mQuit)
menubar.add_cascade(label = "File",menu = filemenu)
mGui.config(menu = menubar)
mGui.mainloop()
I'm using python 3.3 on windows 7.
I have add the rest of the code as requested.
As the comments suggested, it would be good to pass the variable x as a parameter to the function.
def mColour(x):
...
def mHello(x):
...
Then when you want to call the functions:
x = "#000000"
x = mColour(x)
mhello(x)
As a rule of thumb, defining global variables inside a function is a bad idea (with rare circumstances being exceptions). You want to keep local and global namespaces seperate. Functions allow the passing of arguments for this reason.
#colour chooser
def mColour(x):
color = colorchooser.askcolor()
mlabel2 = Label(mGui,text=color).pack()
messagebox.showinfo(title = "Colour",message = "This feature has not been fully added yet.")
x = color[1]
print (color[1]) # Just a test
return x
x = "#000000" # default text colour
mColour(x)
You could use a class instead as I don't think there's a way to access local variables from another function.
class Example(object):
x="00006"
def c():
print(Example.x)
c()
So here you're not using any globals at all
EDIT: Now your question makes a lot more sense. Because your functions are connected to these UI controls, it becomes much more difficult to pass parameters to them.
As such, you need a structure in which to store these values that you get from the UI. Then, when mhello() needs it, it has access to a function that can get the color from whatever structure you choose to use.
Now, mHello still can't take the color or the structure as a parameter, so you've got three options.
1) You can make something global, which you've already said you don't want to do.
2) You can make something static so that you can access the same instance from within mHello.
3) But I think the best answer is to use the structure that's commonly used: Make the UI a class. It has member variables to which the member functions have access. If mColor and mHello are members of the same class, then they can access whatever they need, pretty easily. Then you create some means of getting stuff outside the UI class so that it can be accessed, processed, and returned by whatever application you're writing.
(old answer:)
There are two ways.
EDIT: Both of which have already been suggested.
You could either make both of those functions members of the same class, and then x (which you should name something more descriptive) is accessible to both of them without being global.
Or...
You could (as suggested by other commentors) pass x as a parameter to your second function. mColor() even returns x which means you can store that value in another variable that you then pass to mhello().
Incidentally, I'm not sure why you're prefacing your methods with m but that typically identifies them as members of a class. Are they?
It would also be helpful to see the rest of the code, where you're actually calling these functions.