Python issue with CTRL-V in Tkinter Entry widget - python

In the Entry widget, I tried to restrict values to only hexadecimal using validatecommand and a function to verify if the entry value is in 'abcdef0123456789'. The problem lies in the fact that "CTRL+V" (Paste) doesn't work when I use it to insert value. There is no problem with "CTRL+C" and "CTRL+X" (Copy and Cut).
Is that a way to restrict the entry to hexadecimal value and in same time allow the use of CTRL-V to Paste/insert value?

Is that a way to restrict the entry to hexadecimal value and in same time allow the use of CTRL-V to Paste/insert value?
Yes. Arguably the simplest method is to use the validatecommand to check that all of the characters in the widget are hex digits. The validatecommand doesn't care how the characters are entered (typing vs cut/paste).
In the following example, '%P' tells tkinter to pass the new value of the entry widget if the edit is allowed. We can then use the re module to see if the new value is composed of only zero or more hex digits.
import tkinter as tk
import re
def validate(possible_new_value):
if re.match(r'^[0-9a-fA-F]*$', possible_new_value):
return True
return False
root = tk.Tk()
entry = tk.Entry(root, validate="key",
validatecommand=(root.register(validate), '%P'))
entry.pack(padx=20, pady=20)
root.mainloop()

Related

Hi , How can I change a string number from Entry of tkinter into int number?

Hi i'm a beginner in python and I really got int trouble with some methods, I wanna give some number from Entry of tkinter class and show them with a chart,
but the thing is that I cant get int number:
so the chart wont work [here is the picture of my code , I get some bumber from entry but i cant make them integer number]
1: https://i.stack.imgur.com/2Vuvn.jpg
2: https://i.stack.imgur.com/Pa23V.jpg
Welcome. I'm posting a complete, I think, answer to this question but there are a couple of etiquette things you should know:
Please don't post screenshots of your code. Copy and paste into the editor.
Please post just enough code to show your problem, but which is complete enough that we can just copy it into our own editors / IDEs and run without a lot of modification.
The previous commenters are correct that this question has probably been answered a hundred times, so please try to search through previous answers before posting your question.
Having said that, I have not answered this question before, so here's my rendition. I know you're a beginner so I've tried to keep it as simple as possible, but you're also tackling TKinter so I've not made it overly simplistic.
import tkinter as tk
def main():
global entryVar, lableVar
#create a tkinter window:
rootWin = tk.Tk() #creates a root window
rootWin.title('Entry Test') #shows text on the title bar
rootWin.geometry('500x200') #sets the displayable size of the window
#we'll need these variables and they MUST be tk.StringVar()
entryVar = tk.StringVar() #variable to hold the entry value
lableVar = tk.StringVar() #variable to hold the lable value
#create an entry widget:
entry = tk.Entry(
rootWin,
width = 5,
textvariable = entryVar
)
entry.pack(expand=1)
entry.bind('<Return>', getEntryValue) #bind enter key to widget
entry.bind('<KP_Enter>', getEntryValue, add='+') #bind the other enter key to widget
#create a lable widget
lable = tk.Label(
rootWin,
textvariable = lableVar
)
lable.pack(expand=1)
lableVar.set("This is where the lable is.")
entry.focus_set() #set focus on the entry widget for convenience
rootWin.mainloop()
def getEntryValue(event):
global entryVar, lableVar
x = entryVar.get() #get the value from Entry
x = int(x) #change it to an int
lableVar.set(x) #set the lable variable
entryVar.set("") #clear the entry variable
if __name__ == "__main__":
main()
So, what's going on here is that we make a window in the usual way. I've created both an Entry() widget to get some input, and a Label() widget to show whatever has been input. I've broken the Entry() and Label() declarations up over multiple lines just to make them easier to read.
You can attach variables to many TKinter widgets to that you can .get() and .set() their values more easily, but they almost always need to be TKinter variable types such as StringVar() or IntVar(). I've created two such variables, one for the Entry() widget and another for the Label() widget.
I've also added "bindings" to the Entry() widget to both show how that works and to make data entry a bit more convenient. I don't know if you have a separate number pad on your computer keyboard so I've bound both the main <enter> key as well as the number pad's <enter> key. When you hit either one of those keys, the Entry() widget will call the getEntryValue() function which does the work of getting the value and displaying it on the window.
For convenience, entry.focus_set() immediately puts the focus on the Entry() widget, then the TKinter window enters the .mainloop() to do its stuff.
The getEntryValue() function is called by the events which we set on the Entry() widget. I broke it down into more lines than necessary to illustrate what needs to happen. First we retrieve the value of the Entry() widget through its variable, entryVar. You do that using entryVar's .get() method: x = entryVar.get(). That returns a string value which you will have to convert to an integer using the normal int() function available in Python. For this purposes of this demonstration I've chosen to display that value to a Label() widget which I've placed in the window, so I use the Label() widget's variable lableVar: lableVar.set(x). You don't have to convert the integer back into a string before doing this.
I then clear out the entryVar variable so that there isn't anything left in the Entry() widget to get in the way of our next entry.
I've used entryVar and lableVar as globals just to simplify the example.
And that's how you do it.
I guess the problem is here:
a=str(e3.get())
Try something like this:
a=int(e3.get())
Since what you want is an integer

