Python multiple commands tkinter - python

Im quite new to python and cant solve a problem after searching a lot. Maybe you guys can help me out. I want to add multiple commands to 1 butten. So if you have 100hp, you will lose every time 10hp and if you are on 0hp you get 50hp back, but dont know how to do that. I have read you need to use 1 function and inside both functions but when im doing that i get an error.
player_1_lose_10_Button = Button(self, text = "10 HP", command=self.myfunction)
player_1_lose_10_Button.place(x=180,y=140)
def myfunction(self):
lose10(self)
check(self)
def check(self):
global player1health
if player1health <= 0:
player1health +=50
player_1_lose_10_Button = Button(self, text = "50 HP", command=self.check)
print('You died, you get 50hp back')
def lose10(self):
global player1health
player1health-=10
print(f'You lost 10 HP, current HP: {player1health}')

You can combine these into one function just fine:
def lose_but_check(self):
self.lose10()
self.check()

Related

Why is only the function work and the Texts aren't showing?

I have been trying to make a user input with seconds together which counting down one by one till Zero. Sometimes somethings comes into my head but i take unexpected results. I am really wondering why the texts aren't being shown. Thanks for help from now.
import time
def timer():
for x in range(60,-1,-1):
print(x)
time.sleep(1.5)
input(f"Type code in {timer()} seconds : ")
What is wrong...
You are getting error because when you call input(f"Type code in {timer()} seconds : "), the program will run timer() and try to get the returned value from it, then print it with f'Type code in {value} seconds : '.
That is why you will get the count down of 60...0 on your screen, followed by Type code in None seconds :, as timer() return nothing(None).
What to do...
Rendering a renewing display and trying to get user input at the same time in the command prompt is not ideal if not impossible. (Command prompt is not for fancy display.)
To achieve your goal, i suggest using an UI (user-interface), here is a simple UI to do it:
import tkinter as tk
class UI():
def __init__(self):
self.root = tk.Tk()
self.root.geometry("200x50")
self.data = tk.StringVar()
self.label = tk.Label(text="")
self.entry = tk.Entry(textvariable=self.data)
self.label.pack()
self.entry.pack()
self.x = 60
self.count_down()
self.entry.bind("<Return>", self.end)
self.root.mainloop()
def count_down(self):
if self.x < 0:
self.root.destroy()
else:
self.label.configure(text=f"Type code in {self.x} seconds : ")
self.x -= 1
self.root.after(1500, self.count_down)
def end(self, keypress):
self.root.destroy()
app = UI()
value = app.data.get()
# do whatever you want with value
print('value : ',value)
As tdelaney and DarryIG said in the comment, when executing the code snippet, it will output 60,59,58..., until 0, and then display "Type code in None seconds : ", I think this is the right result.
only place a simple expression(such as a variable) in the {}, the code snippet can output the expression and literal together.
Time = 5
input(f"Type code in {Time} seconds : ")
The code snippet above will output"Type code in 5 seconds : "

is it possible to get a variable out of a function, into another function, if the first one doesn't trigger by the second one?

def NewNote(x, y):
print("something")
text = input()
return (text)
def Delete(x, y):
text = GetText()
pen.write(text, align="left", font=("arial", TextSize))
print(text)
**text = BlackSquare.onrelease(NewNote)**
**text = VerLine.onrelease(NewNote)**
**text = HorzLine.onrelease(NewNote)**
color = turtle.onscreenclick(settings)
WhiteeraserSquare.onrelease(Delete)
BlackeraserSquare.onrelease(Delete)
def GetText():
textA = text
return textA
< so basically the NewNote function gets triggered by one of the starred triggers, takes an input from the user, and from there i want to get that input to the delete function. so i tried to return it to the trigger, save it again as a variable, than put it into another function that would send it back up to the
delete function, but i clearly don't understand how the whole return thing works, because the delete function keeps printing "none".
(i am using the Turtle graphics module, so.. the triggers, and the pen.write are from there).
ps: this is my first time asking a question in stack overflow, so if i did something wrong, forgive me.
You're misunderstanding turtle event handlers and need to (re)read about them:
def NewNote(x, y):
print("something")
text = input()
return (text)
text = BlackSquare.onrelease(NewNote)
The onrelease() method doesn't return anything (returns None) so assigning its result into the text variable does nothing.
The NewNote() event handler's caller doesn't care about its return value so the return (text) is basically ignored.
Here's a simple example that I hope will help you understand how these functions are used. It puts up two turtle buttons, a green and red square. Click on the green one and it will prompt you for input and write in the center of the screen. Click on the red one and it will erase that text:
from turtle import Screen, Turtle
def delete_text(x, y):
pen.clear()
def write_text(x, y):
text = screen.textinput("Text Input", "Enter some text")
pen.clear()
pen.write(text, align='center', font=('Arial', 18, 'bold'))
screen = Screen()
write = Turtle()
write.shape('square')
write.color('green')
write.penup()
write.onrelease(write_text)
write.backward(200)
erase = Turtle()
erase.shape('square')
erase.color('red')
erase.penup()
erase.onrelease(delete_text)
erase.forward(200)
pen = Turtle()
pen.hideturtle()
screen.mainloop()
To pass information between write_text() and delete_text() requires some sort of global entity through which to pass this information. It can be as simple as a global variable or something more complex like an object that's passed as an extra argument to the handers via a lambda expression.

Passing variable from one function to another in same class?

