python tkinter read user input text label each letter separately - python

Code runs but when I try to write something there is a notification in therminal:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\", line 1883, in __call__
return self.func(*args)
File "c:/Users\", line 11, in getting_Text
if text[0] == 'a' :
File "C:\Users", line 1643, in cget
return self.tk.call(self._w, 'cget', '-' + key)
TypeError: can only concatenate str (not "int") to str
And also: Do I have to put all alphabet to all characerts like
if user[0]== "a"
if user[0]== "b"
etc
and do I have to do it to like thousands of characters like [0] then [1]... [100]
import tkinter as tk
#making main window
root = tk.Tk()
root.title("Encryptor")
root.geometry("600x300")
#getting text
def getting_Text():
user = text.get("1.0",'end-1c')
#I print it just to know if the programme work
print (user)
if text[0] == "a":
result.insert(tk.END, ';', 'big')
if text[0] == "b":
result.insert(tk.END, "%", "big")
#etc.
#UX of the window
prawy_margines = tk.Frame(root)
prawy_margines.pack (side=tk.RIGHT, expand =tk.YES , fill=tk.BOTH)
left_margin = tk.Frame(root)
left_margin.pack(side=tk.LEFT, expand=tk.YES, fill=tk.BOTH)
#after clicking button function getting_text() is used
button = tk.Button( root , text = "Encrypt", activebackground = "#FFFFFF", command=getting_Text)
button.pack( side = tk.TOP )
text=tk.Text(root, width=36, height=15 )
text.pack(side= tk.LEFT)
result= tk.Text(root, width=36, height=15 )
result.pack(side=tk.RIGHT)
root.mainloop()

What you could do to seperate a string into single letters is just get everything in your text widget. Then get the length of the string and then creata a loop which uses the first element of the string and put it somewhere you want to save the letters, then remove it from the string and end the loop.
Since it will loop as often as the length of the string you can always just use the first letter of the string and remove it until the string is empty and the loop will end because the length you set for the loop to run ends the loop.

Related

Delete item from dictionary and Listbox

I have a program that puts the contents of a dictionary in a Tkinter Listbox, but I'm having trouble deleting it from the Listbox and the dictionary.
from tkinter import *
import ast
f = open("orders.txt", "r")
contents = f.read()
f.close()
things = ast.literal_eval(contents)
secondthing = [things, "test"]
root = Tk()
f = Frame(root).pack()
l = Listbox(root)
b = Button(root, text = "delete selection", command = lambda: delete(l))
b.pack()
l.pack()
for i, j in things.items():
oneitem = i + " " + j
l.insert(END, oneitem)
def delete(listbox):
global things
# Delete from Listbox
selection = l.curselection()
l.delete(selection[0])
# Delete from list that provided it
evaluater = l.get(selection[0])
value = eval(evaluater)
ind = things.index(value)
del(things[ind])
print(things)
root.mainloop()
When I try to delete something it gives me:
Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/tkinter/__init__.py", line 1883, in __call__
return self.func(*args)
File "/Users/mimmo/black_market/aaa.py", line 12, in <lambda>
b = Button(root, text = "delete selection", command = lambda: delete(l))
File "/Users/mimmo/black_market/aaa.py", line 28, in delete
value = eval(evaluater)
File "<string>", line 1
ohhh ohhhhh
^
SyntaxError: unexpected EOF while parsing
Can someone help me because I can delete it from the Listbox, I just have an error when deleting it from the dictionary.
The contents of orders.txt:
{"ayyy" : "ayyyyyy", "ohhh" : "ohhhhh"}
First of all, I would recommend using json or pickle to store contents of the dictionary - it's the most common practice. I don't really understand what do you want to do so I wrote a function which deletes an element from listbox and things by it's index.
An error you are getting is caused by eval function which tries to intepret your listbox item as python code. Of course, it's getting syntax error.
# Deletes element from listbox and thigs by it's index
def delete(listbox, index: int):
global things
item = listbox.get(index)
key = item.split()[0]
del things[key]
listbox.delete(index)

"can only concatenate str (not "int") to str" when zipping list of strings and list of objects