Adding and updating new widget in tkinter in runtime

I am trying to build a GUI creator using Python and Tkinter, but ran into a problem.
My problem is How to add\update widgets in runtime?
for example:
I have created the main window.
In that main window, I have created a frame name w_frame which contains a bunch of widget.
Based on my input in the Text or Entry widget beside the w_frame, I want to update a particular widget.
Lets say w_frame contains a Entry widget, radio button, button and label all available with the basic or main attributes need to display it.
Now I want to change the background color of label.
In short I want to write the code label_name.property_name=value or for example a_label.bg=red in the text widget and as soon as I press apply button, the widget should change.
I have searched on web, but not able to find the required solution. Also tried using How can i update a certain widget in tkinter, but that does not work depending on my input.
from tkinter import *
root=Tk()
w_frame=Frame()
w_frame.pack()
def update_Frame():
a=u_text_wid.get("1.0",END)
b.config(a)
root.update()
def add_wid_in_frame():
global a,b
a=Button(w_frame,text='heelo')
a.pack()
b=Label(w_frame,text='heelo')
b.pack()
u_text_wid=Text()
u_text_wid.pack()
button1=Button(text="add",command=add_wid_in_frame)
button1.pack()
button1=Button(text="update",command=update_Frame)
button1.pack()
root.mainloop()
this results me in an error
unknown option "-bg="red"
Note:
I want to update the widget based on the property value provided by the user, so it wont be hard-code into the script.
You are getting the error because every thing you retrieve from Text widget is a string and you cannot directly pass an string to .config method, you need a keyword and then you can assign value which can be string.
According to your question and the comments on the question, what i have figured out is:
You want to run lable.config(bg='red') from the Text widget.
You want to change the property of specific widget.
Here's what you can do:
To run Tkinter code form Text widget, you can use:
getattr method
eval method
Just to change property of widget:
def update_Frame():
global bcd
a = u_text_wid.get("1.0", "end-1c")
b=a.split(",")
c=[tuple(i.split("=")) if "=" in i else i for i in b]
d=dict(i for i in c)
for key,value in d.items():
bcd[key]=value
We can use string to change property only in this format widget_name[key]=value.
Some Useful Links:
Eval()
Getattr()
For your case, you can use ast.literal_eval() to convert a JSON string to dictionary and use the dictionary in .config():
from ast import literal_eval
...
def update_Frame():
a = u_text_wid.get("1.0", "end-1c") # don't include ending newline
cnf = literal_eval(a) # convert JSON string to dictionary
b.config(cnf)
Example input of the JSON string:
{"fg":"yellow", "bg":"red"}
Note that you can also use json module to convert the JSON string as well.

How to register values to ttk.Spinbox via keyboard entry?

Can a ttk.Spinbox widget allow a user to type in values to it's entry field and have it registered? If so, how can I do so?
I am aware that it is possible to use the .set() method on the ttk.Spinbox's textvariable to alter its value. But this isn't what I was thinking off. Instead, I would simply like to allow the user to click on the ttk.Entry widget of the ttk.Spinbox and manually type in values there and have it registered to its textvariable. Presently, I can type in values there but nothing happens when I press the Return key.
Thank you.
Can a ttk.Spinbox widget allow a user to type in values to it's entry field and have it registered? If so, how can I do so?
If you associate a variable with the textvariable attribute, there's nothing else you need to do. Anytime the user changes the value, whether by the arrows or by typing into the editable portion of the widget, the value in the variable will instantly be updated.
You can verify this yourself by creating a spinbox and a label, both associated with the same variable. You can then see the label being updated in real time when you edit the spinbox.
Example:
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
spinvar = tk.IntVar()
spinbox = ttk.Spinbox(root, from_=0, to=100, textvariable=spinvar)
label = ttk.Label(root, textvariable=spinvar)
spinbox.pack()
label.pack()
root.mainloop()
Presently, I can type in values there but nothing happens when I press the Return key.
If you want something to happen when the user presses the <Return> key, you have to add a binding to call a function.
Example:
def do_something(event):
print("do something:", spinvar.get())
spinbox.bind("<Return>", do_something)

