How to get a value from another file function? python - python

Does anyone can help here?
I have two files called game.py and settings.py, I just want to get one value from settings to use in game, but I dont know what I am doing wrong.
the value I want it is in the function bbbbb...
THIS IS MY SETTINGS
from tkinter import*
import game
class Application(Frame):
def __init__ (self, master):
Frame.__init__(self,master)
self.grid()
self.create_widgets()
def bbbbb(self):
self.xr = self.ball_numbers.get()
print("printing...", self.xr)
return self.xr
def create_widgets(self):
self.ball_numbers = IntVar()
Label(self,text = "Select how many balls you wish to play:").grid()
Radiobutton(self, text = "1 Ball", variable = self.ball_numbers, value = 1, command = self.bbbbb).grid ()
Radiobutton(self, text = "2 Balls", variable = self.ball_numbers, value = 2, command = self.bbbbb).grid ()
Radiobutton(self, text = "3 Balls", variable = self.ball_numbers, value = 3, command = self.bbbbb).grid ()
settings_window = Tk()
settings_window.title(" THE BOUNCER - Settings")
settings_window.geometry("600x600")
app = Application(settings_window)
settings_window.mainloop()
I need that value in the class handling_settings, in the function create_ball_numbers
AND THIS IS MY game.py
from livewires import games, color
from tkinter import*
import settings
import random
games.init(screen_width = 735, screen_height = 350, fps = 35)
class Bounce(games.Sprite):
def update(self):
if self.right > games.screen.width or self.left < 0:
self.dx = -self.dx
if self.top < 0:
self.dy = -self.dy
if self.bottom == 315 and self.overlapping_sprites:
self.dy = -self.dy
class Bar_moving(games.Sprite):
def update(self):
self.x = games.mouse.x
self.y = 315
class handling_settings():
self.yr = bbbbb()
print("printing number from settings ", self.yr)
def create_ball_numbers(self):
print("inside def", self.yr)
def main():
background = games.load_image("BG.jpg", transparent = False)
games.screen.background = background
call = handling_settings()
call.create_ball_numbers()
bar_small = games.load_image("bar_small.jpg", transparent = False)
the_bar_small = Bar_moving(image = bar_small, x = games.mouse.x)
games.screen.add(the_bar_small)
games.mouse.is_visible = False
games.screen.event_grab = True
games.screen.mainloop()
main()
I think I am not using on the right way IMPORT on top of the file.... keeping appearing this msg...
File "C:\Users\Bruno\Desktop\DIT\Object Oriented Programming\GAME - Assignment\game.py", line 3, in <module>
from settings import bbbbb
ImportError: cannot import name bbbbb
If I run both files individually... its ok... but when I try to get the value in bbbbb function in settings, I get stuck...

You have a circular import; settings imports game, which imports settings. At that time, neither module is fully done initializing (anything beyond the import lines has not yet run).
You don't actually use the game module in settings, so just remove the import game line from settings.py.
In game.py, you imported the settings name; bbbbb is an attribute on the Application class in that module. The line:
self.yr = bbbbb()
will never work here.
You should definitely not create a new Tk() root window in settings, however; you can only ever have one main loop in a Tk application. Make settings a dialog window triggered by the main application in game.
So to get the bbbbb() result, you need to instead spawn the settings dialog box, let the user interact with it, and then retrieve the ball_numbers setting when the user closes the dialog again.

First don't do any circular import, in settings.py there is no need to import game module.
As bbbbb is a function of class Application, therefore it cannot be called directly, to call it we need an object of the same class, which is already created as
app = Application(settings_window)
so, in module game.py, just use app object to call bbbbb()
self.yr = settings.app.bbbbb()

Related

Passing a tkinter canvas between classes without calling the child from within the parent

