how to copy a string that appears on tkinter GUI - python

i have a password generator script that works fine, problem is, i present the password in the GUI in a label and it doesn't give me the option to copy it so i can put the password where i want it, how can i print the password to the GUI so i can copy it after, is there a better way than label?
I am using the function
tk.Label(root,text=k).grid(row=1)
k being the variable where the password is stored
Alternately if there is some python function that enables me to just straight up copy the contents of k to the clipboard that might be even better, thanks

The simplest solution is to use an Entry widget with the state set to "readonly".
Example:
import tkinter as tk
root = tk.Tk()
entry = tk.Entry(root)
entry.pack(side="top", padx=20, pady=20)
# insert the password
entry.insert(0, "SuperSecretPassw0rd!")
# configure the entry to readonly
entry.configure(state="readonly")
root.mainloop()
You can also automatically add it to the clipboard with the clipboard_clear and clipboard_append methods:
root.clipboard_clear()
root.clipboard_append(entry.get())

If I understand your problem correctly, you want to get or set a value in a TK gui? Instead of using a Label, I would use an Entry, and I would use one of the TK variable classes (such as StringVar) for k, which have get and set methods
here's a example of a script I use to get and set text values in a TK widget:
frame = tk.Frame(master)
frame.pack()
filepath = tk.StringVar()
filepath.set("/Volumes/data/data/test_data/")
fileentry = tk.Entry(frame, textvariable=filepath, width=125)
fileentry.pack()
if something:
a = filepath.get()
reference to TK variable classes: https://effbot.org/tkinterbook/variable.htm

Related

Tkinter focus on Entry when script run

I am using tkinter to make a small user input sort of thing.
I couldn't find how to set focus to an Entry box when the script is run.
I.e. When the window opens, the first thing that automatically gets focus is the Entry box. set_focus() or focus() doesn't seem to work.
Here is my code:
root = Tk()
v = StringVar()
text = Entry(root,
textvariable=v).grid(column=0,row=0)
text.focus_set()
root.mainloop()
A geometry manager (.grid(), or .pack(), etc...) returns None. You must not use it on the same line as the assignment to a variable:
Your code was trying to call .focus_set() on a variable text whose value was set to None.
Further, the correct method to set the focus to a widget is focus_set(), not set_focus().
root = Tk()
v = StringVar()
text = Entry(root, textvariable=v)
text.grid(column=0, row=0)
text. focus_set()
root.mainloop()

Tkinter Python listbox