I get this error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Hunter\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1883, in __call__
return self.func(*args)
File "c:\Users\Hunter\Documents\Programming\Python Scripts\Scripts\spoolClient\menuScript.py", line 46, in <lambda>
updateJsonButton = Button(preferences, text="Save Preferences", command=lambda: updateJson())
File "c:\Users\Hunter\Documents\Programming\Python Scripts\Scripts\spoolClient\menuScript.py", line 17, in updateJson
for i, j in zip(entryNames, entry):
File "C:\Users\Hunter\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1643, in cget
return self.tk.call(self._w, 'cget', '-' + key)
TypeError: can only concatenate str (not "int") to str
When trying to run my script:
from tkinter import *
from tkinter.ttk import *
from tkinter import messagebox
from tkinter import filedialog
import qrMaker
import qrReader
import json
settings = {}
#define vars
preferencesSkippedRows = [1, 3, 5, 7, 9, 11]
def openPreferences():
def updateJson():
print("here")
for i, j in zip(entryNames, entry):
print("loopdie")
value = str(j.get())
settings[i]=value
settingsjson = json.dumps(settings)
print(settingsjson)
f = open("preferences.json","w")
f.write(settingsjson)
f.close()
preferences = Tk()
preferences.title("Preferences")
preferences.iconbitmap(qrMaker.getCurrentPath()+'icon.ico')
preferences.geometry('400x600')
topText = Label(preferences, width=30, text="Filament Spool Client Preferences")
cameraText = Label(preferences, width=30, text="Select Camera Instance:")
cameraEntry = Combobox(preferences, width=30, values=qrReader.getCameras())
qrWidthText = Label(preferences, width=30, text="QR Output Width (in.)")
qrWidthEntry = Entry(preferences, width=30)
qrHeightText = Label(preferences, width=30, text="QR Output Height (in.)")
qrHeightEntry = Entry(preferences, width=30)
text = [cameraText, qrWidthText, qrHeightText]
entry = [cameraEntry, qrWidthEntry, qrHeightEntry]
entryNames = ['cameraEntry', 'qrWidthEntry', 'qrHeightEntry']
updateJsonButton = Button(preferences, text="Save Preferences", command=lambda: updateJson())
for i in preferencesSkippedRows:
preferences.grid_rowconfigure(i, minsize=10)
topText.grid(column = 0, row = 0)
row=2
for text, entry in zip(text, entry):
text.grid(column = 0, row = row)
entry.grid(column = 1, row = row)
row+=2
updateJsonButton.grid(column=1, row=row+2)
preferences.mainloop()
openPreferences() #I call script.openPreferences() in my main program but I left this here for debugging purposes
I can see from the error message that the error occurs somewhere in the line that my zip function occurs, but I have no idea what causes this. Oddly enough, this error goes away if instead of setting updateJson equal to the command value of my Tkinter button state, I set updateJson, which calls the function right as the button object is initialized. I also know what the error is saying, I just don't know where an integer is coming from, and how I can fix this issue. Any help would be appreciated.
Update: I've just found that the actual zipping of the two lists is not the problem, but when I introduce the for loop, the same error occurs.
Answering to close out this thread, answer from "user2357112 supports Monica".
The issue in this script is that for text, entry in zip(text, entry) literally uses "entry" in the for loop, and is executed after the button instance is created, meaning that if updateJson is called during the button object initialization, then there will be no error thrown as entry is still defined as a list. However, after for text, entry in zip(text, entry) executes at startup, entry is now defined as the last object in the list entry, no longer the list entry itself. When the user presses the button and updateJson is called, an error is thrown as entry is not a list anymore(I'm not 100% sure on the error part).

Create automatically a certain numbers of Entrys - Tkinter/Python

I want to use Tkinter to write a code where the user can enter a number N. Depending on this number N the program automatically (i dont want to use any buttons) creates N-Entry rows.
My solution works partially:
from tkinter import *
root = Tk()
Label(root, text = "Enter Number of columns").grid(row = 0, column = 0)
N = IntVar()
e_N = Entry(root, textvariable = N).grid(row = 0, column = 1)
# Put trace callbacks on the Entry IntVar
def create_rows(name, index, mode):
rows = N.get()
for i in range(rows):
Entry(root).grid(row = i + 1, column = 0)
N.trace('w', create_rows)
# Setting the vars will trigger the trace
N.set(2)
mainloop()
When you run the code for the first time, it works fine. If you delete the number two and enter a new number, new lines are automatically created. However, an error message is displayed :
Exception in Tkinter callback
Traceback (most recent call last):
File "/home/anaconda3/lib/python3.7/tkinter/__init__.py", line 508, in get
return self._tk.getint(value)
_tkinter.TclError: expected integer but got ""
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/anaconda3/lib/python3.7/tkinter/__init__.py", line 1705, in __call__
return self.func(*args)
File "<ipython-input-97-2da00b5c0b50>", line 12, in create_rows
rows = N.get()
File "/home/anaconda3/lib/python3.7/tkinter/__init__.py", line 510, in get
return int(self._tk.getdouble(value))
_tkinter.TclError: expected floating-point number but got ""
This error is repeated as soon as the old number is deleted and a new one is entered.
Does someone know what is wrong and how to fix it?
Also as an extra: Only new lines can be created, i.e. if you first enter 5 and then 3, the last two lines are not deleted.
Edited code:
from tkinter import *
root = Tk()
Label(root, text = "Enter Number of columns").grid(row = 0, column = 0)
N = IntVar()
e_N = Entry(root, textvariable = N).grid(row = 0, column = 1)
# Put trace callbacks on the Entry IntVar
def create_rows(name, index, mode):
try:
rows = N.get()
except _tkinter.TclError:
""
for i in range(rows):
Entry(root).grid(row = i + 1, column = 0)
N.trace('w', create_rows)
# Setting the vars will trigger the trace
N.set(2)
mainloop()
Putting a trace on the value of N means it calls create_rows whenever it changes, including just after you deleted the original number, but before you type the new one. You could put N.get() inside a try/except, and only add new lines if the contents of the number entry are a valid integer. This will handle the deleted case when the value is an empty string, and also if someone types a non-number into the entry.

How would I copy the contents of a Listbox row in Tkinter which the user selects to the windows clipboard

So I want to make a Tkinter Listbox where if the user clicks (preferably double clicks) on a row the contents of that row would be copied to the clipboard.
Here is example code of what I need help with:
from tkinter import *
app = Tk()
def listbox_copy():
app.clipboard_clear()
app.clipboard_append(listbox[1])
listbox = Listbox(app)
list = ['string 1', 'string 2', 'string 3']
for c in list:
listbox.insert(END,c)
listbox.place(relx=0.5, rely=0.55, anchor="center")
listbox.bind('<<ListboxSelect>>', lambda event: listbox_copy())
app.mainloop()
Right now I'm getting this error:
File "C:\Users\elias\Desktop\test.py", line 14, in <lambda>
listbox.bind('<<ListboxSelect>>', lambda event: listbox_copy())
File "C:\Users\elias\Desktop\test.py", line 7, in listbox_copy
app.clipboard_append(listbox[1])
File "C:\Users\elias\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 1489, in cget
return self.tk.call(self._w, 'cget', '-' + key)
TypeError: can only concatenate str (not "int") to str
Thank you for any help.
You should get the selected item using listbox.get(ANCHOR) instead of listbox[1]. If you want to copy the selected item to clipboard when user double-clicks the item, bind <Double-Button-1> instead of <<ListboxSelect>>:
def listbox_copy(event):
app.clipboard_clear()
selected = listbox.get(ANCHOR)
app.clipboard_append(selected)
...
listbox.bind('<Doubld-Button-1>', listbox_copy)

How to pass a entry field value to a function

I am trying to make a GUI based encryption program using tkinter on python3. Here one option is to encrypt an Image now there is an entry field where the user will enter the mode, 1 for RGB and 0 for greyscale. Now I am trying to pass that entry field value to the encrypt and decrypt function which will execute upon pressing the corresponding button. But I am getting an error while I am passing the value to the function. The script where the buttons and the entry field is written, as follows:
global mode
def getvalue():
mode =int(mode_txt.get())
return mode
image_window = Tk()
image_window.geometry ( '350x200' )
image_window.title ('Image Cryptography')
lbl1 = Label(image_window, text = "Select mode(0 for greyscale/ 1 for RGB): " ).place( x=20, y=40 )
mode_txt = IntVar
mode_txt = Entry(image_window, width = 4) #the entry field
mode_txt.place(x= 300, y=40)
mode_txt.bind('<Return>', getvalue)
mode_txt.pack()
Now I am passing the mode like this:
def encrypt():
mode = getvalue()
if(mode == 0): #greyscale
#some code#
The buttons are like this:
btn_decrypt = Button( image_window, text = "Image Decryption", command = decrypt)
btn_decrypt.place( x=20, y=100 )
btn_encrypt = Button( image_window, text = "Image Encryption", command = encrypt)
btn_encrypt.place( x=200, y=100 )
btn_exit = Button( image_window, text = "Go Back" , command = goback).place( x=140, y=150 )
image_window.mainloop()
The error I am getting is:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib64/python3.7/tkinter/__init__.py", line 1705, in __call__
return self.func(*args)
File "image1.py", line 98, in decrypt
if(mode == 0):
NameError: name 'mode' is not defined
I don't know where I'm am going wrong? Any help will be appreciated. Thank you.

Categories

Resources