for my program i am using tkinter for the GUI. Before the program starts i want to have to input a password. I used the input() function. When running my code in my jupyter notebook everything works fine. So i created and executable file with pyinstaller, but when double clicking it won´t start and ask for the input. Since i often used pyinstaller i don´t think i failed in creating the exe-file, so my guess is, that the problem lies within the input() function. Is there another way to ask for user input?
I tried creating a window with an entry widget via Toplevel but i am not quite sure how to implement it since i want to start the program AFTER i entered the password.
My relevant code:
if __name__=='__main__':
root = tkinter.Tk()
asd = input("Enter the password:")
if asd == str(12345):
app = GUI(master=root)
app.master.title("Programm Links")
app.master.minsize(600,400)
root.config(menu=app.menubar)
app.center(root)
app.mainloop()
else:
root.destroy()
So with help of the comments on my question i got an answer:
import tkinter
from tkinter import messagebox
from tkinter import simpledialog
if __name__=='__main__':
root = tkinter.Tk()
root.withdraw()
asd = tkinter.simpledialog.askstring("Password","Enter the password:")
if asd == str(12345):
app = GUI(master=root)
app.master.title("Programm Links")
app.master.minsize(600,400)
root.config(menu=app.menubar)
app.center(root)
app.mainloop()
else:
messagebox.showwarning("WRONG PASSWORD","You entered a wrong password")
root.destroy()
This creates a dialogbox that asks for a user input. root.withdraw() hides the root window frame that gets created by root = tkinter.Tk() which is needed for the dialogbox to run.
Related
I have a function to display a GUI window where the user can type the password. I use IDLE shell a lot during development, so using getpass is not an option.
This function is part of a utility script that has other functions I want to be able to use (after submitting the password using this function).
import tkinter
def password_from_user():
password = None
def get_password(*__):
nonlocal password
password = entry.get()
window.destroy()
window = tkinter.Tk()
entry = tkinter.Entry(window, width=40, show='*')
entry.bind('<Return>', get_password)
entry.pack()
entry.focus_set()
window.mainloop()
return password
The password gets stored and returned from the function. However, the Tkinter window stays open. I can press ⌘+Tab to switch back to IDLE shell, but it's slightly inconvenient. I'd like this window to be completely closed.
If I run this as a script, of course, everything gets closed at the end:
if __name__ == '__main__':
print(password_from_user())
But, I need this function only for IDLE session. If I were only using command line, I would use getpass which would be more than sufficient.
Edit 1: I have tried using both destroy and quit. Neither of them works for me.
Edit 2: Just tested on a Windows machine with Python 3.8.5. It works. So, I'm pretty sure it's something to do with macOS.
Figured out a solution that satisfies me.
Save the Tkinter code in a separate module (say, _password_box_ui.py):
import tkinter
password = None
def get_password(*__):
global password
password = entry.get()
window.quit()
window = tkinter.Tk()
window.title('Password')
entry = tkinter.Entry(window, width=40, show='*')
entry.bind('<Return>', get_password)
entry.pack()
entry.focus_set()
window.mainloop()
print(password)
Then, in another module (which I'll import in the IDLE shell), use a function like this:
import pathlib
import subprocess
import sys
def password_from_user():
process = subprocess.run(
[
f'{sys.base_exec_prefix}/bin/python',
pathlib.Path(__file__).parent / '_password_box_ui.py',
],
capture_output=True,
)
return process.stdout.rstrip(b'\n').decode()
May not be very elegant, but serves my purpose, which is to use IDLE to get password from the user using a GUI (so that, ultimately, no password needs to be stored in plaintext anywhere).
I am creating a program where I make use of a check button to delete and recover a background image in python tkinter. I got the deleting part. Can someone help with the recovering part? I want to recover the image on clicking the check button.
You can do the same with your background image as I have done with the hi variable.
Like this:
import tkinter as tk
root = tk.Tk()
var = tk.IntVar()
def test():
if var.get():
hi.grid_remove()
else:
hi.grid(column=0, row=1)
hi = tk.Label(text="hi")
hi.grid(column=0, row=1)
c_b = tk.Checkbutton(text="Check", variable=var, command=test)
c_b.grid(column=0, row=0)
root.mainloop()
Note: Don't use destroy(). Use grid.remove or grid.forget() instead, otherwise your image won't be recovered.
I prefer using grid.remove, because if you need to do some change to a widget after making it disappear. Then to get it back grid.forget also won't work properly.
I created a root window by using pycharm. I added a button widget which does not work properly. When I run the program it executes the action (action that is assigned for that button) before clicking on the button.
code:-
from tkinter import messagebox
def buttontapped():
messagebox._show("Message", "Hello World")
root = Tk()
label1 = Label(root, text="Nish")
label1.pack()
Button(root, text="Message", command=buttontapped()).pack()
root.mainloop()```
As you have not shared the code, i can only guess what could be causing the problem.
However, this sounds like a common mistake of including parenthesis in the bind method: button.bind('<event>',function())
This calls the function immediately and binds the return value instead of the function.
If this is the problem, the solution is to remove the parenthesis.
The problem I am encountering is that I appear to be stuck in an infinite loop, (If I am not, please correct me). I am using tkinter for python 3.6 (64 bit) on windows 10.
In the module I am having an issue with I have 3 entry widgets and 2 buttons. Both buttons call the "destroy()" function in order to kill the parent window.
Below is a heavily abstracted version of my module, the purpose of the module is to take inputs from the entry widget and write them to a file.
def Create():
parent = Tk()
parent.MakeItlookNice
entry1 = Entry(parent)
entry1.insert(INSERT, "Please enter your desired username here")
entry2 = Entry(parent)
entry2.insert(INSERT, "Please enter your desired password here")
entry3 = Entry(parent)
entry3.insert(INSERT, "What is your mother's maiden name")
Submit = tk.Button(parent,
text ="Click here to submit your stuff",
command = lambda: [parent.destroy(),
submit.function()])
Cancel = tk.Button(parent,
text ="Click here to cancel your request",
command = lambda: parent.destroy())
parent.mainloop()
This function is contained within the module "RegisterNewUser". The "Menu" module is the module that called this function. As far as I am aware once parent.destroy() is called there is no more code to execute since it is all contained within parent.mainloop(), therefore the function is finished and the "Menu" module should continue executing.
What should happen:
I want the Submit button to destroy the window, execute the function and then return to the "Menu" module.
I want the cancel button to destroy the window and return to the "Menu" module.
What actually happens:
The window closes, like it is supposed to
But the code inside the "Menu" module does not start executing again
When I go to close the python shell, it warns me that the program is still running
Ultimately my question is, what code is still running and why hasn't it stopped?
Thank you for reading this and if you require more detail please let me know.
EDIT: I have done research on this topic before posting this question. I have read the documentation on both the tk.destroy() function and the tk.mainloop() function, I have also opened up the Tkinter module in IDLE to try and understand what happens at a deeper level but after all this, I was still unable to figure out a solution. This is my first question on stack overflow, please forgive me if I have done anything wrong.
Hmmm, so you say multiple windows? an easier way to achieve a complex UI as such is using a concept called frames. Tkinter allows you to completely change you screen and layout if you switch to a new frames. This might require you to reprogram alot of code. for an example see Switch between two frames in tkinter
Also, Some guy built a really nice Bitcoin monitoring app using tkinter and frames on youtube
I think you would probably benefit from using Toplevel() here.
I have taken the code you provided and added it to a class used to create the main window and to manage the pop up window.
I noticed a few things with you code.
Its obvoious you are importing tkinter twice like this:
import tkinter as tk
from tkinter import *
I can tell from how you have written your entry fields vs your buttons. Do not do this. Instead just used one or the other. I recommend just using import tkinter as tk.
You are using a function to create a new tkinter instance and judging by your question you all ready have a tkinter instance created for your menu. Instead of creating new Tk() instances you can use Toplevel() instead to open a new window that can inherit everything from the main window and should be easier to manage.
You do not really need to use lambda in this situation. I have also removed the lambda function and replaced with a simple command that will work here.
Take a look at the below code and let me know if you have any questions.
import tkinter as tk
class MyApp(tk.Frame):
def __init__(self, master, *args, **kwargs):
tk.Frame.__init__(self, master, *args, **kwargs)
self.master = master
self.master.title("Main MENU")
tk.Button(self.master, text="Open top level", command = self.create).pack()
def create(self):
self.top = tk.Toplevel(self.master)
entry1 = tk.Entry(self.top, width = 35)
entry1.pack()
entry1.insert(0, "Please enter your desired username here")
entry2 = tk.Entry(self.top, width = 35)
entry2.pack()
entry2.insert(0, "Please enter your desired password here")
entry3 = tk.Entry(self.top, width = 35)
entry3.pack()
entry3.insert(0, "What is your mother's maiden name")
tk.Button(self.top, text ="Click here to submit your stuff",
command = self.Submit).pack()
tk.Button(self.top, text ="Click here to cancel your request",
command = self.top.destroy).pack()
def Submit(self):
print("Do something here to submit data")
self.top.destroy()
if __name__ == "__main__":
root = tk.Tk()
app1 = MyApp(root)
tk.mainloop()
You can use toplevel() and its library function wait_window() just prior to (or instead of) your mainloop() and your problem will be solved
wait_window() mentioned above worked for me in the code below replacing popup.mainloop() with it, the mainloop() kept my code in an infinite loop upon the popup even after okay button was hit
Trying to convert my code to .exe file so that other users can make use of it.
The purpose of this code is to get an interface where the user can enable/disable LAN connection in a single click.
Kindly 'run as administrator' you IDLE to make this code work.
import tkinter as tk
import subprocess as sub
import os
WINDOW_SIZE = "350x100"
root = tk.Tk()
root.title("Windows Adapter Toggler")
root.geometry(WINDOW_SIZE)
#to execute bash command right from python script
tk.Button(root, text="DISABLE Internet", command=lambda: sub.call('netsh
interface set interface name="Ethernet" admin=DISABLED')).pack()
tk.Button(root, text="ENABLE Internet", command=lambda: sub.call('netsh
interface set interface name="Ethernet" admin=ENABLED')).pack()
#os.system(bashCommand)
root.mainloop()
SideNote:
1.Will work if your ethernet port name is 'ethernet',if something else then change the name in the code.Will implement this 'changing name of port'feature later in the code.
2.Already tried converting with pyinstaller and py2exe but didn't happen.