I am a new python user. I'm used to programing on matlab.
I've trying to make a simple GUI with Tkinter pack, but I'm having some problems with that. I had already read and searched what i want but I couldn't develop it.
What I'm trying to do is to make a listbox and when I choose one (or more) options the index be returned (and stored) as a variable (array or vector) that could be used to indexing another array.
The best result I got was a listbox where the index were printed, but not stored as a variable (at least it hasn't been shows in the variables list)
I'm using spyder (anaconda).
I tryied a lot of codes and I don't have this anymore.
Sorry for the dumb question. I guess I still thinking in a Matlab way to write
To keep this application simple, your best option is to get the listbox selection when you want to do something with it:
from tkinter import Tk, Listbox, MULTIPLE, END, Button
def doStuff():
selected = lb.curselection()
if selected: # only do stuff if user made a selection
print(selected)
for index in selected:
print(lb.get(index)) # how you get the value of the selection from a listbox
def clear(lb):
lb.select_clear(0, END) # unselect all
root = Tk()
lb = Listbox(root, selectmode=MULTIPLE) # create Listbox
for n in range(5): lb.insert(END, n) # put nums 0-4 in listbox
lb.pack() # put listbox on window
# notice no parentheses on the function name doStuff
doStuffBtn = Button(root, text='Do Stuff', command=doStuff)
doStuffBtn.pack()
# if you need to add parameters to a function call in the button, use lambda like this
clearBtn = Button(root, text='Clear', command=lambda: clear(lb))
clearBtn.pack()
root.mainloop()
I've also added a button to clear the listbox selection because you cannot unselect items by default.
First, import tkinter, then, create the listbox. Then, you can use curselection to get the contents of the listbox.
import tkinter as tk
root = tk.Tk() #creates the window
myListbox = tk.Listbox(root, select=multiple) #allows you to select multiple things
contentsOfMyListbox = myListbox.curselection(myListbox) #stores selected stuff in tuple
See the documentation here.

Tkinter GUI: Adding new entry boxes using .grid() when button is pressed

I'm trying to create new entry boxes when the "ADD entry" is used for my program. I do realize that the 'pack codes' works when I run it individually, but when I combine with existing program which is in grid(), the window is not showing when I run my program.
I also understand that we should not to use both .pack() when I have other things using .grid() in the same program. Hence, my question is, how do I create new entry boxes in grid.
I have tried finding elsewhere but they all suggested pack. For instance: I have looked here here, etc etc, to name a few; but couldn't find anything similar to mine. I would like to add entry boxes below the current entry boxes which is at row 3.
I'm kind of new to Python; (am using Python 2.7 and tkinter module in this program. Thank you very much for the help!
My simplified error codes are as follows:
from Tkinter import *
import tkFileDialog
import tkMessageBox
import Tkinter
import os
class Window:
def __init__(self, master):
self.filename3=""
csvfile=Label(root, text="NUMBERS").grid(row=3, column=0)
bar=Entry(master).grid(row=3, column=3)
self.entryText3 = StringVar()
self.bar = Entry(root, textvariable=self.entryText3).grid(row=3, column=3)
#BUTTONS
self.cbutton= Button(root, text="OK", command=self.process_csv)
self.cbutton.grid(row=15, column=6, sticky = W + E)
####PROBLEM FROM HERE#####
all_entries = []
addboxButton = Button(root, text='ADD', fg="BLUE", command=self.addBox)
addboxButton.pack()
#I have also tried replacing the last 2 lines with the following 2 lines instead but to no avail:
#self.addboxButton = Button(root, text='ADD THA-ID', fg="BLUE", command=self.addBox)
#self.addboxButton.grid(row=3, column=6)
frame_for_boxes = Frame(root)
frame_for_boxes.pack()
def addBox(self):
print "ADD"
next_row = len(all_entries)
lab = Label(frame_for_boxes, text=str(next_row+1))
lab.grid(row=next_row, column=0)
ent = Entry(frame_for_boxes)
ent.grid(row=next_row, column=0)
all_entries.append( ent )
def process_csv(self):
#own program here
print "program"
root = Tk()
window=Window(root)
root.mainloop()
There are few issues with your program other than the one you stated:
Inside the initializer (__init__()) you attached the widgets to root which is not defined within the scope of your Window class. The reasonable way to fix this issue is when you use an instance of Tk(), id est root id est master in Window class, make it as an instance variable. This means the first thing you have to do in the inititializer is this : self.master = master. This will result in you having to replace all root occurrences within __init__() by self.master
The second issue to fix is the one you specified in your question's title: you can not mix the grid() and pack() layout managers for the same widget container. You have to decide which one. Since you placed most of the widgets using grid(), I suggest you to get rid of pack(). This means:
addboxButton.pack() becomes, for example, addboxButton.grid(row=0, column=1)
frame_for_boxes.pack() becomes, for example, frame_for_boxes.grid(row=0, column=0)
The previous list item fixes the problem but it will make you discover other issues within your program which are related:
NameError: global name 'all_entries' is not defined
NameError: global name 'frame_for_boxes' is not defined
This is because those widget variables are not reachable within the scope of addBox() function. To resolve this issue, you have to make those 2 elements as instance variables. This means:
all_entries = [] becomes self.all_entries = []
frame_for_boxes = Frame(root) becomes self.frame_for_boxes = Frame(self.master) (remember we replaced root by self.master in 1.)
The consequence of this error fixing is that you have to use all over inside your program:
self.all_entries instead all_entries
self.frame_for_boxes instead of frame_for_boxes
For scalability reasons, I think you will have at least to make the rest of widgets as instance variables (i.d. prefix them with the self keyword)
As your real project is more complicated than what you show in this MCVE, I encourage you to adopt the SaYa idiom when creating and placing widget elements. This means you will need to replace:
csvfile=Label(root, text="NUMBERS").grid(row=3, column=0)
by
self.csvfile = Label(self.master, text="NUMBERS")
self.csvfile.grid(row=3, column=0)
To avoid unexpected bugs in your program, you must do the same for the remaining widgets you declared in the inititialzer.
There are also other things I would like to mention, but most of them are available on PEP8
What you have to do it to create a command which creates the entries and stores the new entries inside of a variable.
In my case, I use Entry_i and store in Entries but you can use self.Entries to make communication easier. (python 3.5)
def Make_Entry(self, root, Entries, x, y):
Entry_i = Entry(root, bd = 5)
Entry_i.grid(row = x, column = y, sticky = W+E+N+S)
Entries.append(Entry_i)
return(Entries, x+1, y+1)

Tkinter Entry returns float values regardless of input

I have some pretty simple code right now that I am having issues with.
root = Tk()
label1 = Label(root, text ="Enter String:")
userInputString = Entry(root)
label1.pack()
userInputString.pack()
submit = Button(root,text = "Submit", command = root.destroy)
submit.pack(side =BOTTOM)
root.mainloop()
print(userInputString)
When I run the code everything operates as I would expect except
print(userInputString)
for an input asdf in the Entry print will return something like 0.9355325
But it will never be the same value back to back always random.
I am using python 3.5 and Eclipse Neon on a Windows 7 Machine.
Ultimately the goal is to accept a string from the user in the box that pops up and then be able to use that value as string later on. For example, it might be a file path that needs to be modified or opened.
Is Entry not the correct widget I should be using for this? Is there something inherently wrong with the code here? I am new to python and don't have a lot of strong programming experience so I am not even certain that this is set up right to receive a string.
Thanks in advance if anyone has any ideas.
There are two things wrong with your print statement. First, you print the widget, not the text in the widget. print(widget) prints str(widget), which is the tk pathname of the widget. The '.' represents the root window. The integer that follows is a number that tkinter assigned as the name of the widget. In current 3.6, it would instead be 'entry', so you would see ".entry".
Second, you try to print the widget text after you destroy the widget. After root.destroy, the python tkinter wrapper still exists, but the tk widget that it wrapped is gone. The following works on 3.6, Win10.
import tkinter as tk
root = tk.Tk()
label = tk.Label(root, text="Enter String:")
entry = tk.Entry(root)
def print_entry(event=None):
print(entry.get())
entry.bind('<Key-Return>', print_entry)
entry.focus_set()
submit = tk.Button(root, text="Submit", command=print_entry)
label.pack()
entry.pack()
submit.pack()
root.mainloop()
Bonus 1: I set the focus to the entry box so one can start typing without tabbing to the box or clicking on it.
Bonus 2: I bound the key to the submit function so one can submit without using the mouse. Note that the command then requires an 'event' parameter, but it must default to None to use it with the button.
The NMT Reference, which I use constantly, is fairly complete and mostly correct.

Python - TKinter - Editing Widgets

I need a widget in TKinter to be a global widget, however, I need the text displayed in it to be different every time. I'm quite new with TKinter and haven't yet successfully managed to edit an option in a widget.
I assume it's something to do with widget.add_option() but the documentation is quite confusing to me and I can't figure out the command.
I specifically just need to edit the text = "" section.
Thanks
EDIT:
gm1_b_current_choice_label = Label(frame_gm1_b, text = "Current input is:\t %s"% str(save_game[6]))
I specifically need to update the save_game[6] (which is a list) in the widget creation, but I assume once the widget is created that's it. I could create the widget every time before I place it but this causes issues with destroying it later.
You can use the .config method to change options on a Tkinter widget.
To demonstrate, consider this simple script:
from Tkinter import Tk, Button, Label
root = Tk()
label = Label(text="This is some text")
label.grid()
def click():
label.config(text="This is different text")
Button(text="Change text", command=click).grid()
root.mainloop()
When the button is clicked, the label's text is changed.
Note that you could also do this:
label["text"] = "This is different text"
or this:
label.configure(text="This is different text")
All three solutions ultimately do the same thing, so you can pick whichever you like.
You can always use the .configure(text = "new text") method, as iCodez suggested.
Alternatively, try using a StringVar as the text_variable parameter:
my_text_var = StringVar(frame_gm1_b)
my_text_var.set("Current input is:\t %s"% str(save_game[6]))
gm1_b_current_choice_label = Label(frame_gm1_b, textvariable = my_text_var)
Then, you can change the text by directly altering my_text_var:
my_text_var.set("Some new text")
This can be linked to a button or another event-based widget, or however else you want to change the text.

Categories

Resources