Multiprocessing code in a game isn't working - python-3.x

My problem is that when I do a multiprocessing code it isn't working for a script I wrote.
The code I am writing is for a clicker game by the way.
Here's the code I tried. What I was hopping it would do was to open a Tk window, which it does, but the part that's wrong is every 0.6 seconds 1 is added to score, but that isn't happening. The part that isn't working is the def autopoints and bellow that
from tkinter import *
import time
import multiprocessing
root = Tk()
c = Canvas(root, width=100, height=100)
score = 0
PointsPerClick = 10
PriceForUpgrade = 100
pointsfromautogen = 1
timeforautogen = 0.6
priceforautogen = 500
pricefortimeautogen = 2000
root.title("Clicker Game")
#this is basically the code for the text in the window
scoretext = StringVar()
scoretext.set(score)
score_label = Label(root, textvariable = scoretext)
upgradecosttext = StringVar()
upgradecosttext.set(PriceForUpgrade + 10)
upgradecost_label = Label(root, textvariable = upgradecosttext)
pointsperclicktext = StringVar()
pointsperclicktext.set(PointsPerClick)
pointsperclicktext_label = Label(root, textvariable = pointsperclicktext)
pointsfromautogentext = StringVar()
pointsfromautogentext.set(pointsfromautogen)
pointsfromautogentext_label = Label(root, textvariable = pointsfromautogentext)
#code for the buttons
def bAaction():
global score
score += PointsPerClick
scoretext.set(score)
def bBaction():
global score
global PriceForUpgrade
if score > PriceForUpgrade:
global PointsPerClick
score -= PriceForUpgrade
PointsPerClick += 5
PriceForUpgrade += 150
upgradecosttext.set(PriceForUpgrade + 1)
pointsperclicktext.set(PointsPerClick)
else:
print('Not enough. Need more score')
def bCaction():
global pointsfromautogen
global priceforautogen
if score > priceforautogen:
pointsfromautogen += 10
pointsfromautogentext.set(priceforautogen + 1)
priceforautogen += 100
#code for the auto generator (aka the part that isn't working)
def autopoints():
time.sleep(0.1)
score + pointsfromautogen
scoretext.set(score)
if __name__ == '__main__':
ap = multiprocessing.Process(target=autopoints)
ap.start()
ap.join()
def bDaction():
if score < pricefortimeautogen:
if timeforautogen > 0.5:
timeforautogen - 0.1
pricefortimeautogen + 2000
else:
print('At max level or not enough points')
#all of the buttons
buttonA = Button(root, text='Points Generator', command=bAaction)
buttonB = Button(root, text='Upgrade', command=bBaction)
buttonC = Button(root, text ='Auto Points Upgrade', command=bCaction)
buttonD = Button(root, text='Speed Up Auto Points', command=bDaction)
#just packing everything needed
buttonA.pack()
buttonB.pack()
buttonC.pack()
buttonD.pack()
score_label.pack()
upgradecost_label.pack()
pointsperclicktext_label.pack()
pointsfromautogentext_label.pack()
c.pack()
root.mainloop()

Related

How can i bind from one function to another in python