I am somewhat of a beginner when it comes to Python, but i decided i want to write a basic 2-d physics playground. Unfortionetly i ran straigt into trouble when trying to setup the basic structure.
My plan is to create a GUI with a canvas in a parent function named mainWindow, then i figured i would create a child class (Hero) which creates a circle the user can manipulate on the canvas. This seems to work fairly well.
The problem occurs when i try to do anything with the Hero class, like call a function to delete the circle so i can redraw it in some direction. I can't seem to pass the canvas from the mainWindow to the Hero class. Any help would be greatly appreciated, including telling me that this is the wrong way to do things.
Im adding the two documents im working with since my rambling is probably hard to follow.
I run the program from the phesics.py document, resulting in the GUI poping up with my canvas and a red circle. When i close the window i get the following error:
classes.py", line 29, in moveHeroBody
canvas.delete(heroBody)
NameError: name 'canvas' is not defined
Unfortionetly i dont know how to get the "world" into the child
classes.py
from tkinter import *
class mainWindow():
def __init__(self):
#Setup the GUI
root = Tk()
root.geometry('800x600')
# Setup the canvas within the GUI (master)
world = Canvas(root, height = 600, width = 800, bg = "#FFFFFF")
world.place(relx = 0.5, rely = 0.5, anchor = CENTER)
Hero(world)
root.mainloop()
class Hero(mainWindow):
def __init__(self,world):
#Initial creation of hero at coordinates
x1 = 10
y1 = 10
x2 = 70
y2 = 70
heroBody = world.create_oval(x1,y1,x2,y2, fill = "#FF0000", outline = "#FF0000")
#Move the hero
def moveHeroBody():
print("moveHeroBody")
world.delete(heroBody)
phesics.py
from tkinter import *
from classes import *
mainWindow1 = mainWindow()
moveHero = Hero.moveHeroBody()
You're passing it ok, but you're throwing the value away. Also, Hero shouldn’t inherit from mainWindow.
You need to save world as an attribute so that you can reference it later.
class Hero():
def __init__(self,world):
self.world = world
...
Then, you can use self.world to reference the canvas:
def moveHeroBody():
print("moveHeroBody")
self.world.delete(heroBody)
Though, the above code will fail because heroBody is a variable local to the __init__ - you need to do the same with it:
class Hero():
def __init__(self,world):
self.world = world
...
self.heroBody = world.create_oval(...)
#Move the hero
def moveHeroBody():
print("moveHeroBody")
self.world.delete(self.heroBody)
I think you need to initialize the class Hero in your mainWindow class. The modifications needed to do in the code are:
classes.py
from tkinter import *
from time import sleep
class mainWindow():
def __init__(self):
#Setup the GUI
self.jump_gap = 25
root = Tk()
root.geometry('800x600')
# Setup the canvas within the GUI (master)
self.world = Canvas(root, height = 600, width = 800, bg = "#FFFFFF")
self.world.place(relx = 0.5, rely = 0.5, anchor = CENTER)
self.hero = Hero(self.world)
self.world.pack()
root.bind("<space>",self.jump) # -> [1] Binds the SPACE BAR Key to the function jump
root.mainloop()
def jump(self,event):
gaps = list(range(self.jump_gap))
for i in gaps:
self.world.after(1,self.hero.moveHeroJump(h=i)) # [2] -> Binds the moveHeroJump method with the window action to a queue of updates
self.world.update() #[2] updates the canvas
sleep(0.01*i) # Added some linear wait time to add some look to it
gaps.reverse()
for i in gaps:
self.world.after(1,self.hero.moveHeroJump(h=-i))
self.world.update()
sleep(0.01*i)
class Hero():
def __init__(self,world):
#Initial creation of hero at coordinates
self.world = world
self.x1 = 10
self.y1 = 410
self.x2 = 70
self.y2 = 470
self.heroBody = self.world.create_oval(self.x1,self.y1,self.x2,self.y2, fill = "#FF0000", outline = "#FF0000")
#Move the hero
def moveHeroJump(self,h):
print("moveHeroBody")
self.y1 -= h
self.y2 -= h
self.world.delete(self.heroBody)
self.heroBody = self.world.create_oval(self.x1,self.y1,self.x2,self.y2, fill = "#FF0000", outline = "#FF0000")
physics.py
from tkinter import *
from classes import *
mainWindow1 = mainWindow()
Edit
So this got me playing some minutes ago, and I researched some sources from stack in order to complete this question. Here are the sources (referenced in the code as well):
How to bind spacebar key to a certain method in tkinter python
Moving Tkinter Canvas
The solution edited above is capable to perform a simple animation of a ball jumping. self.jump_gap is a fixed quantity that tells the ball how much does it needs to jump. The jump parses a certain height h to the moveHeroJump method to make the ball change its position, after the change of position is queued into the Canvas an update is called to see the changes on the ball.

How to solve Error: image "pyimage1" doesn't exist

