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
Related
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 : "
I want to constantly run an if loop outside of my functions, but I can't figure out how to do it. I made a mock up of the code::
import tkinter
from tkinter import *
code = Tk()
T = 1
X = 0
def printx():
global X
print(X);
def teez():
global T
T = 0;
def teeo():
global T
T = 1;
if T == 1:
X = 5
else:
X = 6
button1 = Button(code, text = "Print X", command = printx)
button1.pack()
button2 = Button(code, text = "T = 0", command = teez)
button2.pack()
button2 = Button(code, text = "T = 1", command = teeo)
button2.pack()
code.mainloop()
I want the if loop to change X based on what my functions do, but the if loop seems to not run.
There is no such thing as an "if loop". if is a conditional statement that executes one of two branches of code, once only. The looping statements at this level are for and while; see your favorite Python tutorials to become familiar with their usage.
Running a constant monitor loop is the wrong control flow for this. Rather, you need only to check when the button is pressed. Put the functionality inside your press-handling routines:
def teez():
global T, X
T = 0
X = 6
def teeo():
global T, X
T = 1
X = 5
I strongly question setting global variables within the code. Instead, consider making an object with attributes T and X, and setting those as needed, passing the object to the routines that have to manipulate them.
the if structure is not a loop, but a conditional statement. If you want to do something iteratively, try with while True:
I have two buttons on my interface. I want both of them to be able to call their respective functions when I either click on them or a hit the Enter Key.
The problem I'm having is that only the last button in the traveral focus gets activated when I hit the Enter Key, even if the preceeding one has the focus. What can I do to resolve this problem.
Useful answer are welcome and appreciated.
This is the problem in question:
from tkinter import *
w = Tk()
def startProgram(event = None):
print('Program Starting')
def readyContent(event = None):
print('Content being prepared')
# Buttons
Button(text='Prepare', command=readyContent).grid(row=10,column=2)
w.bind('<Return>',readyContent) # Binds the Return key to a Function
Button(text='Start', command=startProgram).grid(row=10,column=3)
w.bind('<Return>',startProgram) # Binds the Return key to a Function
w.mainloop()
When you click on the Prepare or Start button, in return you get either Content being prepared or Program Starting repectively. Nothing like that happens when you use the Tab Key to give focus to one button or the other. Even if the focus is on the Prepare button, when you hit Enter you get: Program Starting
This is the solution to my problem.
I hope it helps anyone else having the same problem as me.
from tkinter import *
w = Tk()
def startProgram(event = None):
print('Program Starting')
def readyContent(event = None):
print('Content being prepared')
# Buttons
btn1 = Button(text='Prepare', command=readyContent)
btn1.grid(row=10,column=2)
btn1.bind('<Return>',readyContent) # Binds the Return key to a Function
btn2 = Button(text='Start', command=startProgram)
btn2.grid(row=10,column=3)
btn2.bind('<Return>',startProgram) # Binds the Return key to a Function
w.mainloop()
Have a good day! :)
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.
I'm trying to create an "Admin" section to a small program that executes some maths.
The admin button on the main TK window creates a top level window with an entry field that only turns on when the correct password is entered into a password field (or at least it will be when I figure out how to do this.)
The submit button is intended to update the global variable of a price that will then be remembered by the program from the entry field that would have the new price input by the user. The issue I'm having is how to make the global variable update and change and stay changed once this button is pressed.
This code is only designed to test the ability to do this but for the sake of context I will post it here anyways. Any help towards this goal would be fantastic.
The issue is that this code does not work, it wont allow me to alter the global variables, and produces the error the variable int has no attribute append?
Further - So append was the wrong move, fair enough, the problem i have is that global12mmprice = 200 is not updating the globalvariable and at other points in the program it is still referencing the original value. Is there a way to completely update the global variable so that the program will reflect the new value and the old one will no longer exist?
global12mmprice = 86.67
global15mmprice = 191.19
int12mmprice = int(global12mmprice)
int15mmprice = int(global15mmprice)
class mainwindow(tk.Frame):
def __init__(self, root):
tk.Frame.__init__(self, root)
b1 = tk.Button(self, text="Glass Table", command = self.glsqWindow)
b1.grid(column=1,row=2,pady=50,padx=10)
self.count = 0
b2 = tk.Button(self, text='Round Table', command = self.glrnWindow)
b2.grid(column=2,row=2,pady=50,padx=10)
self.count = 0
b3 = tk.Button(self, text='Console Table', command = self.glcnWindow)
b3.grid(column=3,row=2,pady=50,padx=10)
self.count = 0
b4 = tk.Button(self, text='Admin', command = self.admin)
b4.grid(column=4,row=2,pady=50,padx=10)
self.count = 0
def admin(self):
self.count += 1
window = tk.Toplevel(self)
window.geometry("600x350+300+300")
def submit():
int12mmprice.append(200)
b1 = tk.Button(window,text='Submit', command=submit)
b1.grid(column=3,row=2,pady=50,padx=10)
There is alot more code after this but this is the relevant part. Also any general advice you might have is of course welcome.
ANSWER:- Provided with alot of assistance from "fdhsdrg". This is the solution that i implemented to get the desired result for anyone who has this question in future.
As was explained to me i needed to create a file that the program could read and write to that would create the necessary information for the program to access and alter as and when needed.
import tkinter as tk
from tkinter import *
from tkinter import Tk, Frame, Menu
import tkinter.messagebox as box
import pickle, os
file=open('prices.dat','rb')
data=pickle.load(file)
file.close
global12mmprice = data[0]
global15mmprice = data[1]
class mainwindow(tk.Frame):
def __init__(self, root):
tk.Frame.__init__(self, root)
b1 = tk.Button(self, text="Glass Table", command = self.glsqWindow)
b1.grid(column=1,row=2,pady=50,padx=10)
self.count = 0
b2 = tk.Button(self, text='Round Table', command = self.glrnWindow)
b2.grid(column=2,row=2,pady=50,padx=10)
self.count = 0
b3 = tk.Button(self, text='Console Table', command = self.glcnWindow)
b3.grid(column=3,row=2,pady=50,padx=10)
self.count = 0
b4 = tk.Button(self, text='Admin', command = self.admin)
b4.grid(column=4,row=2,pady=50,padx=10)
self.count = 0
def admin(self):
self.count += 1
window = tk.Toplevel(self)
window.geometry("600x350+300+300")
def submit():
global data
data[0] = '86.67'
file=open('prices.dat','wb')
pickle.dump(data,file)
file.close
global root
box.showinfo('Administration','The program will now terminate and the prices will be updated.')
root.destroy()
b1 = tk.Button(window,text='Submit', command=submit)
b1.grid(column=3,row=2,pady=50,padx=10)
As you can see the data list in the .dat file gets updated, later i will replace this with a get.entry() field but for now this demonstrates the intended design. You might want to consider using resetboard instead of destroy if you want the program to automatically relaunch after closing.
Well, the error message you added pretty much explains everything.
int12mmprice is an Integer, which does not have the method append. Append is a method which can be used on objects of type List:
>>> a=9
>>> type(a)
<type 'int'>
>>> a.append(15)
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
a.append(15)
AttributeError: 'int' object has no attribute 'append'
>>> a=[9]
>>> type(a)
<type 'list'>
>>> a.append(15)
>>> a
[9, 15]
EDIT:
Right, now the problem of the scopes. To edit the global int12mmprice put global int12mmprice at the start of the submit function. This makes sure that submit does not look at int12mmprice in its own function scope but in the global scope.