I am creating a software for a driving school but I'm limited to what plugins are available to me. I also have to use text files for the databases rather than being able to use SQL or the like. I can't seem to figure out this next stage.
This is the scenario:
Each instructor has a unique login, and they can choose to book a lesson onto the calendar/timetable, or just simply view it. The issue is that I'm unsure how to store the data without creating a very large number of text files, because originally my idea was that each instructor would be able to view their own individual calendar/timetable (linked together via their unique login) however because of how the calendar works, each week would require it's own text file and then that number of text files would be multiplied by the total number of instructors.
The code for the calendar and timetable is(not perfectly working but the main principles are there):
import sys
import re
from tkinter import *
import tkinter.messagebox as box
import tkinter.font as Font
import time
import calendar
#from tkinter import font
from tkinter import ttk
def Calendar():
def mainTimetable():
#root1 = Tk()
#frame = Frame(root1)
days = ["","Mon","Tue","Wed","Thur","Fri","Sat","Sun"]
hours = ["","08:00","09:00","10:00","11:00","12:00","13:00","14:00","15:00",
"16:00","17:00","18:00"]
class WrappedButtons:
def __init__(self, master, **kwargs):
self.button = Button(master,font=('Courier'),fg='#333333',bg='#CCCCCC', **kwargs)
self.name = ''
def nameToggle(self):
if not self.name:
self.name = nameEntry.get()
else:
self.name = ''
self.button.config(text=self.name)
def subTimetable():
global nameEntry
popup = Toplevel()
#popup.title('Timetable')
for x in range(12):
Label(popup,font=('Courier'),fg='#333333',bg='#CCCCCC', text=hours[x]).grid(row=x,column=0)
for x in range(8):
Label(popup,font=('Courier'),fg='#333333',bg='#CCCCCC',text=days[x]).grid(row=0,column=x)
if x < 7: # this avoids an extra column of buttons
for y in range(11):
temp = WrappedButtons(popup,width=20)
temp.button.config(command=temp.nameToggle)
temp.button.grid(row=y+1,column=x+1)
Label(popup,text = "Enter the name of pupil and click the slot you wish to fill/remove: ")\
.grid(row=13,column=0,columnspan=4)
nameEntry = Entry(popup,width=40)
nameEntry.grid(row=13,column=4,columnspan=2)
backButton = Button(popup,font=('Courier'),fg='#333333',bg='#CCCCCC',text='Back',command= popup.destroy)#lambda: [f() for f in[popup.destroy,ownermenu]]).grid(row=13,column=6) # Add functionality to return to user page
submitButton = Button(popup,text='Submit Data').grid(row=13,column=7)
menubar = Menu(popup)
filemenu = Menu(menubar,tearoff=0)
filemenu.add_command(label='Home',command=lambda:[f() for f in [popup.destroy,home1]])
filemenu.add_separator()
filemenu.add_command(label='Exit',command=popup.destroy)
menubar.add_cascade(label='Page',menu=filemenu)
popup.config(menu=menubar)
popup.configure(bg='#333333')
#popup.overrideredirect(True)
#popup.geometry("{0}x{1}+0+0".format(popup.winfo_screenwidth(), popup.winfo_screenheight()))
subTimetable()
#root.mainloop()
root = Tk()
root.title('Calendar')
root.configure(bg='#333333')
permanentFrame,newFrame = Frame(root), Frame(root)
permanentFrame.pack(side='top')
newFrame.pack(side='top')
months = {1: 31, 2: 28, 3: 31, 4: 30, 5: 31, 6: 30, 7: 31, 8: 31, 9: 30, 10: 31, 11: 30, 12: 31}
lbMonths = Label(permanentFrame,text='Months: ',fg='#333333',bg='#CCCCCC')
lbMonths.pack()
dropMonths = ttk.Combobox(permanentFrame, values=list(months.keys()))
dropMonths.pack()
class ButtonsWrap:
def __init__(self,master,month,day, **kwargs):
self.button = Button(master,**kwargs)
self.monthInd = month-1
self.dayInd = day-1
self.toplevel = False
self.thing = None
def popClose(self):
self.thing.destroy()
self.toplevel = False
self.thing = None
def popup(self):
if not self.toplevel:
self.thing = Toplevel()
self.toplevel = True
#Label(self.thing, command=mainTimetable).pack()
self.popClose
mainTimetable()
self.thing.protocol("WM_DELETE_WINDOW",self.popClose) #Add back in when 'back' functionality is complete
buttons = []
def makeCalendar(blank):
curMonth = int(dropMonths.get())
for i in buttons:
if i.thing:
i.thing.destroy()
for i in newFrame.slaves():
i.destroy()
rows = [Frame(newFrame) for i in range(5)]
[i.pack() for i in rows]
curDay = 1
for i in range(35):
if len(rows[0].slaves()) == 7:
rows.pop(0)
temp = ButtonsWrap(rows[0], curMonth,curDay,text='',height=1,width=2)
temp.button.pack(side='left')
buttons.append(temp)
if curDay <= months[curMonth]:
temp.button.config(text=curDay,command=temp.popup)
curDay += 1
dropMonths.bind('<<ComboboxSelected>>', makeCalendar)
menubar = Menu(root)
filemenu = Menu(menubar,tearoff=0)
filemenu.add_command(label='Home',command=lambda:[f() for f in [root.destroy,home1]])
filemenu.add_separator()
filemenu.add_command(label='Exit',command=root.destroy)
menubar.add_cascade(label='Page',menu=filemenu)
root.config(menu=menubar)
root.overrideredirect(True)
root.geometry("{0}x{1}+0+0".format(root.winfo_screenwidth(), root.winfo_screenheight()))
root.mainloop()
Calendar()
It works by allowing the instructor to type into the timetable, and then my aim is to save the timetable so that it can be referenced in the future (so it doesn't reset every time it's closed). What would be an efficient way of achieving my goal?
Feel free to ask questions if I've poorly explained the problem, as I feel I may have.
Related
Hello dear programmers,
I have generated an EXE with pyinstaller. However, I would like this EXE to be valid for only 6 months so that users have to re-download a improved EXE with updates from a download-center. Is there any way to add this in the program code?
Unfortunately I can't include a standard update function because the users often don't have internet.
I am curious about your suggestions. Thanks a lot guys! I've attached a small snippet of the program below.
import tkinter as tk
from tkinter import ttk
class Win1:
def __init__(self, master):
self.master = master
self.topFrame = tk.Frame(self.master)
self.topFrame.grid(row=0, column=0, sticky='news', ipady = 5)
self.B_GapFrame = tk.Frame(self.master)
self.master.resizable(False, False)
self.gapType = tk.StringVar(self.master)
self.choiceGap = ['RBC, TUR']
self.gapType.set('') # set the default option
self.ctngMenu = tk.OptionMenu(self.topFrame, self.gapType, *self.choiceGap, command=self.choose_gap_handle)
self.ctngMenu.config(width=40)
self.LabelGap = tk.Label(self.topFrame, text="Select TYPE")
self.LabelGap.grid(row = 3, column = 0,sticky = "W")
self.ctngMenu.grid(row = 3, column =2,sticky = "W", columnspan = 3)
self.frameVar = tk.StringVar(self.master)
self.choiceFrame = "Test"
self.frameVar.set('') # set the default option
self.frameMenu = ttk.Combobox(self.topFrame, values= self.choiceFrame, state = "readonly", justify = "center", textvariable = self.frameVar, width = 12)
self.frameMenu.grid(row = 1, column =2,sticky = "W", pady = 7, columnspan = 3)
self.LabelFrame = tk.Label(self.topFrame, text="Select TUR ")
self.LabelFrame.grid(row = 1, column = 0,sticky = "W",pady =7)
def choose_gap_handle(self, selected_Gap):
if selected_Gap == 'RBC, TUR':
self.B_GapFrame.tkraise()
self.B_GapFrame.grid(row=2, column=0, sticky='news')
root = tk.Tk()
root.geometry("+50+50")
app = Win1(root)
root.mainloop()
It all depends how 'cruel' you want to be.
One option might be to add a hard coded date in your code like
import datetime
RLS_DATE = datetime.date(2021, 02, 24)
and then before your main code section something like:
if datetime.date.today() - RLS_DATE > 7 * 30: # about 7 months
# as #TheLizzard suggested delete the executable.
# You might do this only if running under
# py2exe to avoid deleting your own source code
if getattr(sys, 'frozen', False):
os.remove(sys.argv[0])
elif datetime.date.today() - RLS_DATE > 6 * 30: # about 6 months
# write your own coded, that shows just a popup and lets the user
# continue using the app.
If you don't want to hardcode the release date, you could write a smarter script to create your executable and add some data for py2exe, that contains the date at which you compiled the executable.
What I mean with being cruel.
Either just show a popup, that the user should update,
or add a popup and block the user interface for x seconds.
The delay might increase the longer the user doesn't update
or just exit the program
or even delete the program
Of course all these options are not safe.
This is just for standard users.
If somebody insists to run your program, he can modify the generated executable to ignore the date.
You can save your app first launch time to local file and then compare it with current time.
import os
import time
import tempfile
import tkinter as tk
EXPIRATION_TIME_SEC = 100
class App(object):
def __init__(self):
config = os.path.join(tempfile.gettempdir(), 'config.txt')
self.start_time = time.time()
if os.path.isfile(config):
with open(config, 'r') as f:
self.start_time = int(float(f.read()))
else:
with open(config, 'w') as f:
f.write(f'{self.start_time}')
self.root = tk.Tk()
self.label = tk.Label(self.root)
self.label.pack()
self.update_label()
self.root.mainloop()
def update_label(self):
if time.time() - self.start_time > EXPIRATION_TIME_SEC:
self.root.quit()
self.label.configure(text=f'Expired in: {int(self.start_time+EXPIRATION_TIME_SEC-time.time())} sec.')
self.root.after(1000, self.update_label)
App()
Output:
I'm new in Python and I'm currently trying to use tkinter as first GUI. I was used to making it without classes. And it is my first time to use import tkinter as tk instead of import *
import tkinter as tk
def update():
pass
#Game.statsFrame #doesn't work Game.statsFrame.stat1_amountLabel too
#Game.stat1_amountLabel #doesnt work < want to use update_idletasks() or
#just type new cofnig...
#just errors like: "Game' has no attribute 'statsFrame" etc #Game
class character:
name = ""
experience = 0
level = 0
gold = 0
stat1 = 0
stat2 = 0
stat3 = 0
stat4 = 0
stat5 = 0
avaiblePoints = 0
def add_stat1(self):
if self.avaiblePoints >= 1:
self.stat1 += 1
self.avaiblePoints -= 1
update()
else:
pass
def add_stat2(self):
if self.avaiblePoints >= 1:
self.stat2 += 1
self.avaiblePoints -= 1
update()
[...]
myChar = character()
myChar.avaiblePoints = 3
class Game:
def __init__(self, parent):
self.myParent = parent
self.myGame = tk.Frame(parent)
self.myGame.grid()
self.statsFrame = tk.Frame(self.myGame).grid()
self.stat1Label = tk.Label(self.statsFrame)
self.stat1Label.config(text="Strength:")
self.stat1Label.grid(column=1, row=1)
self.stat1_amountLabel = tk.Label(self.statsFrame)
self.stat1_amountLabel.config(text=myChar.stat1)
self.stat1_amountLabel.grid(column=2, row=1)
self.add_stat1Button = tk.Button(self.statsFrame)
self.add_stat1Button.config(text="+", command=myChar.add_stat1)
self.add_stat1Button.grid(column=3, row=1)
root = tk.Tk()
myapp = Game(root)
root.mainloop()
But I can't get to (for example) stat1Label and change text inside it and after it use update_idletasks(). It's like it doesnt exist. Errors shows that Game has not atributtes like stat1Label etc.
I want to use it becouse I have read that __init__ method is better and I want to swtich between pages. I have no idea, when I wasn't using class in tkinter some things (like this) was easier and had no problems. I'm very confused guys.
It's excellent that you're using import tkinter as tk instead of the dreaded "star" import, and that you're trying to organize your code with classes. It can be a little confusing at first, but it makes your code more modular, which helps enormously, especially when the GUI gets large.
There are a few problems with your code. The most important one is this line:
self.statsFrame = tk.Frame(self.myGame).grid()
The .grid method (and .pack and .place) all return None. So that line saves None to self.statsFrame, not the Frame widget. So when you later try to do stuff with self.statsFrame it won't do what you expect.
Another problem is that the text attribute of your self.stat1_amountLabel doesn't track the value of myChar.stat1, so when you change the value of myChar.stat1 you need to explicitly update the Label with the new value. Alternatively, you could use the textvariable attribute with an IntVar to hold the character's stat. See the entry for textvariable in the Label config docs for info.
Your character class has a whole bunch of attributes like name, experience etc as class attributes. That's not a good idea because class attributes are shared by all instances of a class. But you probably want each character instance to have their own instance attributes. So you should give character an __init__ method where you set those attributes. OTOH, it's ok to use class attributes for default values that get overridden by instance attributes.
Anyway, here's a repaired version of your code with a Button that updates the Strength stat. I've put the stats in a list, rather than having a bunch of separate named stats that would have to be managed separately. And I've given Game a make_stat method so you can easily add rows for the other stats.
import tkinter as tk
class Character:
def __init__(self, availablePoints=0):
self.name = ""
self.experience = 0
self.level = 0
self.gold = 0
self.stats = [0] * 5
self.availablePoints = availablePoints
def add_stat(self, idx):
if self.availablePoints >= 1:
self.stats[idx] += 1
self.availablePoints -= 1
class Game:
def __init__(self, parent):
self.myParent = parent
self.myGame = tk.Frame(parent)
self.myGame.grid()
self.statsFrame = tk.Frame(self.myGame)
self.statsFrame.grid()
self.make_stat("Strength:", 0, 0)
def make_stat(self, text, idx, row):
label = tk.Label(self.statsFrame, text=text)
label.grid(column=1, row=row)
amount = tk.Label(self.statsFrame, text=myChar.stats[idx])
amount.grid(column=2, row=row)
def update():
myChar.add_stat(idx)
amount["text"] = myChar.stats[idx]
button = tk.Button(self.statsFrame, text="+", command=update)
button.grid(column=3, row=row)
myChar = Character(3)
root = tk.Tk()
myapp = Game(root)
root.mainloop()
This code is still not ideal, but it's an improvement. ;) For example, it would be good to give Game a method for creating new characters, rather than creating them in the global context. You could store them in a dict attribute of Game, using the character's name as the key.
Here's a new version that works on separate named stat attributes. As I said in the comments, doing it this way is more complicated (and less efficient) than using a list to hold the stats.
import tkinter as tk
class Character:
def __init__(self, availablePoints):
self.name = ""
self.experience = 0
self.level = 0
self.gold = 0
self.stat1 = 0
self.stat2 = 0
self.stat3 = 0
self.stat4 = 0
self.stat5 = 0
self.availablePoints = availablePoints
class Game:
def __init__(self, parent):
self.myParent = parent
self.myGame = tk.Frame(parent)
self.myGame.grid()
self.statsFrame = tk.Frame(self.myGame)
self.statsFrame.grid()
self.make_stat("Strength:", "stat1", 1, 1)
def make_stat(self, text, stat, column, row):
label = tk.Label(self.statsFrame, text=text)
label.grid(column=column, row=row)
amount = tk.Label(self.statsFrame, text=getattr(myChar, stat))
amount.grid(column=(column+1), row=row)
def update():
if myChar.availablePoints >= 1:
v = getattr(myChar, stat) + 1
setattr(myChar, stat, v)
myChar.availablePoints -= 1
amount["text"] = v
button = tk.Button(self.statsFrame, text="+", command=update)
button.grid(column=(column+2), row=row)
myChar = Character(5)
root = tk.Tk()
myapp = Game(root)
root.mainloop()
I took a network programming class this semester and my project consists in a quiz game, with a simple graphic interface.
I would like to display the question and it will be like that the player clicks on a button to answer.
The problem is, I don't know how to code the "wait for click" in python, the code is being executed until the end.
I tried to use a while with a boolean condition (if not clicked then wait) and this was waiting as I wanted, but there was no display of the graphic interface...
Here is my code, I am kind of desperate
Thanks for the help in advance.
import numpy as np
from numpy.random import shuffle
from random import randint
import socket
import time
from Tkinter import *
from time import clock
class Interface(Frame):
def __init__(self, fenetre, **kwargs):
Frame.__init__(self, fenetre, width=768, height=576, **kwargs)
self.pack(fill=BOTH)
#DATAS
self.question = ["What is the capital of France?","In which continent is Argentina?","Where is Big Ben?","What is the most densely populated country?","What language do they speak in Brazil?"]
self.answer = [["Paris","London","Berlin","Madrid"],["South America","Africa","Europe","Asia"],["London","New York","Mexico","Jakarta"],["China","India","USA","Indonesia"],["Portuguese","Spanish","French","English"]]
self.question_done=[0]*(len(self.question))
#SCORE, stored as a list score[0]--> score of the player 1
self.score=[0]
# Creation of widgets
self.message = Label(self, text="Welcome to the Bule Game")
self.message.pack()
self.bouton_quitter = Button(self, text="Quitter", command=self.quit)
self.bouton_quitter.pack(side="bottom")
#Total number of questions
self.totalnb = 3
self.bouton_a1 = Button(self, text="",command = self.checkAnswer)
self.bouton_a1.pack(side="left")
self.bouton_a2 = Button(self, text="",command = self.checkAnswer)
self.bouton_a2.pack(side="left")
self.bouton_a3 = Button(self, text="",command = self.checkAnswer)
self.bouton_a3.pack(side="left")
self.bouton_a4 = Button(self, text="",command = self.checkAnswer)
self.bouton_a4.pack(side="left")
for i in range(self.totalnb):
#Choose the question
self.nbq = self.chooseQuestion(self.question)
print("the number is {}".format(self.nbq))
self.message["text"] = self.question[self.nbq]
#answers possible
self.ans=self.displayA(self.question,self.answer,self.nbq)
self.play()
def play(self):
#update buttons
self.bouton_a1["text"]=self.ans[0]
self.bouton_a1["command"]=(lambda: self.checkAnswer(self.answer,self.ans[0],self.nbq,self.score))
self.bouton_a2["text"]=self.ans[1]
self.bouton_a2["command"]=(lambda: self.checkAnswer(self.answer,self.ans[1],self.nbq,self.score))
self.bouton_a3["text"]=self.ans[2]
self.bouton_a3["command"]=(lambda: self.checkAnswer(self.answer,self.ans[2],self.nbq,self.score))
self.bouton_a4["text"]=self.ans[3]
self.bouton_a4["command"]=(lambda: self.checkAnswer(self.answer,self.ans[3],self.nbq,self.score))
#CHOOSE RANDOMLY A QUESTION IN THE LIST
def chooseQuestion(self,question):
k = randint(0,len(question)-1)
if (self.question_done[k]!=0):
while(self.question_done[k]!=0):
k = randint(0,len(question)-1)
self.question_done[k]=1
else :
self.question_done[k]=1
#print(question[k])
#displayA(question,answer,k)
#print("le num interne est {} ".format(k))
return k
#SHOW THE POSSIBLE ANSWERS
def displayA(self,question,answer,i):
a = answer[i]
order = np.arange(4)
shuffle(order) #create list from 1 to 4 in different order --> to print the answers in random order
a_display = [a[order[0]],a[order[1]],a[order[2]],a[order[3]]]
return a_display
#CHECK IF GOOD ANSWER OR NOT
def checkAnswer(self,answer,agiven,qnb,score):
print("CHECK")
test = False
if(answer[qnb][0] in agiven):
test = True
score[0]=score[0]+1
print("the answer is {}".format(test))
return test
def quit(self):
self.message["text"] = "The score is {}.".format(self.score)
fenetre = Tk()
interface = Interface(fenetre)
interface.mainloop()
If you want the program to wait for a button click, then you should put the next code to execute in the button callback command. I moved the question asking code into a method named nextQuestion, which is called in checkAnswer after a condition is satisfied. I have also made a couple of minor improvements with enough comments to explain them (I think).
Here is the complete code:
import numpy as np
from numpy.random import shuffle
from random import randint
import socket
import time
from Tkinter import *
from time import clock
class Interface(Frame):
def __init__(self, fenetre, **kwargs):
Frame.__init__(self, fenetre, width=768, height=576, **kwargs)
self.pack(fill=BOTH)
#DATAS
self.question = ["What is the capital of France?","In which continent is Argentina?","Where is Big Ben?","What is the most densely populated country?","What language do they speak in Brazil?"]
self.answer = [["Paris","London","Berlin","Madrid"],["South America","Africa","Europe","Asia"],["London","New York","Mexico","Jakarta"],["China","India","USA","Indonesia"],["Portuguese","Spanish","French","English"]]
self.question_done=[0]*(len(self.question))
#SCORE, stored as a list score[0]--> score of the player 1
self.score=[0]
# Creation of widgets
self.message = Label(self, text="Welcome to the Bule Game")
self.message.pack()
self.bouton_quitter = Button(self, text="Quitter", command=self.quit)
self.bouton_quitter.pack(side="bottom")
self.bouton_start = Button(self, text="Start", command=self.startQestion)
self.bouton_start.pack()
#Total number of questions
self.totalnb = 3
# Variable to keep track of how many questions have been asked
self.questions_asked = 1
def startQestion(self):
# Create buttons before you ask the first questions
self.bouton_a1 = Button(self, text=" ",command = self.checkAnswer)
self.bouton_a1.pack(side="left")
self.bouton_a2 = Button(self, text=" ",command = self.checkAnswer)
self.bouton_a2.pack(side="left")
self.bouton_a3 = Button(self, text=" ",command = self.checkAnswer)
self.bouton_a3.pack(side="left")
self.bouton_a4 = Button(self, text=" ",command = self.checkAnswer)
self.bouton_a4.pack(side="left")
self.bouton_start.pack_forget() #Remove the start button
self.nextQuestion() # ask question
def nextQuestion(self):
#Choose the question
self.nbq = self.chooseQuestion(self.question)
print("the number is {}".format(self.nbq))
self.message["text"] = self.question[self.nbq]
#answers possible
self.ans=self.displayA(self.question,self.answer,self.nbq)
self.play()
def play(self):
#update buttons
self.bouton_a1["text"]=self.ans[0]
self.bouton_a1["command"]=(lambda: self.checkAnswer(self.answer,self.ans[0],self.nbq,self.score))
self.bouton_a2["text"]=self.ans[1]
self.bouton_a2["command"]=(lambda: self.checkAnswer(self.answer,self.ans[1],self.nbq,self.score))
self.bouton_a3["text"]=self.ans[2]
self.bouton_a3["command"]=(lambda: self.checkAnswer(self.answer,self.ans[2],self.nbq,self.score))
self.bouton_a4["text"]=self.ans[3]
self.bouton_a4["command"]=(lambda: self.checkAnswer(self.answer,self.ans[3],self.nbq,self.score))
#CHOOSE RANDOMLY A QUESTION IN THE LIST
def chooseQuestion(self,question):
k = randint(0,len(question)-1)
if (self.question_done[k]!=0):
while(self.question_done[k]!=0):
k = randint(0,len(question)-1)
self.question_done[k]=1
else :
self.question_done[k]=1
#print(question[k])
#displayA(question,answer,k)
#print("le num interne est {} ".format(k))
return k
#SHOW THE POSSIBLE ANSWERS
def displayA(self,question,answer,i):
a = answer[i]
order = np.arange(4)
shuffle(order) #create list from 1 to 4 in different order --> to print the answers in random order
a_display = [a[order[0]],a[order[1]],a[order[2]],a[order[3]]]
return a_display
#CHECK IF GOOD ANSWER OR NOT
def checkAnswer(self,answer,agiven,qnb,score):
print("CHECK")
test = False
if(answer[qnb][0] in agiven):
test = True
score[0]=score[0]+1
print("the answer is {}".format(test))
#Check to see if the maximum number of questions has been asked already
if self.questions_asked < self.totalnb:
self.nextQuestion() # Ask the next question if less number of questions has been asked
self.questions_asked += 1 # Update the number of questions that has been asked
# If maximum number of questions is asked, display end message and remove answer buttons
else:
self.message["text"] = "End of Qestion"
self.bouton_a1.pack_forget()
self.bouton_a2.pack_forget()
self.bouton_a3.pack_forget()
self.bouton_a4.pack_forget()
#return test
def quit(self):
self.message["text"] = "The score is {}.".format(self.score)
fenetre = Tk()
interface = Interface(fenetre)
interface.mainloop()
I am working on a Human machine interface design...
I have created an array of labels...I have used same label and properties for all the labels in the array, but when i executive my code, size of the labels do not match with each other....
This is my code....
from tkinter import *
import time
root = Tk()
class Clock:
def __init__(self):
self.time1 = ''
self.time2 = time.strftime('%H:%M:%S')
self.mFrame = Frame()
self.mFrame.pack(side=TOP,fill=X)
self.bottomFrame = Frame()
self.bottomFrame.pack(side=BOTTOM,fill=BOTH)
root.title('HUMAN MACHINE INTERFACE')
self.company_name=Label(self.mFrame, text='Host Company Name', font=('Arial',24,'bold','underline'),bg='white',relief=RAISED).pack(fill=X)
self.machine_name=Label(self.mFrame, text='Machine name', font=('Arial',24,'bold','underline'),bg='yellow',relief=RAISED).pack(fill=X)
self.my_company_name=Label(self.mFrame, text='SYNERGY AUTOMATION', font=('Arial',24,'bold','underline'),relief=SUNKEN).pack(side=LEFT)
self.watch = Label(self.mFrame, text=self.time2, font=('times',24,'bold'),relief=SUNKEN)
self.watch.pack(side=RIGHT)
self.clock() #first call it manually
num=['1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16',]
r=0
c=0
for i in num:
Label(self.bottomFrame, text=i,bg='red',fg='white',font=(34),padx=50,pady=20,relief=SUNKEN).grid(row=r,column=c)
c = c + 1
if c == 4 or c == 8:
c=0
r=r+1
def clock(self):
self.time2 = time.strftime('%H:%M:%S')
self.watch.configure(text=self.time2)
self.mFrame.after(200, self.clock) #it'll call itself continuously
obj1 = Clock()
root.mainloop()
You aren't using the sticky option when you call grid. Without it, the labels will only be big enough to contain the text. If you want them to fill the table cells, use something like sticky=N+S+E+W
Label(...).grid(... sticky=N+S+E+W)
By the way,
self.company_name=Label(...).pack(fill=X)
You are setting self.company_name to None because that's what pack returns. A tkinter best practice is to separate the creation of the widget from laying it out on the screen:
self.company_name=Label(...)
...
self.company_name.pack(fill=X)
This is the code for the function I'm using to start the main part of the program, however I want some sort of loop or something which creates ten questions, but waits for an input from the Entry box before moving onto the next question.
Any ideas?
def StartGame():
root = Tk()
root.title("Maths Quiz - Trigonometry and Pythagoras' Theorem | Start The Game")
root.geometry("640x480")
root.configure(background = "gray92")
global AnswerEntry
TotScore = 0
Count = 0
AnswerReply = None
WorkingArea = Text(root, width = 70, height = 10, wrap = WORD).place(x = 38, y = 100)
n = GetRandomNumber()
Angle,Opposite,Adjacent,Hypotenuse = Triangle()
Question,RealAnswer = QuestionLibrary(Opposite,Adjacent,Hypotenuse,Angle,n)
AskQuestion = Label(root, text = Question, wraplength = 560).place(x = 48, y = 300)
PauseButton = ttk.Button(root, text = "Pause").place(x = 380, y = 10)
HelpButton = ttk.Button(root, text = "Help", command = helpbutton_click).place(x = 460, y = 10)
QuitButton = ttk.Button(root, text = "Quit", command = root.destroy).place(x = 540, y = 10)
AnswerEntry = Entry(root)
AnswerEntry.place(x = 252, y = 375)
SubmitButton = ttk.Button(root, text = "Submit", command = submit_answer).place(x = 276, y = 400)
TotScore,AnswerReply = IsAnswerCorrect(Answer,RealAnswer)
ScoreLabel = ttk.Label(root, text = TotScore).place(x = 38, y = 10)
AnswerReplyLabel = ttk.Label(root, text = AnswerReply).place(x = 295, y = 440)
root.mainloop()
I want the loop to start after the AnswerReply = None
You don't want a loop. The only really important loop inside a GUI should be the mainloop(), handling signal and executing callbacks.
Example:
try:
import Tkinter as Tk
except ImportError:
import tkinter as Tk
class QAGame(Tk.Tk):
def __init__(self, questions, answers, *args, **kwargs):
Tk.Tk.__init__(self, *args, **kwargs)
self.title("Questions and answers game")
self._setup_gui()
self._questions = questions[:]
self._answers = answers
self._show_next_question()
def _setup_gui(self):
self._label_value = Tk.StringVar()
self._label = Tk.Label(textvariable=self._label_value)
self._label.pack()
self._entry_value = Tk.StringVar()
self._entry = Tk.Entry(textvariable=self._entry_value)
self._entry.pack()
self._button = Tk.Button(text="Next", command=self._move_next)
self._button.pack()
def _show_next_question(self):
q = self._questions.pop(0)
self._label_value.set(str(q))
def _move_next(self):
self._read_answer()
if len(self._questions) > 0:
self._show_next_question()
self._entry_value.set("")
else:
self.quit()
self.destroy()
def _read_answer(self):
answer = self._entry_value.get()
self._answers.append(answer)
def _button_classification_callback(self, args, class_idx):
self._classification_callback(args, self._classes[class_idx])
self.classify_next_plot()
if __name__ == "__main__":
questions = ["How old are you?",
"What is your name?"]
answers = []
root = QAGame(questions, answers)
root.mainloop()
for q,a in zip(questions, answers):
print "%s\n>>> %s" % (q, a)
We only have a Label, an Entry and a Button (I did not care about layout!, just pack()).
Attached to the button is a command (aka callback). When the button is pressed, the answer is read and the new question is assigned to the label.
Usage of this class is understandable from the example in the `if name == "main" block. Please note: the answers-list is filled in place, the questions-list is kept unchanged.
I don't know Tk, but is there no any signals of input text changed? There should be for sure. Just check if this signal occured and then move onto new question, because it means that someone typed something in input box.