I wanted to program a simple graphical version of Tic Tac Toe in Python after having previously made a text based one with a friend. For this I used tkinter. I have been able to get rid of all mistakes in the first window where you choose which symbol you want. But in the second window when you are supposed to place it, when I press one of the buttons it tells me that "pyimage2" doesn't exist which seems to be a common error
I have already checked out some other threads where I was told that I should use TopLevel instead, since there can only be one instance of Tk(). But I already am using it, and when I try using two instances by using destroy() on the first, the error remains. I have also switched from simple PhotoImage to PIL, but even that is of no help
from tkinter import *
from random import *
from PIL import Image, ImageTk
global root
global SpielerSymbol
SpielerSymbol = "Defaultshit"
def combine_funcs(*funcs):
def combined_func(*args, **kwargs):
for f in funcs:
f(*args, **kwargs)
class SelectionScreen:
def __init__(self,pRoot):
Imageo = Image.open("o.png")
o = ImageTk.PhotoImage(Imageo)
Imagex = Image.open("x.png")
x = ImageTk.PhotoImage(Imagex)
Screen = Toplevel(pRoot)
self.TextField = Label(Screen, text="Please choose a symbol.")
self.TextField.grid(row=1,column=1)
self.ButtonX = self.SelectionButton(x,Screen)
self.ButtonX.Choice.grid(row = 2, column = 1)
self.ButtonO = self.SelectionButton(o,Screen)
self.ButtonO.Choice.grid(row = 2, column = 2)
Screen.mainloop()
class SelectionButton:
def __init__(self, pImage, pScreen):
self.Choice = Button(pScreen, image = pImage, command = lambda: combine_funcs(setSpielerSymbol(str(pImage)), pScreen.destroy(), pScreen.quit()))
def setSpielerSymbol(pZeichen):
global SpielerSymbol
SpielerSymbol = pZeichen
class Game:
def __init__(self, pRoot):
global SpielerSymbol
ImageFeldx = Image.open("Feldx.png")
Feldx = ImageTk.PhotoImage(ImageFeldx)
ImageFeldo = Image.open("Feldo.png")
Feldo = ImageTk.PhotoImage(ImageFeldo)
ImageFeld = Image.open("Feld.png")
Feld = ImageTk.PhotoImage(ImageFeld)
Window = Toplevel(pRoot)
Feld1 = [self.Feld(Feld,Window,1,1), self.Feld(Feld,Window,1,2), self.Feld(Feld,Window,1,3),
self.Feld(Feld,Window,2,1), self.Feld(Feld,Window,2,2), self.Feld(Feld,Window,2,3),
self.Feld(Feld,Window,3,1), self.Feld(Feld,Window,3,2), self.Feld(Feld,Window,3,3)]
Window.mainloop()
class Feld:
def __init__(self, pImage, pWindow, pRow, pColumn):
self.Feld1 = Button(pWindow, image = pImage, command =lambda: combine_funcs(self.setFeldImage(self), Window.quit()) )
self.Feld1.grid(row=pRow,column=pColumn)
def setFeldImage(self, pFeld1):
pFeld1.Feld1.config(image=SpielerSymbol)
def main():
root = Tk()
root.withdraw()
SelectionScreen1 = SelectionScreen(root)
print("Das ist das Werk von Feiglingen")
Game1 = Game(root)
main()
The output should be two windows, first the one where you choose a symbol, that one should work fine, and the second should be a tic tac toe field where clicking on a button should display the symbol you've chosen. And what I instead get is the error message image "pyimage1" doesn't exist
Also sorry for the ugly code, I am still a beginner, especially at Python

Variables in custom python module

