Copying a randomly generated string from python to the clipboard - python

I'm working on a "Password Generator" that will generate a string of random characters. I would like to add a 'Copy' button that when clicked will take that random string and add it to the clipboard so that it can be pasted elsewhere.
I thought I had it worked out with my current code as I stopped getting error messages but whenever I try to paste the password I get something like "<function genpass at 0x029BA5F0>".
import random
from swampy.Gui import *
from Tkinter import *
import string
#--------Globals-------
pcha = string.ascii_letters + string.punctuation + string.digits
g = Gui()
#--------Defs---------
def genpass():
return "".join(random.choice(pcha) for i in range (10))
def close():
g.destroy()
def copy():
g.withdraw()
g.clipboard_clear()
g.clipboard_append(genpass)
#--------GUI----------
g.title("Password Helper")
g.la(text="Welcome to Password Helper! \n \n Choose from the options below to continue. \n")
rndpass = StringVar()
update = lambda:rndpass.set(genpass())
btna = g.bu(text="Generate a New Password", command=update)
btna.pack(padx=5)
pbox = g.en(textvariable = rndpass)
pbox.config(justify='center')
pbox.pack( padx = 5)
btnb=g.bu(text ="Copy to Clipboard", command=copy)
btnc=g.bu(text ="Exit", command=close)
g.mainloop()
I feel like I'm missing just one little thing that would solve my problem but I just can't guess what it is. I've been searching around and found a few possible solutions (even pyperclip) but no matter how I try them I always end up with the same outcome. Any help is greatly appreciated.

This line:
g.clipboard_append(genpass)
is adding the function genpass, rather than its return value
You need to call the function with ():
g.clipboard_append(genpass())
Edit: It looks like you're storing the password in rndpass. So to get that back out, you need to call rndpass.get():
g.clipboard_append(rndpass.get())

Related

Passing function return into a text string within PySimpleGUI window

Sorry for the noob question.
I've defined a button in PySimpleGUI that should check the number of records in the API and return in a text field in the window, that number, within a text string.
I'm doing something wrong with the hierarchy of statements, I think.
When I add indentation to the last two lines quoted, then nothing happens upon button click, but if I reduce indents, an error says that 'response' is undefined.
Passing the function result into the string directly doesn't seem to work either (error says you can't do it).
I think I've tried every combination of indents and also parameters given to the get_entries function.
if event == '-CHECK-':
baseurl_short = 'https://api.nfz.gov.pl/app-umw-api/agreements?page=1&limit=25&format=json&api-version=1.2&sort=provider-code:ASC'
if method == ['Service Type']:
api_url_short = ''.join([baseurl_short, '&serviceType=', type_input, '&year=', year_input, '&branch=', region_input])
else:
api_url_short = ''.join([baseurl_short, '&productCode=', code_input, '&year=', year_input, '&branch=', region_input])
def main_request_short(api_url):
r = requests.get(api_url)
return r.json()
def get_entries(response):
return math.ceil(response['meta']['count'])
sum_entries = get_entries(response)
window['-OUTPUT-'].update('Downloading ' + sum_entries + ' records')

How to check input in Textbox Tkinter Python?