Im trying to make my code bind to red only at first
and make red's handler rebind to yellow after red finishes. Im not sure how to do this. Would anyone know how this is done. Because in my code if you run it. It only runs the yellow function instead of red and im pretty sure this is because im overwriting the bind function.
from tkinter import *
import random
root = Tk()
root.geometry("300x300")
score = 0
lb1 = Listbox(root)
e = Entry(root)
def binder1():
root.bind('<Return>', red)
def red(event):
print(e.get())
if e.get() == "red":
lb1.insert("end", "Correct")
binder1
global score
score += 1
mb4['text'] = str("Score ") + str(score)
redcolour = Label(root, text = "What colour is this boi!", fg = "Red")
def yellow(event):
print(e.get())
if e.get() == "yellow":
lb1.insert("end", "Correct")
global score
score += 1
mb4['text'] = str("Score ") + str(score)
root.bind('<Return>', yellow)
yellowcolour = Label(root, text = "What colour is this boi!", fg = "Yellow")
mb4= Menubutton(root, text = str("Score: ") + str(score))
mb4.menu = Menu(mb4)
e.focus_set()
e.pack()
yellowcolour.pack()
redcolour.pack()
lb1.pack()
mb4.pack()
root.mainloop()
It's not clear for me why you want to bind red first.
I would make it more dynamically and let make decision by user input.
like this:
from tkinter import *
def check_input(event):
global score
my_input = e.get()
if my_input == "yellow":
lb1.insert("end", "Correct yellow")
score += 1
mb4['text'] = str("Score ") + str(score)
elif my_input == "red":
lb1.insert("end", "Correct red")
score += 1
mb4['text'] = str("Score ") + str(score)
else:
return None
if __name__ == "__main__":
root = Tk()
root.geometry("300x300")
root.bind('<Return>', check_input)
score = 0
lb1 = Listbox(root)
e = Entry(root)
redcolour = Label(root, text = "What colour is this boi!", fg = "Red")
yellowcolour = Label(root, text = "What colour is this boi!", fg = "Yellow")
mb4= Menubutton(root, text = str("Score: ") + str(score))
e.focus_set()
e.pack()
yellowcolour.pack()
redcolour.pack()
lb1.pack()
mb4.pack()
root.mainloop()

Python Tkinter, can I limit the number of entry?

How can I limit the number of user inputs such that if the user has wrongly tried 5 times already, the system will end immediately?
I have tried to use While loop as usual to achieve. However, the while loop seems to be unable to calculate the number of incorrect input.
Please let me know what should I do. Appreciate
import tkinter as tk
import csv
from tkinter import messagebox
def user_login():
locals()
entry_user_name = entry_usr_name.get()
entry_user_pwd = entry_usr_pwd.get()
with open(r'user.csv', 'r') as user_file
reader = csv.reader(user_file)
user = list(reader)
found = False
count1 = 5
for count in range(len(user)):
if entry_user_name == user[count][0]:
if entry_user_pwd == user[count][1]:
target = count
found = True
break
else: found = False
else: found = False
count1 -= 1
if not found:
tk.messagebox.showerror(title='Error',
message='Invalid password. Please enter again. You have '+str(count1)+ ' left')
if count1 == 0:
tk.messagebox.showerror(title='Error',
line1='Too many input. The system will be ended immediately',
line2='This will be recorded in the security system')
if found:
tk.messagebox.showinfo(title='Successful login',
message='Valid password.')
startpage()
window = tk.Tk()
entry_username = tk.Entry(window, font='Courier 17')
entry_pwd = tk.Entry(window,font='Courier 17')
entry_usr_name.place(x=330, y=245)
entry_usr_pwd.place(x=330, y=345)
login_button= tk.Button(window,
command=user_login) # with some setting
login_button.place(x=440, y=420)
window.mainloop()
You can use a tracking variable to keep record of how many attempts a person has made.
Here is a simple example.
import tkinter as tk
root = tk.Tk()
counter = 1 # tracking variable
tk.Label(root, text="User Name: ").grid(row=0, column=0)
tk.Label(root, text="Password: ").grid(row=1, column=0)
entry_name = tk.Entry(root)
entry_pass = tk.Entry(root)
entry_name.grid(row=0, column=1)
entry_pass.grid(row=1, column=1)
def check_login():
global counter, entry_name, entry_pass
x = entry_name.get()
y = entry_pass.get()
if counter <= 5: # if counter 5 or less then check login info
if x == "Bob" and y == "mypassword":
print("Correct!")
else:
counter += 1 # add 1 to counter
print("Bad login! Please try again")
else:
print("Exceeded max attempt.")
tk.Button(root, text="Login", command=check_login).grid(row=2, column=0, columnspan=2)
root.mainloop()