I'm trying to create a button that changes colors on click.
After digging around in an old Python book I haven't looked at in years, I've gotten to the point where I make the the button, but I can't figure out how to pass i into the second function so it increments and is then is reset to 0.
I suppose I could just increment I on click in the first function, but now I'm annoyed and want to figure it out.
Instead of self.change_color I tried change_color(i). That threw an error. Same with trying self.change_color(i).
I'm not sure what to do at this point.
import tkinter
class joeGUI:
def __init__(self):
i = 0
colorArray = ['blue','DarkGreen','red','yellow']
self.main_window = tkinter.Tk()
self.color_button = tkinter.Button(self.main_window,
text = 'Click to Change Color',
command = self.change_color,
bg = colorArray[i])
self.color_button.pack()
tkinter.mainloop()
def change_color(self):
if (count < 3):
count += 1
else:
count = 0
return count;
joe_gui = joeGUI()
Store i as a class attribute (self.i = 0) and change the references of count to self.i.

Python GUI shuts down when i use infinite loop

I tried to make a Clicker and I used an infinite loop, so I would raise my Variable every second. But every time I use the Button, my program crashes.
Do you have any advice how I prevent that, because I have no idea what is really happening.
import time
from tkinter import *
class Clicker :
#updates the Label
def AK_CLabel(self):
self.ClickerLabel.configure(text="Du hast " + str(self.Clicks))
#Generates Clicks
def Klicken(self):
self.Clicks += 1
self.AK_CLabel()
#raises price of Helping Elf and raises the clicks per second
def HElf(self) :
if(self.Clicks >= self.priceHElf) :
self.Clicks -= self.priceHElf
self.priceHElf = self.priceHElf * 1.2
self.Elfs += 1
self.Elfhilft()
self.AK_CLabel()
#Should make the Clicks go up by the amount of Elfs, but if I use the Button the Programm shuts down
def Elfhilft(self):
while (not time.sleep(5)):
self.Clicks = self.Bitcoins1 + self.Elfs
time.sleep(1)
def __init__(self, master):
self.master = master
self.master.title = "Der Klicker"
self.Elfs = 0
self.priceHElf = 30
self.Clicks = 30
#Buttons and Label
self.DerKnopf = Button(text = "Clicks", command = self.Klicken)
self.ClickerLabel = Label(text = "You have " +str(self.Clicks))
self.HelferElf = Button(text = "A helping Fairy", command = self.HElf)
self.DerKnopf.pack()
self.ClickerLabel.pack()
self.HelferElf.pack()
root = Tk()
my_gui = Clicker(root)
root.mainloop()
Firstly, in your example bitcoins1 is undeclared. I assume this is just a variable name you forgot to change before posting, so I renamed it to clicks in order to replicate your issue.
Second, you have your Elfhilft() function using sleep(), which is causing issues with your Tkinter app. Tkinter uses its own loop system to handle real-time stuff, and sleep will cause that loop to stall in most cases. I suggest you use an implementation of after (How to create a timer using tkinter?) in order to replicate the autoclicker-esque function I assume you're trying to implement. As an example:
def autoclick(self):
self.clicks = self.clicks + self.Elfs
#In main app / __init__()
root.after(1000, self.autoclick) # updates auto-clicks every second

Tkinter mainloop() not running - Python

I have designed somewhat of an AI to play 2048. I would like to display the game state after each move the AI makes. To do so, I have created a GUI using Tkinter.
First time using Tkinter, and as the title suggests, it seems like my 'updateDisplay' method blocks the mainloop() from being called. Any help would be appreciated.
The GUI will display if I remove the call to self.after(1000, self.updateDisplay(ai, game)). However, it will then obviously not update
class GameGrid(Frame):
def __init__(self,ai, game):
Frame.__init__(self)
self.game = game
self.ai = ai
self.grid()
self.master.title('2048')
#self.gamelogic = gamelogic
self.grid_cells = []
self.init_grid()
self.update_grid_cells()
self.after(1000, self.updateDisplay(ai, game))
self.mainloop()
def updateDisplay(self, ai, game):
game.move(ai.nextMove(4))
print "hello"
for i in range(GRID_LEN):
for j in range(GRID_LEN):
new_number = int(game.state[i][j])
if new_number == 0:
self.grid_cells[i][j].configure(text="", bg=BACKGROUND_COLOR_CELL_EMPTY)
else:
self.grid_cells[i][j].configure(text=str(new_number), bg=BACKGROUND_COLOR_DICT[new_number], fg=CELL_COLOR_DICT[new_number])
if game.over:
if game.won:
print 'You Won!'
else:
print 'Game Over :( Score:', game.score
return 0
else:
print "test"
self.after(10000, self.updateDisplay(ai, game))
if __name__ == "__main__":
game = Game()
ai = AlphaBetaRecursive(game)
gui = GameGrid(ai, game)
When you do self.after(1000, self.updateDisplay(ai, game)), you're calling self.updateDisplay immediately rather than passing the function as an argument to after. You need to get rid of the inner parentheses! According to the docs, after does take extra *args, but it doesn't actually say what is done with them (maybe they're passed to the callback? I'm not sure). Since ai and game are already attributes of self, you don't actually need to pass them as arguments at all. Just use:
self.after(1000, self.updateDisplay)
And change the definition of updateDisplay to:
def updateDisplay(self):
# use self.ai and self.game rather than ai and game in the implementation of the function
...

Categories