I want to make a battle ship game, where each player puts their different boats on an 10 x 10 field. To know where the boats where placed, I want to change a variable from False to True, if the button was clicked. Also the colour of the button should change to black, but if it is already black it shall change back to grey and also the variable should be false again.
In my code I defined a class only for the buttons. master should be a frame. The command 'put command' is needed, as I need these buttons for a second frame with another command. bentuzung means whoever is using it (in my case its either 1 or 2).
So I am searching for a way to assign a variable to a button. Also the code should not become too long.
from tkinter import *
class buttons():
def __init__(self, master, benutzung):
self.button_list = []
for j in range(10):
for m in range(10):
btn = Button(master, text = " ")
btn.grid(row = j, column = m)
self.button_list.append(btn)
self.put_command(benutzung)
def put_command(self, benutzung):
if benutzung == 1:
for x in self.button_list:
x.configure(command = lambda bt = x: self.set_ship(bt))
def set_ship(self, btn):
btn.configure(bg = "black")
So I found out a solution myself. You can just create a new attribute e.g. 'num' and assign a value to it. Then you can get the value by 'btn.num'.
Code:
from tkinter import *
class buttons():
def __init__(self, master, benutzung):
self.button_list = []
for j in range(10):
for m in range(10):
self.btn = Button(master, text = " ", bg = "grey")
self.btn.grid(row = j, column = m)
self.btn.num = 1
self.button_list.append(self.btn)
self.put_command(benutzung)
def put_command(self, benutzung):
if benutzung == 1:
for x in self.button_list:
x.configure(command = lambda bt = x: self.set_ship(bt))
def set_ship(self, btn):
if btn.num == 1:
btn.configure(bg = "black")
btn.num = 0
elif btn.num == 0:
btn.configure(bg = "grey")
btn.num = 1
You can use the textvariable parameter with IntVar().
So your button would be:
num = IntVar()
b = Button(master, text = "str", textvariable = num)
b.pack()
Hopefully this helps!
Related
I created a simple spin box. what I want is, as I increase or
decrease the value in spin box, a new entry should be created or
deleted respectively.
I am not able to get the Int value from the spinbox.
I tried, user_input = int(sb.get()), But this also didn't work.
I am getting this error,
'str' object cannot be interpreted as an integer.
,,,
1st code:
from tkinter import *
root = Tk()
sb_var = IntVar()
sb = Spinbox(root, bg='gray', textvariable=sb_var)
sb.pack()
user_input = sb.get()
for x in range(user_input):
my_entry = Entry(root)
my_entry.pack()
root.mainloop()
,,,
2nd code:
from tkinter import *
root = Tk()
root.geometry("500x400")
def up_or_down(direction):
if direction == "up":
my_entry = Entry(root)
my_entry.pack()
if direction == "down": # I don't know how to code this condition
my_entry.destroy()
tcl_up_or_down = root.register(up_or_down)
sb = Spinbox(root, from_=0, to=100, bg='gray', command=(tcl_up_or_down, '%d'))
sb.pack()
root.mainloop()
'''
I was wondering how to make this code work.I always get 12 in the console.
from tkinter import *
s = 12
root = Tk()
root.geometry("200x200")
root.title("Program")
e = Entry(root)
e.pack()
def clicked():
e.get = s
print(s)
button = Button(root,command=clicked,text="ok")
button.pack()
root.mainloop()
You have to change the function clicked as follows:
def clicked():
s=e.get()
print(s)
There were two errors in your code:
You were trying to assign the value 12 to a function.
You were not calling the function (using parenthesis).
this line here:
e.get = s
says the method of e named get is equally to s.
Which is nonsense. You want s to be equally to what is returned by e.get.
to have something returned you need to invoke this method first.
So the logical right way to do this is by:
s = e.get()
Note that it is a variable in the enclosed namespaces of your function.
To make it global you need to global the variable.
from tkinter import *
s = 12
root = Tk()
root.geometry("200x200")
root.title("Program")
e = Entry(root)
e.pack()
def clicked():
#global s
s = e.get()
print(s)
button = Button(root,command=clicked,text="ok")
button.pack()
b2 = Button(root, text='print', command=lambda:print(s))
b2.pack()
root.mainloop()
I have used .place() instead of .pack() and placed my same entry on the same position as it was place before, but this time if value changes as you click on button OK.
Use e.insert(0,"Value") to insert any value in a entry.
This worked for me. Also let me know did it worked for you as well?
from tkinter import *
s = 12
root = Tk()
root.geometry("200x200")
root.title("Program")
e = Entry(root)
e.place(relx=0.1, rely = 0.1)
def clicked():
e = Entry(root)
e.insert(0, s)
e.place(relx=0.1, rely = 0.1)
button = Button(root,command=clicked,text="ok")
button.place(relx=0.4, rely = 0.2)
root.mainloop()
I am new to tkinter and python, I ran into a problem during my if statements. I am trying to compare the entries to the randomly imported integers and delete the page and give a congrats screen.
I have tried to create text variable but I didn't know how to define it and I was sent to use get command but I'm stuck here now.
I would really appreciate any help and thank you for your time.
I am new to tkinter and python, I ran into a problem during my if statements. I am trying to compare the entries to the randomly imported integers and delete the page and give a congrats screen. I would really appreciate any help and thank you for your time.
from math import *
from tkinter import *
from tkinter import messagebox
# Intro Window Creation
window = Tk()
window.geometry("900x500")
window.title("Welcome To Practice Your Quadratic Equation Solving Skills")
# Picking Difficulty
def Introclick():
window.destroy()
windo = Tk()
windo.geometry("900x500")
windo.title("Difficulty Setting")
label1 = Label(windo, text="Please enter your difficulty setting from ranging 1-3", bg="gray", font="Georgia 22")
label1.pack()
lebel2 = Label(windo, text="1 being the easiest and 3 being the hardest", bg="gray")
lebel2.pack()
def LV1():
def destroy1():
lOL.destroy()
lOL=Tk()
Answer11=Entry(lOL)
Answer12=Entry(lOL)
Answer11.pack()
Answer12.pack()
def crap():
if y > x:
if Answer11.get() == y and Answer12.get() == x:
lOL.destroy()
response = messagebox.askyesno("Great job you got it", "Try again")
else:
print("cry1")
else:
if Answer11.get() == x and Answer12.get() == y:
lOL.destroy()
response = messagebox.askyesno("Great job you got it", "Try again")
else:
print("cry2")
lOL.geometry("900x500")
lOL.title("Level 1")
z = Label(lOL, text="Easiest Difficulty")
z.pack()
lOL.configure(bg="gray")
import random
x = random.randint(1,5)
y = random.randint(1,7)
b = x + y
c = x * y
FunctionOut1=Label(lOL, text="Quadratic Equation \n" +"x^2 + " + str(b) + "x + " + str(c), bg="gray", fg="green" )
FunctionOut1.pack()
Dead = Button(lOL, text="Exit", command=destroy1)
Dead.pack()
LAB11 = Label(lOL, text="Input both Answers, Integers Only")
LAB11.pack()
FAnswer1=Button(lOL, command=crap,text="Submit Answer")
FAnswer1.pack()
# The buttons that allow to pick the difficulty
B1 = Button(windo,text="Level 1", width=(20), command=LV1, fg="green", bg="gray")
B2 = Button(windo,text="Level 2", width=(20), command=LV2, fg="yellow", bg="gray")
B3 = Button(windo,text="Level 3", width=(20), command=LV3, fg="red", bg="gray")
B1.pack()
B2.pack()
B3.pack()
windo.configure(bg="gray")
Introbutt = Button(window, text="Let's Start!", padx=50, pady=50, command=Introclick, fg="blue", bg="black")
Introbutt.pack()
window.mainloop()
I need it so that when I press the button it will switch between 2 labels, when I have managed to create a second statement now I need to be able to switch between the two. I have no clue what to do to get this to work, please help
def changeLabelText():
z = True
print(z)
if z == True:
print("The current text is", l1['text'])
z = False
return z
elif z == False:
print("The current text is", l12['text'])
z = True
return z
l1['text'] = "Changed Text"
l12['text'] = "Text"
b1 = Button(app, text="Change Text", command=changeLabelText)
l1 = Label(app, text="Text")
l12 = Label(app, text="New Text")
It's unclear for what reason you're using those redundant conditions, but here's a small example how you can switch labels (technically - a text options as your function's name claims):
try:
import tkinter as tk
except ImportError:
import Tkinter as tk
def changeLabelText():
l1['text'], l2['text'] = l2['text'], l1['text']
app = tk.Tk()
b1 = tk.Button(app, text="Change Text", command=changeLabelText)
l1 = tk.Label(app, text="Text")
l2 = tk.Label(app, text="New Text")
l1.pack()
l2.pack()
b1.pack()
app.mainloop()
Right now, after I press the 'Time Range' button and call the calculateTime function, the text widget would appear with the results that I've inserted into it. However, after that, whenever I close the GUI window, the program would freeze and I'll have to forced quit it. This is my code:
import tkinter
from tkinter import *
import math
from tkinter import messagebox
class MyClass(tkinter.Frame):
def __init__(self, *args, **kwargs):
tkinter.Frame.__init__(self, *args, **kwargs)
#Setting up frame and widgets
vcmd1 = (self.register(self.__vcmd1), '%P', '%S')
vcmd2 = (self.register(self.__vcmd2), '%P')
vcmd3 = (self.register(self.__vcmd3), '%P', '%S')
label_iso = Label(self,text="Isotope A, Element")
label_vol = Label(self, text="Voltage")
label_range = Label(self, text="Charge Range")
label_iso.grid(row=0, column=0, sticky=E)
label_vol.grid(row=1, column=0, sticky=E)
label_range.grid(row=2, column=0, sticky=E)
self.entry1 = tkinter.Entry(self, validate="key", validatecommand=vcmd1)
self.entry2 = tkinter.Entry(self, validate="key", validatecommand=vcmd2)
self.entry3 = tkinter.Entry(self, validate="key", validatecommand=vcmd3)
self.entry1.grid(row=0, column=1)
self.entry2.grid(row=1, column=1)
self.entry3.grid(row=2, column=1)
def __vcmd1(self, P, S):
validString = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM,1234567890'
if not S in validString:
return False
if "," in P:
if (len(P) - 1) > len(P.replace(",","")):
return False
messagebox.showinfo("Error", "Expected Form: ex. 133,Cs")
else:
return True
def __vcmd2(self, P):
if P == '':
return True
try:
float(P)
return True
except ValueError:
messagebox.showinfo("Error", "Entry is not a float or integer")
return False
def __vcmd3(self, P, S):
if "," in P:
if len(P.split(",")) > 2:
return False
a = P.split(",")[0]
b = P.split(",")[1]
if a != '' and b != '':
try:
int(a)
int(b)
except ValueError:
messagebox.showinfo("Error", "Expected form: ex. 1,12")
return False
else:
return True
class TimeGenerator:
def __init__(self,master):
frame = MyClass(master)
frame.grid(columnspan=2)
button = Button(root, text='Time Range', command=self.calculateTime)
button.grid(row=3, columnspan=2)
self.text = Text(root)
self.iso = frame.entry1
self.vol = frame.entry2
self.r = frame.entry3
def calculateTime(self):
x = 5
if self.r.get() == "" or self.iso.get() == "" or self.vol.get() == "":
messagebox.showinfo("Error", "No field can be empty")
return None
self.iso = self.iso.get().replace(" ", "")
list = []
for e in self.iso.split(","):
list.append(e)
f = open("/Users/LazyLinh/PycharmProjects/mass.mas12.txt", "r")
i = 0
while (i < 40):
header = f.readline()
i += 1
self.mass = 0
#iterate through text file
for line in f:
line = line.strip()
columns = line.split()
if (list[0] == columns[3]):
if (list[1].lower() == columns[4].lower()):
if (len(columns) == 16):
self.mass = float(columns[13].replace("#","")) + float(columns[14].replace("#",""))
else:
self.mass = float(columns[12].replace("#","")) + float(columns[13].replace("#",""))
#Calculation
self.r = self.r.get().replace(" ", "")
tup = tuple(int(x) for x in self.r.split(","))
list = []
for q in range(tup[0], tup[1] + 1):
y = (x * math.sqrt(self.mass * 1.6605402e-27 / (2 * q * float(self.vol.get())))) * 10e6
list.append(y)
i = tup[0]
#inserting to text widget
for time in list:
self.text.insert("end", "%d: %s\n" % (i, time))
i = i + 1
self.text.pack()
root = Tk()
b = TimeGenerator(root)
root.mainloop()
I've tried to searched up on this topic, but I'm not really using any weird update() function, and text shows up after the function is finished, so how likely that it is an event loop problem? Am I also doing something wrong that could cause this problem?
Thank you!
You have widgets in the root window that use both pack and grid. You cannot do this. Within a given container (root window, frame, etc) you can use one or the other, but not both.
The reason your program freezes is due to pack and grid fighting to gain control of the layout. When you pack the text widget it causes a change in the size and/or position of other widgets in the root window. That triggers grid to try to re-layout the widgets it is responsible for. This triggers pack to try to re-layout the widgets it is responsible for, and on and on until the end of time.
My guess is that you need to use grid with self.text since you use grid everywhere else.