Tkinter entry boxes

I need to count from a starting input value to an ending value using tkinter entry boxes but the 2 output files are blank except for brackets and I know that the csv outputs work it's just getting the user input that is the issue. Thanks for any help.
There is the current code.
import csv
from tkinter import *
# Variables/Arrays
oddArray = []
evenArray = []
def main():
for i in range(oute1, oute2):
x = i
# Odds
if(x % 2 == 1):
oddArray.append(x)
# Evens
elif(x % 2 == 0):
evenArray.append(x)
with open("odd_labels", "w") as outputFile1:
writer1 = csv.writer(outputFile1)
writer1.writerow([oddArray])
with open("even_labels", "w") as outputFile2:
writer2 = csv.writer(outputFile2)
writer2.writerow([evenArray])
# gui framework
myGui = Tk()
# myGui.geometry('225x50')
# myGui.title("Label Creator")
Label(myGui, text="Starting value: ").grid(row=0)
Label(myGui, text="Ending value: ").grid(row=1)
a = IntVar()
b = IntVar()
e1 = Entry(myGui, textvariable=a).grid(row=0, column=1)
e2 = Entry(myGui, textvariable=b).grid(row=1, column=1)
oute1 = a.get()
oute2 = b.get()
Button(myGui, text="Start", command=main).grid(row=3)
myGui.mainloop()
The problem is how you create your entry fields.
When you use the grid manager at the end of a widget creation then you are unable to use .get() on it because the grid manager is returning None. To avoid this you need to make sure you create your widget first then define where it goes on a separate line.
Change:
e1 = Entry(myGui, textvariable=a).grid(row=0, column=1)
e2 = Entry(myGui, textvariable=b).grid(row=1, column=1)
to:
e1 = Entry(myGui, textvariable=a)
e1.grid(row=0, column=1)
e2 = Entry(myGui, textvariable=b)
e2.grid(row=1, column=1)
I notived your oute1 and oute2 are both only created on the start of the program. You need to move them into a function and it should work fine in your main function.
Try this:
import csv
from tkinter import *
myGui = Tk()
oddArray = []
evenArray = []
Label(myGui, text="Starting value: ").grid(row=0)
Label(myGui, text="Ending value: ").grid(row=1)
a = IntVar()
b = IntVar()
e1 = Entry(myGui, textvariable=a)
e1.grid(row=0, column=1)
e2 = Entry(myGui, textvariable=b)
e2.grid(row=1, column=1)
def main():
oute1 = a.get()
oute2 = b.get()
for i in range(oute1, oute2):
x = i
# Odds
if(x % 2 == 1):
oddArray.append(x)
# Evens
elif(x % 2 == 0):
evenArray.append(x)
with open("odd_labels", "w") as outputFile1:
writer1 = csv.writer(outputFile1)
writer1.writerow([oddArray])
with open("even_labels", "w") as outputFile2:
writer2 = csv.writer(outputFile2)
writer2.writerow([evenArray])
Button(myGui, text="Start", command=main).grid(row=3)
myGui.mainloop()

After text widget opens, tkinter GUI crashes/does not respond whenever its closed

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.

Display of a large amount of data in a Canvas with a Scrollbar

