Hi I have this code:
from tkinter import *
import random
class calculation_game:
def __init__(self):
self.screen_user = Tk()
self.screen_user.title("חישובים - מסך משתמש")
self.screen_user.geometry("400x400+600+200")
self.screen_user.resizable(False, False)
self.x = 0
self.points_user = Label(self.screen_user, text="הניקוד שלך הוא: ")
self.points_user.place(x=290, y=370)
self.points_text = Label(self.screen_user, text=self.x)
self.points_text.place(x=252, y=370)
self.button = Button(self.screen_user, text="שלח", command=lambda :self.select_lvl())
self.button.place(x=180, y=230)
self.text_name = StringVar()
self.text_name = Entry(self.screen_user, justify='center')
self.text_name.place(x=100, y=200)
self.screen_user.mainloop()
I have this var: self.x = 0
I want add 1 to self.x if something good after I add 1 to var self.x
I want show this on the software with self.points_text
sorry in my English
I dont quite understand your question but I believe you're trying to increment self.x by one if an event occurs
try using
self.x += 1
instead
Related
i have 2 classes and when i run the first one, it works fine but when it gets to the second class i get an error saying AttributeError: 'Question2' object has no attribute 'correct'. how do i make it so that the functions work in both of the class? is there something wrong with my indent? please help me fix this code, thanks:
Edit: i have a problem with using self, if i remove self from the functions it wouldnt work, if i indent it to not be a part of the class, it still wont work, the self gets turns white
class Question1:
def __init__ (self, master):
x = random.randint(5, 12)
y = random.randint(5, 12)
self.master = master
self.user_choice = StringVar()
self.user_choice.set("")
self.frame = Frame(master, padx=200, pady=200)
self.frame.grid()
self.q = Label(self.frame, text="What is {} + {} ?".format(x, y))
self.q.grid(row=0)
self.ans = Entry(self.frame, width=50, textvariable=self.user_choice)
self.ans.grid(row=1)
self.answer = x+y
self.sub = Button(self.frame, text="submit", command=self.correct)
self.sub.grid(row=3)
def correct(self):
global p
if int(self.user_choice.get()) == self.answer:
cor = Label(self.frame,text="Correct!")
cor.grid(row=5, pady=20)
p += 1
if p >= 3:
Question2(self.master)
else:
self.sub.destroy()
nex = Button(self.frame, text="Next", command=self.necs)
nex.grid(row=4)
else:
inc = Label(self.frame,text="incorrect")
inc.grid(row=5, pady=20)
self.sub.destroy()
nex = Button(self.frame, text="Next", command=self.necs)
nex.grid(row=4)
self.frame.destroy()
Question1(self.master)
def necs(self):
self.frame.destroy()
Question1(self.master)
class Question2:
def __init__(self, master):
x = random.randint(2, 2)
y = random.randint(2, 3)
self.master = master
self.user_choice = StringVar()
self.user_choice.set("")
self.frame = Frame(master, padx=200, pady=200)
self.frame.grid()
self.q = Label(self.frame, text="What is {} x {} ?".format(x, y))
self.q.grid(row=0)
self.ans = Entry(self.frame, width=50, textvariable=self.user_choice)
self.ans.grid(row=1)
self.answer = x * y
self.sub = Button(self.frame, text="submit", command=self.correct)
self.sub.grid(row=3)
You can do that by inheriting the properties of Question1 to Question2:
That can be:
class Question2(Question1):
#you can access that by:
self.correct()
Other way is you can define a global function outside both the classes and you can easily access it.
Example:
#somewhere globally:
def correct():
#some code
class Question1():
correct()
class Question2():
correct()
I think you can develop more such ideas of using a function which will be required by multiple classes.
As #JenilDave answered, you need to define function outside class, inherit from other class.explicitly call class.
i.e. for last case:
class Question1:
def correct():
<codes>
class Question2:
q1 = Question1()
q1.correct()
or
Question1.correct(<Question1 instance>)
But since your 'correct' function are heavily dependent to Question1, you can't use either way, and reconstruct your codes.
Working example below:
Instead of generating question Class per questions, send lists of questions to one class.
Every time you succeed third time, you'll move on to next questions by poping list you've provided before.
When Lists are empty, pop() causes IndexError and program closes.
...
Since I can't get what variable 'p' stands for, I'm guessing it's number of successes(passes).
Full Code:
import random
from tkinter import Frame, Label, Entry, Button, StringVar, Tk
class QuestionFrame(Frame):
def __init__(self, master, question_answer):
super().__init__(master)
self.x, self.y = 0, 0
self.master = master
self.entries = question_answer
self.question, self.answer = self.entries.pop(0)
self.success = 0
self.user_choice = StringVar()
self.frame = Frame(master)
self.frame.grid()
self.quest_label = Label(self.frame)
self.ans = Entry(self.frame, width=50, textvariable=self.user_choice)
self.sub = Button(self.frame)
self.quest_label.grid(row=0)
self.ans.grid(row=1)
self.sub.grid(row=3)
self.reload_question()
def reload_question(self):
self.x, self.y = random.sample(range(5, 12), 2)
next_quest = f"What is {self.question.format(self.x, self.y)} ?"
self.quest_label.configure(text=next_quest)
self.ans.delete(0, 'end')
self.sub.configure(text="submit", command=self.correct)
def next(self):
print(self.success)
if self.success == 3:
# loads next entry
try:
self.question, self.answer = self.entries.pop(0)
except IndexError:
self.master.destroy()
else:
self.success = 0
self.reload_question()
else:
self.reload_question()
def correct(self):
self.sub.configure(text="Next", command=self.next)
if int(self.user_choice.get()) == self.answer(self.x, self.y):
self.quest_label['text'] = "Correct!"
self.success += 1
else:
self.quest_label['text'] = "Incorrect!"
if __name__ == '__main__':
# Passing questions with list of (question, answer) tuples.
tests = [("{} x {}", lambda x, y: x*y),
("{} - {}", lambda x, y: x-y)]
root = Tk()
root.title(f'Some fancy title')
window = QuestionFrame(root, tests)
window.mainloop()
I can't seem to update my money counter(var money) when its labeled, I have a button that's supposed to add 0.1 to moneyNum but the money counter doesn't change. I'm new to stack overflow and would appreciate any help.(btw sry if its REALLY messy)
from tkinter import *
import random
from time import sleep
root = Tk()
root.geometry('320x320')
#spacing
spacingTitle = Label(root, text=" \n\n\n\n\n\n\n\n\n")
#title
title = Label(root, text=" \bGamblers Dream\b", font="Helvetica", fg="red")
titleWelcom = Label(root, text=" Welcom to...")
titleWelcom.grid()
title.grid()
#money counter
moneyNum = float(10.0)
money = Label(root, text="money:" + str(moneyNum), font="Helvetica")
money.grid(row=3, column=0)
#moneyClicker
def moneyButtonAdder():
global moneyNum
moneyNum = moneyNum + 0.1
moneyClicker = Button(root, text="click", fg="green", command=moneyButtonAdder)
moneyClicker.grid(row=14)
root.mainloop()
The problem is that once you create a label, you pass the string to it. Label displays the string, and:
changing a string object does not change the label text
changing the integer does not change the string - it lost the whole connection when the new string object was created
So everything is not as procedural as you would have hoped it is.
The solution - use StringVar objects and detect value changes - see this.
So, the solution is:
from tkinter import *
class Observed(object):
"""adapted copy from https://stackoverflow.com/a/6192298/10713244"""
def __init__(self):
self._observed = 10.0
self._observers = []
#property
def observed(self):
return self._observed
#observed.setter
def observed(self, value):
self._observed = value
for callback in self._observers:
print('announcing change')
callback(self._observed)
def bind_to(self, callback):
print('bound')
self._observers.append(callback)
class Observer(object):
def __init__(self, data):
self.text = ''
self.data = data
self.data.bind_to(self.update)
self.tkinter_init()
def update(self, observed):
self.text = 'float: '+str(data._observed)
self.tkinter_update()
def tkinter_init(self):
self.tk = Tk()
self.tvar = StringVar()
self.label = Label(textvariable=self.tvar)
self.label.pack()
def tkinter_update(self):
self.tvar.set(self.text)
if __name__ == '__main__':
data = Observed()
label = Observer(data)
print(label.text)
data.observed = 10.0
print(label.text)
def dec(): data.observed -= 0.1
Button(label.tk, text='decrease', command=dec).pack()
label.tk.mainloop()
Hope that's helpful!
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I am trying to run a while loop that changes the variables in my code but instead it just breaks my code. I am not sure what to do. I want X to change when I change T without the command being repeated.
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;
while 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()
P.S. It is in python 3.7
First lets correct your imports.
You do not need to import Tkinter twice and it is preferred you do not use *.
The best way to import Tkinter is like this:
import tkinter as tk
Then simply use the tk. prefix for Tkinter widgets.
Now to address your looping issue. Tkinter comes with a cool method called after(). Keep in mind the after() method uses a number to represent milliseconds so 1000 is 1 second. So in the below code we are running the check_t function 1000 times a second. You may wish to change that depending on your needs. We can use this method and a function to check the status of your variables and make the needed changes without affecting the mainloop() like a while statement will.
import tkinter as tk
root = tk.Tk()
T = 1
X = 0
def printx():
global X
print(X)
def teez():
global T
T = 0
def teeo():
global T
T = 1
def check_t():
global T, X
if T == 1:
X = 5
root.after(1, check_t)
else:
X = 6
root.after(1, check_t)
button1 = tk.Button(root, text = "Print X", command = printx)
button1.pack()
button2 = tk.Button(root, text = "T = 0", command = teez)
button2.pack()
button2 = tk.Button(root, text = "T = 1", command = teeo)
button2.pack()
check_t()
root.mainloop()
The above code will do exactly what you are trying to do without freezing the mainloop(). That said I really don't like using lots of global statements and prefer the OOP route. The below code is a reworked version of your code that is in OOP.
import tkinter as tk
class MyApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.t = 1 # changed to lower case name as UPPER case is used for constants
self.x = 0
tk.Button(self, text="Print X", command=self.printx).pack()
tk.Button(self, text="T = 0", command=self.teez).pack()
tk.Button(self, text="T = 1", command=self.teeo).pack()
self.check_t()
def printx(self):
print(self.x)
def teez(self):
self.t = 0
def teeo(self):
self.t = 1
def check_t(self):
if self.t == 1:
self.x = 5
self.after(1, self.check_t)
else:
self.x = 6
self.after(1, self.check_t)
MyApp().mainloop()
Here's a super simple GUI program to help illustrate my question. It has:
A window:
main_window (tkinter.Tk())
Two buttons:
self.button1 & self.button2
An attribute/variable:
self.x (an integer: 0)
A method:
xplus1(self) (adds 1 to self.x)
self.button1:
Text says 'Quit'.
Clicking it will terminate the process, via tkinter.destroy.
self.button2:
Text says 0, because it's set to x.
Clicking it is supposed to increase 0 by 1, via self.xplus1.
How can I get the value displayed on self.button2 to increase when clicked?
from tkinter import *
class Main:
def __init__(self):
main_window = Tk()
self.x = 0
self.button1 = Button(main_window,text=self.x,command=self.xplus1)
self.button1.pack()
self.button2 = Button(main_window,text='Quit',command=main_window.destroy)
self.button2.pack()
mainloop()
def xplus1(self):
self.x = self.x + 1
Main()
Add self.button1.config(text=self.x) to the definition of xplus1(self):
def xplus1(self):
self.x = self.x + 1
self.button1.config(text=self.x)
So I have been playing with tkinter to try add a gui to a lift simulator project I have written for university. It is not really needed, but I would like to add it.
Here is the code that I currently have.
import tkinter as tk
class Application(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
master.title("Test") #Controls the window title.
self.pack()
self.createWidgets()
def createWidgets(self):
floors = [i for i in range(41)]
buttons = []
xPos = 0
yPos = 0
for floor in floors:
if(yPos == 5):
xPos = xPos + 1
yPos = 0
if(xPos == 8):
yPos = 2
self.button = tk.Button(self, width=3, text=floor,
command = lambda f=floor: self.pressed(f))
self.button.grid(row=xPos, column =yPos)
yPos = yPos +1
self.QUIT = tk.Button(self, text="QUIT", fg="red",
command=root.destroy).grid(row = xPos, column = yPos)
def pressed(self, index):
print("number pressed", index)
self.button.configure(bg = "red")
root = tk.Tk()
app = Application(master=root)
app.mainloop()
This is all fine and dandy other than when the button is pressed it prints out the correct number, but it changes the background of the last button (number 40) to red, not the one pressed.
If you could let me know what needs correcting that would be great.
Thanks
self.button can only ever reference a single button, and it will always be whatever was assigned to it last. A simple solution is to store the button references in a dict, using floor as the key. Since you're passing that to the callback, you then have everything you need to reconfigure the button:
def createWidgets(self):
...
self.buttons = {}
for floor in floors:
...
self.buttons[floor] = tk.Button(...)
...
def pressed(self, index):
...
self.buttons[index].configure(bg="red")