3

I have been working on a project over the last few weeks where I am interacting with an industrial robot through a wireless connection and using REST protocol through a Raspberry Pi and python. I am new to python but familiar with C++ so I am not new to programming necessarily.

I have created a GUI using Tkinter in python (thanks to a lot of your help already) and I am trying to create a sort of kiosk mode. I already have the GUI launching fullscreen without an option to close it. What I am stuck on is that I am trying to create an entry line in one of the popup windows in my GUI that when the correct password string is entered, it will close the GUI for administrators or authorized personal to be able to access the rest of the Raspberry Pi files if needed. I believe that I know how to make this process work using the root.quit() method (the parent window is root) but the entry line won't even show any text. All text that I type is being typed in terminal even though my GUI is fullscreen. Here is the specific section of code with comments for the popup window that I am trying to get the entry line to be in:

################## Status Window ##################
def statusWindow():                                                     #defines function for popup window for additional options
    window = Toplevel(root)                                             #creates variable to place widgets in window
    window.title('Status')                                              #makes window title for specific window frame
    w, h = window.winfo_screenwidth(), window.winfo_screenheight()      #aquires dimensions from display size
    window.geometry("%dx%d+0+0" % (w, h))                               #sets window size to aquired dimensions
    window.overrideredirect(True)                                       #removes top bar and exit button from parent window frame

    batteryButton = Button(window, text="Battery", fg="green", command=lambda: showBattery(window), width=35, height=12)        #defines criteria for battery button in new window
    statusButton = Button(window, text="Overview", fg="green", command=lambda: showQueueStatus(window), width=35, height=12)    #defines criteria for status button in new window
    returnButton = Button(window, text="Return...", fg="green", command=window.destroy, width=35, height=12)                    ##defines criteria for return button in new window
    passEntry = Entry(window, show="*")

    batteryButton.grid(row=1, column=0, padx=10, pady=5)        #makes button viewable in specified orientation                                                                
    statusButton.grid(row=2, column=0, padx=10, pady=5)         #makes button viewable in specified orientation
    returnButton.grid(row=3, column=0, padx=10, pady=5)         #makes button viewable in specified orientation
    passEntry.grid(row=4, columnspan=10, sticky=W)

    robotName(window)       #call robotName function to display robot name
    winReturn(window)       #call winReturn function to create return label

def robotName(winFrame):                                #define function to display robot name in status window
    label = Label(winFrame, text="Robot Name: ")        #defines variable label for visual display
    name = robot.robot_name()                           #gets robot name from robot and stores it in name variable
    nameLabel = Label(winFrame, text=name)              #defines variable label for visual to hold robot name as string        

    label.grid(row=0, column=0, padx=10, pady=5)        #makes label display in popup window
    nameLabel.grid(row=0, column=3, padx=10, pady=5)    #makes robot name display in popup window

def showBattery(winFrame):                                  #define function to display current battery percentage in popup window
    battery = robot.battery_percentage()                    #retrieves current battery status from robot and stores it in battery variable
    battery = str(battery) + '%'                            #redefines battery variable as previous battery variable string with percentage
    batteryLabel = Label(winFrame, text=battery)            #defines battery label with specified criteria
    batteryLabel.grid(row=1, column=3, padx=10, pady=5)     #displays battery label in popup window

def showQueueStatus(winFrame):                              #define function to display current robot mission queue item status
    queue = robot.robot_state_text()                        #retrieves current queue item status and stores in queue variable
    qStatusLabel = Label(winFrame, text=queue)              #defines queue status label with specified criteria
    qStatusLabel.grid(row=2, column=3, padx=10, pady=5)     #displays queue status label in popup window

def winReturn(winFrame):                                        #define function to display label for return button
    returnLabel = Label(winFrame, text="Close out of window")   #defines return label with specified criteria
    returnLabel.grid(row=3, column=3, padx=10, pady=5)          #displays return label in popup window

I have placed the entry line in the statusWindow() definition as this is the method that gets called from the rest of my program. If you have any ideas why its not letting me type in the entry line, your advice would be appreciated. If more samples of my code is needed, I can post more but I was trying to keep this post short.

Cœur
  • 37,241
  • 25
  • 195
  • 267