I'm having a problem trying to display a large table in tkinter.
First, I tried to display all label at once in the canvas, but over few hundred rows, the program shut down. So I tried to create a scrollable canvas that updates everytime I scroll: I collect the position of the scrollbar and depending on the position of it, I display the 10 values corresponding.
But I can't get this code working. For now it only displays a black background with the scrollbar on the right.
Here is the code:
from tkinter import *
class Application(object):
def __init__(self, parent):
self.x = []
for i in range(1, 1000):
self.x.append(i)
self.parent = parent
self.mainFrame = Frame(self.parent)
self.mainFrame.pack()
self.canvas = Canvas(self.mainFrame, width = 200, height = 500, bg = "black")
self.canvas.grid(row = 0, column = 0)
self.scroll = Scrollbar(self.mainFrame, orient = VERTICAL, command = self.update)
self.scroll.grid(row = 0, column = 1)
self.canvas.configure(yscrollcommand = self.scroll.set)
self.tabCursor = 0
self.scrollPosition = self.scroll.get()
def update(self):
self.tabCursor = round(self.scrollPosition[0]*len(self.x))
if ((len(self.x) - self.tabCursor) < 10):
self.tabCursor = len(self.x) - 10
for i in range(0, 10): #display 10 values
label = Label(self.canvas, text = str(self.x[tabCursor + i]), width = 50)
label.grid(column = 0, row = i)
if __name__ == '__main__':
root = Tk()
app = Application(root)
root.mainloop()
EDIT :
I finally had time to implement your answer. It looks fine but I can't get the scrollbar working and i don't know why.
class TableauDeDonnees(object):
"Tableau de données -- Onglet Tableau de données"
def __init__(self, data, parent):
self.parent = parent
self.data = data
print(self.data[0], self.data[1])
print(len(self.data[0]), len(self.data[1]))
self.labels = []
self.navigationFrame = Frame(self.parent)
self.canvas = Canvas(self.parent, bg = "black", width = 200, height = 500)
self.mainFrame = Frame(self.canvas)
self.navigationFrame.pack()
print(len(data))
for row in range(50):
for column in range(len(data)):
self.labels.append(Label(self.canvas, text = str(data[column][row])))
for i in range(len(self.labels)):
self.labels[i].grid(row = i // 2, column = i % 2, sticky = NSEW)
self.boutonRetour = Button(self.navigationFrame, text = "Retour", command = lambda: self.move(-2))
self.quickNav = Entry(self.navigationFrame, width = 3)
self.quickNav.bind('<Return>', lambda x: self.move(self.quickNav.get()))
self.boutonSuivant = Button(self.navigationFrame, text = "Suivant", command = lambda: self.move(0))
temp = divmod(len(data[0]), len(self.labels) // 2)
self.pages = temp[0] + (1 if temp[1] else 0)
self.position = Label(self.navigationFrame, text='Page 1 sur ' + str(self.pages))
self.pageCourante = 1
self.boutonRetour.grid(row = 0, column = 0)
self.quickNav.grid(row = 0, column = 1)
self.boutonSuivant.grid(row = 0, column = 2)
self.position.grid(row = 0, column = 3)
self.scroll = Scrollbar(self.parent, orient = VERTICAL, command = self.canvas.yview)
self.canvas.configure(yscrollcommand = self.scroll.set)
self.scroll.pack(side = RIGHT, fill='y')
self.canvas.pack(side = LEFT, fill = 'both')
self.canvas.create_window((4,4), window = self.mainFrame, anchor = "nw", tags = "frame")
self.canvas.configure(yscrollcommand = self.scroll.set)
self.mainFrame.bind("<Configure>", self.update)
self.canvas.configure(scrollregion = self.canvas.bbox("all"))
def update(self, event):
self.canvas.configure(scrollregion = self.canvas.bbox("all"))
def move(self, direction):
if (self.pageCourante == 1 and direction == -2) or (self.pageCourante == self.pages and direction == 0):
return
if direction in (-2, 0):
self.pageCourante += direction + 1
else:
try:
temp = int(direction)
if temp not in range(1, self.pages + 1):
return
except ValueError:
return
else:
self.pageCourante = temp
for i in range(len(self.labels)):
try:
location = str(self.data[i % 2][len(self.labels)*(self.pageCourante - 1) + i])
except IndexError:
location = ''
self.labels[i].config(text = location)
self.position.config(text = 'Page ' + str(self.pageCourante) + ' sur ' + str(self.pages))
I don't understand why the scrollbar isn't working properly. Note, that my parent is a notebook.
Also, there is a problem with the number of items displayed. The number of pages is right but it seems it displays more than it should cause last pages are empty and the last values displayed seems right.
Thank you for your attention
The scrollbar doesn't work by continuously creating new widgets ad infinitum. You were also missing some key parts - unfortunately, Scrollbar isn't as straightforward as most tkinter widgets.
from tkinter import *
class Application(object):
def __init__(self, parent):
self.parent = parent
self.canvas = Canvas(self.parent, bg='black', width = 200, height = 500)
self.mainFrame = Frame(self.canvas)
self.scroll = Scrollbar(self.parent, orient = VERTICAL, command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.scroll.set)
self.scroll.pack(side='right', fill='y')
self.canvas.pack(side='left', fill='both')
self.canvas.create_window((4,4), window=self.mainFrame, anchor="nw", tags="frame")
self.canvas.configure(yscrollcommand = self.scroll.set)
self.mainFrame.bind("<Configure>", self.update)
self.x = []
for i in range(1000):
self.x.append(Label(self.mainFrame, text=str(i)))
self.x[i].grid()
def update(self, event):
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
if __name__ == '__main__':
root = Tk()
app = Application(root)
root.mainloop()
If you'd like to show only a few at a time and provide a forum-like interface, you can use Buttons to navigate between pages. This example allows the user to navigate with Back and Forward buttons, as well as by entering a page number in the box and pressing Enter.
from tkinter import *
class Application(object):
def __init__(self, parent):
self.x = list(range(1000))
self.labels = []
self.parent = parent
self.navigation_frame = Frame(self.parent)
self.canvas = Canvas(self.parent, bg='black', width = 200, height = 500)
self.mainFrame = Frame(self.canvas)
self.navigation_frame.pack()
for i in range(100):
self.labels.append(Label(self.mainFrame, text=str(i)))
self.labels[i].grid()
self.back_button = Button(self.navigation_frame, text='Back', command=lambda: self.move(-2))
self.quick_nav = Entry(self.navigation_frame, width=3)
self.quick_nav.bind('<Return>', lambda x: self.move(self.quick_nav.get()))
self.forward_button = Button(self.navigation_frame, text='Forward', command=lambda: self.move(0))
temp = divmod(len(self.x), len(self.labels))
self.pages = temp[0] + (1 if temp[1] else 0)
self.you_are_here = Label(self.navigation_frame, text='Page 1 of ' + str(self.pages))
self.current_page = 1
self.back_button.grid(row=0, column=0)
self.quick_nav.grid(row=0, column=1)
self.forward_button.grid(row=0, column=2)
self.you_are_here.grid(row=0, column=3)
self.scroll = Scrollbar(self.parent, orient = VERTICAL, command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.scroll.set)
self.scroll.pack(side='right', fill='y')
self.canvas.pack(side='left', fill='both')
self.canvas.create_window((4,4), window=self.mainFrame, anchor="nw", tags="frame")
self.canvas.configure(yscrollcommand = self.scroll.set)
self.mainFrame.bind("<Configure>", self.update)
def update(self, event):
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def move(self, direction):
if (self.current_page == 1 and direction == -2) or (self.current_page == self.pages and direction == 0):
return
if direction in (-2, 0):
self.current_page += direction + 1
else:
try:
temp = int(direction)
if temp not in range(1, self.pages+1):
return
except ValueError:
return
else:
self.current_page = temp
for i in range(len(self.labels)):
try:
location = str(self.x[len(self.labels)*(self.current_page - 1) + i])
except IndexError:
location = ''
self.labels[i].config(text=location)
self.you_are_here.config(text='Page ' + str(self.current_page) + ' of ' + str(self.pages))
if __name__ == '__main__':
root = Tk()
app = Application(root)
root.mainloop()

Resources