I am making my own custom python module called zoro, and I want to enable people making a variable, and the variable is equal to a function in my module, but how do I make that?
I've already tried looking in to the code of other modules like turtle, and turtle used the self argument, so I tried to use that, but it said TypeError: win() missing 1 required positional argument: 'self'.
Code of my program to test the module:
import zoro
test = zoro.win("test","black",500,500)
test.zoro.winTitle("test2")
Code of my module:
from tkinter import *
def win(title,bg,w,h):
root = Tk()
root.title(title)
root.config(bg=bg)
root.geometry(str(w) + "x" + str(h))
return root
def winTitle(title):
root.title(title)
I want to do like:
test = zoro.win("test","black",500,500)
test.zoro.winTitle("test2")
Question:
What you want to do is called inheritance.
For example:
zoro.py
import tkinter as tk
class App(tk.Tk):
def __init__(self, title, bg, width, height):
super().__init__()
self.title(title)
self.geometry('{}x{}'format(width, height)
self.config(bg=bg)
Usage
import zoro
class MyApp(zoro.App):
def __init__(self):
super().__init__("test","black",500,500)
# Change title
self.title('my new title')
# Add further widgets
if __name__ == '__main__':
MyApp().mainloop()
Assuming you want your driver to work with the module as currently defined, you need a global variable named root for winTitle to use. In addition, the object returned by win doesn't have an attribute named zoro.
import zoro
zoro.root = zoro.win("test", "black", 500, 500)
zoro.winTitle("test2")
That said, your module should be fixed to avoid global variables in the first place.
from tkinter import *
def win(title, bg, w, h):
root = Tk()
root.title(title)
root.config(bg=bg)
root.geometry(str(w) + "x" + str(h))
return root
def winTitle(root, title):
root.title(title)
Then your driver will look like
import zoro
test = zoro.win("test", "black", 500, 500)
zoro.winTitle(test, "test2")

Tkinter canvas PhotoImage is not appearing

I have a problem with my code. I am creating a small video game called Lumanite. I have created the homepage and have started the graphics generation, but I have run into a bug. I am using Python 3.3 and am on a Win 10 laptop. I run the program through a run file, which accesses the main_game file that uses the classes outlined in a separate file, spritesclasses. I am trying to make a sprite appear. Here is the code for the main_game file and the spritesclasses file. (They import the canvas and root from a MENU file)
#SPRITES
from tkinter import *
from GUI_FILE import canvas, root
from OPENING_FILE import show, hide
class Sprite():
def __init__(self, photoplace):
self.orgin = photoplace
self.photo = PhotoImage(file=photoplace)
self.w = self.photo.width()
self.h = self.photo.height()
def draw(self):
self.sprite = canvas.create_image(self.h, self.w, image=self.photo)
And the MAIN_GAME file:
#Main Game File:
from tkinter import *
from OPENING_FILE import show, hide
from GUI_FILE import root, canvas
from spritesclasses import *
def start_game():
genterrain()
def genterrain():
test = Sprite("logo.gif")
test.draw()
And the sprites are not appearing. No error or anything. Please help me. I will supply you with information at a further notice.
This is a known but tricky issue. You can read about it in Why do my Tkinter images not appear? I've implemented one possible solution below:
from tkinter import *
class Sprite():
def __init__(self, photoplace):
self.photo = PhotoImage(file=photoplace)
self.w = self.photo.width()
self.h = self.photo.height()
self.sprite = None
def draw(self):
canvas = Canvas(root, width=self.w, height=self.h)
canvas.pack()
self.sprite = canvas.create_image(0, 0, anchor=NW, image=self.photo)
def start_game():
genterrain()
def genterrain():
sprite = Sprite("logo.gif")
sprite.draw()
sprites.append(sprite) # keep a reference!
root = Tk()
sprites = []
start_game()
root.mainloop()
The assignment self.photo = PhotoImage(file=photoplace) isn't a sufficient reference as the object test goes out of scope when genterrain() returns and is garbage collected, along with your image. You can test this by commenting out the line sprites.append(sprite) and see your image disappear again.
Also, it wasn't clear why you were positioning the image at it's own width and height -- the first to arguments to create_image() are the X and Y position. I moved canvas creation into draw() so I could size the canvas to the image but that's not a requirement of the visibility fix.

Namespaces and Accessing Tkinter

I have a question, though I'm not sure what language to use. I'm a little confused about how to access the canvas defined in the main driver module from other modules without using globals. For instance, I have instantiated the canvas in driver.py, but am trying to draw from Level.py. For context, it is eventually going to read a text file and draw a map based on the data it extracts from it for an RPG-ish game. Here is my code:
Driver.py:
import tkinter
import Level
HEIGHT = 1024
WIDTH = 800
TILE_SIZE = 32
VERTICAL_TILES = HEIGHT//TILE_SIZE
HORIZONTAL_TILES = WIDTH//TILE_SIZE
root = tkinter.Tk()
root.title("RPG Land")
window = tkinter.Canvas(root,width= WIDTH, height=HEIGHT )
lev = Level.LevelMgr()
lev.loadLevel()
lev.drawLevel()
window.pack()
root.mainloop()
Annnd Level.py:
import tkinter
from driver import window
class LevelMgr:
def __init__(self):
self.levelData = []
self.visibleLevel = []
self.tileColors = {
0 : 'empty',
1 : 'wall',
2 : 'bush' }
def loadLevel(self):
fyle = open('levels/level1','r')
count = 0
for lyne in fyle:
self.levelData.append(lyne)
count += 1
def drawLevel(self):
currentY = 0
currentX = 0
for col in self.levelData:
currentY += 32
for t in col:
window.create_rectangle(currentX, currentY, 32, 32, fill="blue")
currentX += 32
Any advice on how to structure the program better would be also appreciated. When accessing other namespaces, what is the proper way to do so? Do I need to have "import Level" on driver.py, as well as "import driver" in Level.py? I'm a little confused as to the fundamental structure of such a program.
LevelMgr depends on window, so name it explicitly in __init__:
class LevelMgr:
def __init__(self, window):
self.window = window
def drawLevel(self):
...
for t in col:
self.window.create_rectangle(currentX, currentY, 32, 32, fill="blue")
Remove the import statement:
from driver import window
Then, in Driver.py:
lev = Level.LevelMgr(window)
Another possibility is to simply define window in Level.py instead of Driver.py.

Categories