I am Python coder and got stuck in a question that "How to check input in textbox of tkinter python". The problem is that it is not giving output on writing this code .
def start(event):
a = main.get(1.0,END)
if a == 'ver':
print('.....')
main = Text(root)
main.pack()
root.bind('<Return>',start)
We can do this by get() method:
from tkinter import *
a=Tk()
def check():
print(x.get('1.0',END)[:-1])
x=Text(a)
b=Button(a,text='Check',command=check)
x.pack()
b.pack()
a.mainloop()
The text widget guarantees that there is always a trailing newline. When you do get(1.0,END) you're getting that trailing newline even if the user doesn't enter a newline.
If you want to get exactly what the user entered, use get("1.0", "end-1c"). That will get all of the characters up to the end, minus one character.
Note: text indexes are strings of the form line.character. Your code is using the floating point value 1.0 which is incorrect. It works fine in some cases, but it won't work in all. You should always use a string rather than a float for text indexes.
from tkinter import *
from threading import Thread
root = Tk()
def check():
while True :
a = main.get(1.0,END)[:-1]
if a == 'ver':
print('.....')
main = Text(root)
main.pack()
Thread(target=check).start()
root.mainloop()
You should write something like
def start(event):
t = var.get()
if t == 'something':
pass
var = StringVar()
e = Entry(master, textvariable=var)
e.pack()
e.bind(bind('<Return>',start)

How to validate a Tkinter entry widget to only accept string?

I am trying to work my way through Tkinter and this is a part of my code:
FirstName = Label(canvas, text="First Name")
FirstName.configure(width=30, bg="white", fg="black", border=10)
FirstName = canvas.create_window(330, 130, anchor = CENTER, window=FirstName)
FName_Entry = Entry(canvas)
canvas.create_window(850, 145, window=FName_Entry, height=35, width=300)
As you can see this is an entry widget for users to enter their first name.
how can I validate this to only accept string (letters) and if they try to enter integers, symbols or basically anything that is not a letter, it should display a message on the side of the widget urging users to enter a valid name.
I tried to check online but most of them are using classes and I am not used to classes as of yet and am new to Tkinter. other examples explain how to limit entry to integers so I am a bit confused here.
Thanks for helping!
Here is a small snippet to actually make you understand better
from tkinter import *
from tkinter import messagebox
root = Tk()
def check():
sel = e.get()
if not sel.isalpha():
messagebox.showerror('Only letters','Only letters are allowed!')
e = Entry(root)
e.pack(pady=10)
b = Button(root,text='Click Me',command=check)
b.pack(padx=10,pady=10)
root.mainloop()
Here we are checking if sel.isalpha() returns False or not, if it does, then show a messagebox saying only letters are allowed. Simple as that.
Do let me know if any errors. Happy coding
Here is more on isalpha() method
Cheers
You can use list in which you can store the letter which is to be accepted.
Then check the each letter of the input with the element in the list.
If any character not found from the input in the list(acceptable character) then it is invalid input.
# acceptable character list
accepted_characters = ['a', 'b', 'c',.....'z', 'A', 'B', 'C',...'Z']
# input from the tkinter entry widget
inp = "hello"
for i in inp:
if i not in accepted_characters:
print('Invalid data.')
Another way is using RegEx module which is built-in module. But I am not too familiar with RegEx.

Select unique value from list

What I am trying to do is, have a list of characters,each of which is a procedure, then I want to pick randomly (or pseudo randomly, it doesn't matter) from this list, and execute that procedure, then I want to be able to run the it again, and not get the same value,for example if I have five values I want to be able to run it 5 times, then the 6th time I run it, it returns nothing. Here is the code:
from Tkinter import*
from random import randint
Characters=[Percy,Annabeth,Leo,Chuck,Sarah]
Used = []
def callback():
end = len(Characters)-1
rando = randint(0,end)
Characters[rando]
for i in Characters:
if Characters[rando] in Used:
print 'This has already been used'
else:
Characters[rando]()
Used.append(Characters[rando])
break
game = Tk()
game.geometry('50x50+700+100')
Button1 = Button(game,text = '1',command =lambda:callback() )
Button1.pack(side=LEFT)
game.mainloop()
I am trying to get
callback()
to run properly, I have tried what you see but I have also tried
if Characters[rando] in Used:
print 'This has already been used'
else:
Characters[rando]
Used.append(Characters[rando])
in both cases it will run the same procedure multiple times, for example, 'Leo' might be executed 3 times in a row. I searched for hours for a way to do this, but I couldn't find one.
First, I would shuffle the Characters:
Characters = [Percy,Annabeth,Leo,Chuck,Sarah]
random.shuffle(Characters)
Now when you run your callback, you pop one character out:
def callback():
try:
C = Characters.pop() #popping the last one is more efficient than the first.
except IndexError:
return None
return C()
Since this destroys Characters, you may want to keep a copy of it around to reset if you need to:
random.shuffle(Characters)
Characters_save = Characters[:]
def reset_characters():
Characters[:] = Characters_save[:]
Completely untested - but you could implement a basic class:
from random import shuffle
class CallNext(object):
def __init__(self, vals):
self.vals = vals[:]
shuffle(self.vals)
self.iter = iter(self.vals)
def __call__(self):
try:
next(self.iter)()
except StopIteration as e:
pass # or do something smarter?
Another option instead of catching StopIteration would be to use:
next(self.iter, lambda: None)()
And then have:
Button1 = Button(game, text='1', command=CallNext(Characters) )

Zelle Graphics interface issue

I'm using Zelle Graphics library and I'm having trouble replacing graphics objects (which, in this case, happens to be text objects).
Here's the code:
from Graphics import *
winName = "Window"
win = Window(winName,600,500)
win.setBackground(Color('silver'))
title = Text((300,20),"Zack's Flash Card Maker")
title.draw(win)
p1 = Rectangle((50, 100),(550,400))
p1.setFill(Color("black"))
p1.draw(win)
class FlashCard:
def __init__(self):
self.commands = {'addQuestion':self.addQuestion,'startGame':self.startGame}
self.stack = []
self.questions = {}
self.questionAnswered = False
self.questionsCorrect = 0
self.questionsIncorrect = 0
def addQuestion(self):
question = ' '.join(self.stack)
self.stack = []
answer = input(question)
self.questions[question] = answer
def startGame(self):
for question in self.questions:
if(self.questionAnswered == False):
answer=input(question)
questionText = Text((300,150),question)
questionText.setFill(Color("white"))
questionText.draw(win)
if(answer == self.questions[question]):
questionAnswer = Text((300,200),answer + " is correct!")
questionAnswer.setFill(Color("green"))
questionAnswer.draw(win)
self.questionsCorrect = self.questionsCorrect + 1
continue
else:
questionAnswer = Text((300,200),answer + " is incorrect. Study this one.")
questionAnswer.setFill(Color("red"))
questionAnswer.draw(win)
self.questionsIncorrect = self.questionsIncorrect + 1
continue
def interpret(self,expression):
for token in expression.split():
if token in self.commands:
operator = self.commands[token]
operator()
else:
self.stack.append(token)
i = FlashCard()
i.interpret('What is your dog\'s name? addQuestion')
i.interpret('What is your favorite thing to do? addQuestion')
i.interpret('startGame')
This is essentially a mini flash card program I'm making. It takes the interpret commands at the bottom and executes them based on the dictionary in the FlashCard class. It basically works: it does the correct text objects. However, text begins to overlap other text objects because it re-draws. I've tried moving the .draw function all over, but it either doesn't appear at all or it overlaps.
Anyone have any suggestions? I want the text to replace for each new flashcard question.
Thanks!
there's an undraw() command that you need to use if you want to make something invisible. I'd recommend placing it right before your continue statements. It's used like
questionText.undraw()
questionAnswer.undraw()
Alternatively, you can use the del command to get rid of each questionText/questionAnswer instance when you're done with it. That's probably a better option since you're actually freeing up the memory that way instead of storing data and not doing anything with it.
You can use setText method to change the text.
example:
string = Text(Point(1, 1), 'original string')
sting.setText('new string')

Categories

Resources