Tkinter Focusout Entry Validation

I have seen several questions on tkinter entry validation here but each one seems to stick to validate="key" option.
While this is great for interactive validation, what i want is a "focusout" validation.
More particularly I am looking to validate an email field. Here's the code I have tried so far but it doesn't work.
import Tkinter as tk
import re
master = tk.Tk()
def validateEmail(P):
x = re.match(r"[^#]+#[^#]+\.[^#]+", P)
return (x != None)
vcmd = (master.register(validateEmail), '%P')
emailentry = tk.Entry(master, validate="focusout", validatecommand=vcmd)
emailentry.pack()
b = tk.Button(master, text="Login")
b.pack()
tk.mainloop()
Any ideas on how to validate email entry please ?
%S represents the string being inserted, if any. This is only meaningful for validation on text insertion. When the widget loses focus, no character is being inserted so this parameter will always be an empty string. Since it is an empty string, it will always fail your validation.
You should use %P instead, which represents the whole string.
Also, strictly speaking, the validation function should return a boolean rather than an object. You should save the result of the match in a variable, then return something like return (match is not None)

Making Entry widget "disabled" like in windows calc

I've got a problem with Entry widget while making a copy of Windows Calc.
I have made buttons like in windows calc and I also bind the keyboard 1234567890 + - / * % buttons, to make the same things as the calc buttons.
The mainly problem was that I wanted the Entry to store only numbers and let user input only numbers... but after searching many topics about validatecommand and also looking at windows calc I decided that validatecommand isn't the thing I need - I don't know how to make it validate every character the user inputs to the entry box and after making the keyboard binds, when I am in entrybox and press "1" to write the number it does it two times, because the keyboard event binding inserts the "1" to the entry box too.
So, the thing I want to make is to make entry widget work like the Windows Calc.exe entry box.
The windows calc entry box doesn't let you insert any other character then numbers and also doesn't let you to put your cursor into the entry box...,
it looks like this:
-entrybox is disabled BUT it looks like ENABLED
-numbers and operations can be made by calc buttons or by keyboard buttons
I tried getting this effect by disabling the entry widget at start, and making all buttons functions like that:
-enable the entry widget
-insert the number (the widget must be in enabled? or normal? (don't remember the name) state to let you insert something to it)
-disable the entry widget
It works like I want... but it doesn't look like I want it to look. Is there any possibility to change Entry widget disabled bg color to normal?
Or maybe is there another way to make such entry box? :S
The way to do it is with the validatecommand and validate options of the entry widget. This scenario is precisely what those features are for.
You say you "don't know how to make it validate every character the user inputs to the entry box". If you set the validate attribute to "key", that will cause your validate command to be called on every keypress.
Unfortunately, this is a somewhat under-documented feature of Tkinter, though it's documented quite well for Tk. Here's a working example which performs some very rudimentary checks:
import Tkinter as tk
class SampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
# define a command to be called by the validation code. %P
# represents the value of the entry widget if the edit is
# allowed. We want that passed in to our validation comman so
# we can validate it. For more information see
# http://tcl.tk/man/tcl8.5/TkCmd/entry.htm#M7
vcmd = (self.register(self._validate), '%P')
e = tk.Entry(self, validate="key", validatecommand=vcmd)
e.pack()
def _validate(self, P):
# accept the empty string, "." or "-." (to make it possible to
# enter something like "-.1"), or any string that can be
# converted to a floating point number.
try:
if P in (".", "-", "-.", ""):
return True
n = float(P)
return True
except:
self.bell()
return False
app=SampleApp()
app.mainloop()
If you search this site for [tkinter] validatecommand you'll find many other examples.

Categories

Resources