I am a newb and I have a small script that uses guizero to create a small app that reads a rfid tag and activates door lock. The problem I am having is, when the power goes off and the raspberry pi reboots. the script launches but I have to manually click in the texts box before it will start working. how can I have it automatically set focus on the textbox when it launches?
thanks
Mark
Here is code, I found this project online and modified some to work for me.
from gpiozero import LED, Buzzer
from guizero import App, Box, Text, TextBox, warn
import gpiozero
import csv
RELAY_PIN = 17
led8 = LED(5)
led9 = LED(6)
relay= gpiozero.OutputDevice(RELAY_PIN,active_high=False, initial_value=False)
def clearDisplay():
print("Clear display")
rfidStatus.value = "—"
rfidText.value = ""
led8.off()
led9.off()
relay.off()
rfidStatus.repeat(1000, checkRFidTag)
def checkRFidTag():
tagId = rfidText.value
if tagId != "":
RFidRegistered = False
print(tagId)
with open("Database.csv") as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
if row["RFid"] == tagId:
RFidRegistered = True
print("Welcome " + row["User"])
rfidStatus.value = "Welcome " + row["User"]
led8.on()
relay.toggle()
rfidStatus.after(5000, clearDisplay)
if RFidRegistered == False:
print("RFid tag is not registered")
rfidStatus.value = "RFid tag is not registered"
led9.on()
rfidStatus.after(3000, clearDisplay)
rfidStatus.cancel(checkRFidTag)
app = App(title="RFID EM4100 Simple GUI", width=350, height=150, layout="auto")
instructionText = Text(app, text="Click on the text button below\nand scan your RFid tag.")
rfidText = TextBox(app,text="")
rfidStatus = Text(app, text="—")
rfidStatus.repeat(1000, checkRFidTag)
#designBy = Text(app, text="Design by Idris – Cytron Technologies", align="bottom")
app.display()
view
You could use a timer associated with the app to call a fuction shortly after starting up. For example, use:
app.after(1000,setFocus)
to call:
def setFocus():
nameOfTextBox.focus()
The example below sets up two text boxes and two buttons. By commenting out one or other of the lines in setFocus it sets focus to the right hand text box or the cancel button after one second:
from guizero import App, Text, Box, TextBox, PushButton
import sys
app = App(title="Give Focus")
app.width = 500
app.height = 100
paddingHeight = 1
paddingWidth = 10
buttonWidth = 10
topBoxHeight = 100
bottomBoxHeight = 100
app.height = topBoxHeight + bottomBoxHeight
def setFocus():
rightTextBox.focus()
# buttonCancel.focus()
def call_exit():
buttonCancel.text="Exiting"
buttonCancel.enabled=False
app.update()
app.destroy()
sys.exit()
topBox = Box(app, align="top", width= "fill", height = topBoxHeight, border= True)
textFieldBox = Box(topBox, align="top", width= "fill", height= "fill", border= True, layout = "grid")
paddingT00 = Text(textFieldBox, text="", width = paddingWidth, height = paddingHeight, grid = [0,0])
paddingT10 = Text(textFieldBox, text="", width = paddingWidth, height = paddingHeight, grid = [1,0])
message = Text(textFieldBox, text="Text Field Box", grid = [2,0])
paddingT01 = Text(textFieldBox, text="", width = paddingWidth, height = paddingHeight, grid = [0,1])
leftTextBox = TextBox(textFieldBox, text="Type here", width = paddingWidth, height = 1, grid = [1,1])
paddingT21 = Text(textFieldBox, text="", width = paddingWidth, height = paddingHeight, grid = [2,1])
rightTextBox = TextBox(textFieldBox, text="...or here", width = paddingWidth, height = 1, grid = [3,1])
bottomBox = Box(app, align="top", width= "fill", height = bottomBoxHeight, border= True)
buttonBox = Box(bottomBox, align="top", width= "fill", height= "fill", border= True, layout = "grid")
paddingB00 = Text(buttonBox, text="", width = paddingWidth, height = paddingHeight, grid = [0,0])
paddingB10 = Text(buttonBox, text="", width = paddingWidth, height = paddingHeight, grid = [1,0])
message = Text(buttonBox, text="Button Box", grid = [2,0])
paddingB01 = Text(buttonBox, text="", width = paddingWidth, height = paddingHeight, grid = [0,1])
buttonOK = PushButton(buttonBox, text="OK", width = paddingWidth, height = 1, grid = [1,1])
paddingB21 = Text(buttonBox, text="", width = paddingWidth, height = paddingHeight, grid = [2,1])
buttonCancel = PushButton(buttonBox, text="Cancel", command = call_exit, width = paddingWidth, height = 1, grid = [3,1])
app.after(1000,setFocus)
app.display()
Related
I'm trying to incorporate a 'back button' in my Tkinter app in my 'second_home' to allow the user to return to the previous page - from second_home to home. I've incorporated a hide_frames() function to allow all the frames to disappear when called. I have this done on the second_home but I've commented out the function on the home function - the app won't run with the function called. I also have the home function called when launching the app.
When clicking on the back button titled "Previous Page" I receive the error 'TclError: bad window path name ".!labelframe.!canvas'
from tkinter import *
from tkinter import ttk
from tkinter.font import BOLD
win = Tk()
# Creating Frames
wrapper1 = LabelFrame(win, width = 900, height = 950)
wrapper2 = LabelFrame(win, width = 900, height = 950)
wrapper3 = LabelFrame(win, width = 900, height = 950)
wrapper4 = LabelFrame(win, width = 900, height = 950)
mycanvas = Canvas(wrapper1)
mycanvas.pack(side = LEFT, fill = "both", expand ="yes")
# Creating a Hide Frame Function
def hide_frames():
# Destroying the widgets in each frame
for widget in wrapper1.winfo_children():
widget.destroy()
for widget in wrapper2.winfo_children():
widget.destroy()
for widget in wrapper3.winfo_children():
widget.destroy()
for widget in wrapper4.winfo_children():
widget.destroy()
# Hiding all frames
wrapper1.pack_forget()
wrapper2.pack_forget()
wrapper3.pack_forget()
wrapper4.pack_forget()
def home():
#hide_menu_frames()
global myframe
myframe = Frame(mycanvas)
mycanvas.create_window((0,0), window = myframe, anchor = "nw")
wrapper1.pack(fill = "both", expand = "yes", padx = 10, pady = 10)
myframe.pack(fill = "both", expand = 1)
start_label = Label(myframe, text = "Choose Length of Loan Model", font = ("Helvetica", 19)).pack(pady = 100)
# Creating buttons
home_button1 = Button(myframe, text = "12 Month Model", bg='#ffffff', activeforeground='#4444ff', font = ("Helvetica", 16, BOLD), command = second_home).pack(pady = 10)
def second_home():
hide_frames()
mycanvas = Canvas(wrapper2)
mycanvas.pack(side = LEFT, fill = "both", expand ="yes")
yscrollbar = ttk.Scrollbar(wrapper2, orient = VERTICAL, command = mycanvas.yview)
yscrollbar.pack(side = RIGHT, fill = "y")
mycanvas.configure(yscrollcommand = yscrollbar.set)
mycanvas.bind('<Configure>',lambda e: mycanvas.configure(scrollregion = mycanvas.bbox('all')))
wrapper2.pack(fill = "both", expand = "yes", padx = 10, pady = 10)
myframe = Frame(mycanvas)
mycanvas.create_window((0,0), window = myframe, anchor = "nw")
second_label = Label(myframe, text = "Please Input Loan Parameters", font = ("Helvetica", 18), pady = 10, padx = 325).pack()
# Creating a Back Button
back_button = Button(myframe, text = "Previous Page", command = home)
back_button.pack(pady = 10)
# Defining a Main Menu
my_menu = Menu(win)
win.config(menu = my_menu)
# Creating Menu Items
app_menu = Menu(my_menu)
my_menu.add_cascade(label = "Options", menu = app_menu)
app_menu.add_command(label = "Home", command = home)
app_menu.add_separator()
app_menu.add_command(label = "Exit", command = win.quit)
win.geometry("900x950")
#win.resizable(False, False)
win.title("Loan Cash Flow Model Creator")
home()
win.mainloop()
I know i'm probably making a silly mistake but is there any reason that this isn't working? I am trying to delete a row in treeview by clicking on the row and then the delete button but for whatever reason the tv attribute isn't going into the function without an error.
class pageDeleteStaff(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text = "Delete Staff", font = NORMAL_FONT)
label.pack()
tv = ttk.Treeview(self, height = 10, columns = ("StaffID, Forename, Surname, Wage, NIN, Account Name, Account Number, Contract Hours, Usercode, Passcode"))
tv.pack()
tv.heading("#0", text = "StaffID")
tv.heading("#1", text = "Forename")
tv.heading("#2", text = "Surname")
tv.heading("#3", text = "Wage(£)")
tv.heading("#4", text = "NIN")
tv.heading("#5", text = "Account Name")
tv.heading("#6", text = "Account Number")
tv.heading("#7", text = "Contract Hours")
tv.heading("#8", text = "Usercode")
tv.heading("#9", text = "Passcode")
tv.column("#0", width = 100)
tv.column("#1", width = 170)
tv.column("#2", width = 170)
tv.column("#3", width = 150)
tv.column("#4", width = 170)
tv.column("#5", width = 200)
tv.column("#6", width = 150)
tv.column("#7", width = 150)
tv.column("#8", width = 150)
tv.column("#9", width = 150)
conn = sqlite3.connect('subway.db')
c = conn.cursor()
c.execute("SELECT * FROM staff")
staffData = c.fetchall()
for row in staffData:
tv.insert("", "end", text=row[0], values=row[1:])
print(row)
conn.close()
button4 = tk.Button(self, text="Delte", bg = 'grey', fg = 'black', font = SMALL_FONT, height = 2, width = 14,
command = self.deleteRow(controller))
button4.pack()
button4 = tk.Button(self, text="Menu", bg = 'grey', fg = 'black', font = SMALL_FONT, height = 2, width = 14,
command = lambda: controller.show_frame(pageLabour))
button4.pack()
def deleteRow(self, controller):
currentItem = self.tv.focus()
item = tv.item(currentItem)
if item.get("text") == "":
messagebox.showerror("ERROR", "No member of staff selected!")
else:
staffID = int(item.get("text"))
result = messagebox.askyesno("Are you sure?", "Are you sure you would like to delete?")
I'm getting an attribute error when calling tv into the function.
Here is my code
I am trying to create a pop up help window for a tool. I managed to add the scrollbar to a frame that contains canvas and label widget. However that Scrollbar does not shows the img_canvas_3 that I added.
Here is my code:
from tkinter import *
import tkinter.filedialog
from tkinter.filedialog import askopenfilename
from tkinter.filedialog import askdirectory
import PIL
from PIL import Image, ImageTk
help_window = tkinter.Tk()
help_window.title("Help")
help_window.geometry("400x800")
#frame.grid(row=0,column=0)
canvas=Canvas(help_window,bg='red',width=300,height=800,scrollregion=(0,0,500,500))
scroll_y = Scrollbar(help_window, orient="vertical", command = canvas.yview)
frame=Frame(canvas,width=300,height=800, bg="green")
description_label = Label(frame, text = "\n\tMy Tool\n",anchor = "w").pack(side = TOP, fill = "both")
introduction = "This tool provides a basic workflow"
introduction_text = Label(frame, text = introduction, anchor = "w", font = "Verdana 10", bg="yellow").pack(fill = "both")
label_1 = Label(frame, text = "Input Data 1", anchor = "w", font = "Verdana 10", justify=CENTER).pack(fill = "both")
img_canvas_1 = Canvas(frame, bg = "black", height = 300, width = 300)
img_canvas_1.pack(side = TOP)
label_2 = Label(frame, text = "Input Data 2", anchor = "w", font = "Verdana 10", justify = CENTER).pack(fill = "both")
img_canvas_2 = Canvas(frame, bg = "black", height = 300, width = 300)
img_canvas_2.pack(side = TOP)
label_3 = Label(frame, text = "Input Data 3", anchor = "w", font = "Verdana 10", justify = CENTER).pack(fill = "both")
img_canvas_3 = Canvas(frame, bg = "black", height = 300, width = 300)
img_canvas_3.pack(side = TOP)
canvas.create_window(0, 0, anchor = 'nw', window = frame)
canvas.update_idletasks
canvas.configure(scrollregion=canvas.bbox('all'),
yscrollcommand = scroll_y.set)
canvas.pack(fill = 'both', expand = TRUE, side = 'left')
scroll_y.pack(fill = 'y', side = 'right')
help_window.mainloop()
I expected to have the scroll bar working, basically showing all the widgets and elements in the frame as I am adding more and more. That is only true for the untill img_canvas_2
Does anyone have an idea why this is not the case with my code? I tried by playing around with the scrollregion parameter in the canvas variable, but it did not work.
Thanks in advance.
I have written a code for a basic game but the image and shape don't show up unless I add something like item.pack() or win.mainloop() [which doesn't really make sense] but then the lines below it don't run.
When I don't have anything, the buttons show up but the image doesn't show up.
import tkinter as tk
import random
from tkinter import messagebox
win = tk.Tk()
my_label = tk.Label(win, text="Color of the Baloon Game")
my_label.pack()
my_canvas = tk.Canvas(win, width=400, height=600)
my_canvas.pack()
background_image=tk.PhotoImage(file = "CS_Game_menu.png")
background_label = tk.Label(my_canvas, image=background_image)
background_label.photo = background_image
background_label.grid(row = 0, rowspan = 10, column = 0, columnspan = 10)
def drawCircle():
color = "green"
x1 = 265
y1 = 80
diameter = 90
my_canvas.destroy()
circle_button.destroy()
quit_button.destroy()
my_label.destroy()
my_label1 = tk.Label(win, text="What is the Color of the Baloon?", font="Purisa")
my_label1.pack()
my_canvas1 = tk.Canvas(win, width=400, height=600)
my_canvas1.pack()
image1 = r"CS_Game_baloon.png"
photo1 = tk.PhotoImage(file=image1)
item = my_canvas1.create_image(200, 350, image=photo1)
shape = my_canvas1.create_oval(x1, y1, x1 + diameter, y1 + diameter+20, fill=color)
item.pack()
game1_button = tk.Button(my_canvas1, text = "Green")
game1_button.grid(row= 8, column = 3)
game1_button["command"] = lambda: messagebox.showinfo("Congratulations!", "Correct Answer!")
game2_button = tk.Button(my_canvas1, text = "Blue")
game2_button.grid(row= 8, column = 5)
game2_button["command"] = lambda: messagebox.showinfo("Sorry!", "Incorrect Answer!")
game3_button = tk.Button(my_canvas1, text = "Red")
game3_button.grid(row= 8, column = 7)
game3_button["command"] = lambda: messagebox.showinfo("Sorry", "Incorrect Answer!")
circle_button = tk.Button(win, text="New Game")
circle_button.pack()
circle_button["command"] = drawCircle
quit_button = tk.Button(win, text="Quit")
quit_button.pack()
quit_button['command'] = win.destroy
You are using both the create_... methods and grid methods on your canvas object. It won't behave as you expected.
To achieve what you want, you can create a Frame, put your buttons in it, and then use create_window method on your canvas:
def drawCircle():
...
shape = my_canvas1.create_oval(x1, y1, x1 + diameter, y1 + diameter+20, fill=color)
frame = tk.Frame(my_canvas1)
game1_button = tk.Button(frame, text = "Green")
game1_button.grid(row= 8, column = 3)
game1_button["command"] = lambda: messagebox.showinfo("Congratulations!", "Correct Answer!")
game2_button = tk.Button(frame, text = "Blue")
game2_button.grid(row= 8, column = 5)
game2_button["command"] = lambda: messagebox.showinfo("Sorry!", "Incorrect Answer!")
game3_button = tk.Button(frame, text = "Red")
game3_button.grid(row= 8, column = 7)
game3_button["command"] = lambda: messagebox.showinfo("Sorry", "Incorrect Answer!")
my_canvas1.create_window(200,500,window=frame)
And of course, add win.mainloop() to the bottom of your program if you haven't already.
The function of this code is that it displays the list of records in a database with one of the fields being a button. When this button is clicked it brings the user to a new frame which displays the account information for that record.
The record information is displayed in the Record class as dat[0] and dat[1] and I have had problems with initializing this in the second class, I do not know how I would get this information to appear on the second screen.
Thanks for any help.
from tkinter import *
import sqlite3
import AddAccount
import RemoveAccount
import LogOnLib
import LoginMenu
import TrainerAccounts
class Records(object):
def __init__(self, window):
self.window = window
window.state("zoomed")
self.window.title('Trainer Accounts')
window.update_idletasks()
h = self.window.winfo_height()
w = self.window.winfo_width()
Center_h = h/2
Center_w = w/2
self.FrameRecords = Frame(window, bg = "PaleTurquoise1")
self.FrameRecords.place(x = Center_w , y = Center_h, anchor = "center", width = 1024, height = 300)
self.btn_Back = Button(self.FrameRecords, text = "Back", bg = "PaleTurquoise1", font =("Arial", "16"), command = self.Back, width = 20)
self.btn_Back.grid(row = 1, column = 4, columnspan = 5)
self.connection = sqlite3.connect(r"E:\Program\Accounts.db")
self.cur = self.connection.cursor()
self.btn_TrainerID = Label(self.FrameRecords, text = "Trainer ID", bg = "PaleTurquoise1", font =("Arial", "16"), width = 20)
self.btn_TrainerID.grid(row = 0, column = 1, columnspan = 1)
self.NameLabel = Label(self.FrameRecords, text = "Name", bg = "PaleTurquoise1", font =("Arial", "16"), width = 20)
self.NameLabel.grid(row=0, column=0)
self.showallrecords()
def showallrecords(self):
Data = self.readfromdatabase()
for index, dat in enumerate(Data):
self.row1 = Button(self.FrameRecords, text=dat[0],font =("Arial", "16"), command = self.account).grid(row=index+1, column=0)
self.row2 = Label(self.FrameRecords, text=dat[1],font =("Arial", "16")).grid(row=index+1, column=1)
def readfromdatabase(self):
self.cur.execute("SELECT * FROM Trainers")
return self.cur.fetchall()
self.btn_TrainerID = self.row1
self.NameLabel = self.row2
def Back(self):
self.FrameRecords.place_forget()
GUI = LoginMenu.Logged(self.window)
def account(self):
self.FrameRecords.place_forget()
GUI = TrainerAccounts.TrainerInfo(self.window, Records)
##########################################################################################################################################################################################
class TrainerInfo(Records):
def __init__(self, window, Records):
self.window = window
window.state("zoomed")
self.window.title('CHANGEEEE')
window.update_idletasks()
h = self.window.winfo_height()
w = self.window.winfo_width()
Center_h = h/2
Center_w = w/2
self.FrameTrainerInfo = Frame(window, bg = "PaleTurquoise1")
self.FrameTrainerInfo.place(x = Center_w , y = Center_h, anchor = "center", width = 1024, height = 300)
self.connection = sqlite3.connect(r"E:\Program\Accounts.db")
self.cur = self.connection.cursor()
self.showrecord()
def showrecord(self):
Data = self.Information()
for index, dat in enumerate(Data):
Label(self.FrameTrainerInfo, text=self.row1,font =("Arial", "16")).grid(row=index+1, column=0)
Label(self.FrameTrainerInfo, text=self.row2,font =("Arial", "16")).grid(row=index+1, column=1)
def Information(self):
self.cur.execute("SELECT * FROM Trainers WHERE row1 = '" + row1 + "'" + "AND row2 = '" + row2 + "'")
return self.cur.self.all()
Have you tried merging the two classes together ?
if you can push values from database you only need make a .insert on Entrybox
maybe like this
tkEntry = Entry( master)
tkEntry.pack() # .grid or .place, don't make this in obj create
tkEntry.insert( 0, dat[0] ) # 0 is the index and dat[0] is your value