J.kors
  • 81
  • 1
  • 8
  • Hi J.Kors. There is a lot of code here and it would be best if you could provide a [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve). There might be something in your code causing this issue and if you create a MCVE you may find the problem on your own. And if the problem still persist then it would provide something for us to test with. – Mike - SMT Jun 30 '17 at 17:19
  • I do agree that there is something in my code prohibiting it from allowing user text to be typed in an entry line. I have created a second smaller program that works just fine for an entry line only. My guess is that it has something to do with the Tkinter frames I am using. Could it be the focus of the widgets? – J.kors Jun 30 '17 at 17:37
  • I don't see anything in the code you have shown us so far that can cause the user to be typing in the console rather than the entry field. Does the user have a mouse to interact with or is it touchscreen base? – Mike - SMT Jun 30 '17 at 17:40
  • It is a touchscreen base GUI, however I was planning on an administrator having keyboard access since its a python GUI run on a Raspberry Pi. – J.kors Jun 30 '17 at 17:42
  • You could try `focus_force()` on the entry widget – Mike - SMT Jun 30 '17 at 17:43
  • all the guessing could be avoided if I could see how your instance of `Tk()` is created and managed. This is why we ask for [MCVE](https://stackoverflow.com/help/mcve) – Mike - SMT Jun 30 '17 at 18:08

2 Answers2

2

Without seeing how your program is working you don't really need to create a toplevel window to ask for admin access. You can use tkinters simpledialog askstring function to ask for a password and then use iconify() to minimize the window.

Take a look at this example.

from tkinter import *
from tkinter import simpledialog
# from Tkinter import * # for python 2.x
# import tkSimpleDialog as simpledialog # for python 2.x

root = Tk()
root.attributes("-fullscreen", True)# fullscreen without the standard window buttons

def check_admin_password():
    # use askstring here to verify password.
    pass_attempt = simpledialog.askstring("Verifying access",
                                           "Please enter Admin password")
    if pass_attempt == "password":
        root.iconify() # used whatever your instance of Tk() is here in place of root.

admin_minimize_button = Button(root, text = "Minimize window", command = check_admin_password)
admin_minimize_button.pack()

root.mainloop()
Mike - SMT
  • 14,784
  • 4
  • 35
  • 79
  • I tried this code to see if I could use any of it however when I tried to execute it alone, I was given an error that it could not import simpledialog. I commented the import line and it opened up with just a minimize button but with no commands or methods that it called. I'm assuming that happened since it couldnt import the simpledialog. – J.kors Jun 30 '17 at 17:55
  • @J.kors What version of python are you using? – Mike - SMT Jun 30 '17 at 17:56
  • I am using python 2.7 on my Raspberry Pi 3. In response to your other comment above, I just tried using the force_focus() and it still takes the keyboard input in terminal oddly enough. – J.kors Jun 30 '17 at 18:00
  • @J.kors then use `import tkSimpleDialog` The imports are different between python 2 and python 3. You might need to do `import tkSimpleDialog as simpledialog` if you want to use the exact example I provided – Mike - SMT Jun 30 '17 at 18:03
  • Ah yes that was the problem and I think what you've done here will work just fine if I implement it in mine. I will give it a try and post the results in a bit. – J.kors Jun 30 '17 at 18:07
  • @J.kors If you want to use the entry field option you already have you could try `passEntry.focus_force()` this will place the cursor into the entry filed and should allow the users to type in it. – Mike - SMT Jun 30 '17 at 18:09
  • Oddly enough, I did try to use passEntry.focus_force() and while it did place the cursor into the entry field, it still did not allow the keyboard input to show there. – J.kors Jun 30 '17 at 19:58
  • @J.Kors I see you accepted my answer. What was the actually solution to your problem? – Mike - SMT Jun 30 '17 at 20:09
  • I am actually still working on this however using the tkSimpleDialog that you suggested, I can get a dialog window that allows a password to be entered to close my entire GUI. I am currently in the process of editing the tkSimpleDialog.py so that it will open fullscreen because it is not visible when my program is fullscreen so I need to edit it to take focus I believe. – J.kors Jul 05 '17 at 17:08
0

You can do a

passEntry.bind('<Return>', myfunc)

to invoke a password checking function, make your decision what to do, etc. If you need to hide the full screen gui, try

root.tk.call('wm', 'withdraw', root)
Ron Norris
  • 2,642
  • 1
  • 9
  • 13