I had to use an Entry widget in the 'readonly' state, then I wanted to change the text with the insert method : to do so, I understand that it is needed to put the widget in the state 'normal', but I get an error : is that "normal"?
For instance,
entry = ttk.Entry(root,width=30)
entry.insert(0,"Please enter your name")
entry.state(['readonly'])
entry.state(['normal'])
Gives me as a result :
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/tkinter/ttk.py", line 595, in state
return self.tk.splitlist(str(self.tk.call(self._w, "state", statespec)))
_tkinter.TclError: Invalid state name normal
Confusingly, ttk widgets have two different concepts of "state". One is a configuration option named state, and one is a method named state. The configuration option is a shorthand to change the editability of the widget. The method is used to get and set several internal states used for styling.
These two ways of specifying state accept different values. The "readonly" state is one state that is valid on both, but "normal" is only valid for the configuration option.
To use the state method, you pass in a stateSpec which is a list of one or more states or negated states. For example, to switch between readonly and not readonly you would do it this way:
entry.state(["readonly"])
entry.state(["!readonly"])
This manner of specifying a widget state is much more flexible and fine-grained, and is designed to allow complex styling. For example, a widget can at one time be in the states readonly, disabled, invalid, and hover.
The simpler way to configure whether the widget is editable or not is with the state configuration option. It must always be one of the string values "normal", "disabled", or "readonly".
entry.configure(state="readonly")
entry.configure(state="normal")
The allowable values for the configuration option are fairly self-explanatory. The values for building up a stateSpec via the state method are the following:
active - The mouse cursor is over the widget and pressing a mouse button will cause some action to occur. (aka “prelight” (Gnome), “hot” (Windows), “hover”).
disabled - Widget is disabled under program control (aka “unavailable”, “inactive”).
focus - Widget has keyboard focus.
pressed - Widget is being pressed (aka “armed” in Motif).
selected - “On”, “true”, or “current” for things like checkbuttons and radiobuttons.
background - Windows and the Mac have a notion of an “active” or foreground window. The background state is set for widgets in a background window, and cleared for those in the foreground window.
readonly - Widget should not allow user modification.
alternate - A widget-specific alternate display format. For example, used for checkbuttons and radiobuttons in the “tristate” or “mixed” state, and for buttons with -default active.
invalid - The widget's value is invalid. (Potential uses: scale widget value out of bounds, entry widget value failed validation.)
hover - The mouse cursor is within the widget. This is similar to the active state; it is used in some themes for widgets that provide distinct visual feedback for the active widget in addition to the active element within the widget.
Related
As per PyQt5 doc it is said
PySide2.QtWidgets.QWidget.winId()¶
Return type
WId
Returns the window system identifier of the widget.
Portable in principle, but if you use it you are probably about to do something non-portable. Be careful.
If a widget is non-native (alien) and is invoked on it, that widget will be provided a native handle.
This value may change at run-time. An event with type WinIdChange will be sent to the widget following a change in window system
identifier.
But my question is,does it change any widget's original winId?If yes, how to get the new and old?
I have an Entry widget on a simple calculator. The user can choose to enter an equation via the keypad. I was wondering if there was a way to detect a character(from the keypad in my case) being typed into the Entry widget. So, focus is on the widget, user presses '4', it comes up on the widget... can I detect this act, for basic purposes of logging the input?
Every time you press a key inside a Tkinter window, a Tkinter.Event instance is created. All you need to do is access that instance. Here is a simple script that demonstrates just how:
from Tkinter import Tk, Entry
root = Tk()
def click(key):
# print the key that was pressed
print key.char
entry = Entry()
entry.grid()
# Bind entry to any keypress
entry.bind("<Key>", click)
root.mainloop()
key (being a Tkinter.Event instance) contains many different attributes that can be used to get almost any type of data you want on the key that was pressed. I chose to use the .char attribute here, which will have the script print what each keypress is.
Yes. There are a few different ways to do this, in fact.
You can create a StringVar, attach it to the Entry, and trace it for changes; you can bind all of the relevant events; or you can add a validation command that fires at any of several different points in the sequence. They all do slightly different things.
When a user types 4, there's a key event with just the 4 in it (which doesn't let you distinguish whether the user was adding 4 to the end, or in the middle, or replacing a whole selected word, or…), and then a modification event is fired with the old text,* and then the "key" or "all" validation function is called with the (proposed) new text, and the variable is updated with the (accepted) new text (unless the validation function returned false, in which case the invalidcommand is called instead).
I don't know which one of those you want, so let's show all of them, and you can play around with them and pick the one you want.
import Tkinter as tk
root = tk.Tk()
def validate(newtext):
print('validate: {}'.format(newtext))
return True
vcmd = root.register(validate)
def key(event):
print('key: {}'.format(event.char))
def var(*args):
print('var: {} (args {})'.format(svar.get(), args))
svar = tk.StringVar()
svar.trace('w', var)
entry = tk.Entry(root,
textvariable=svar,
validate="key", validatecommand=(vcmd, '%P'))
entry.bind('<Key>', key)
entry.pack()
root.mainloop()
The syntax for variable trace callbacks is a bit complicated, and not that well documented in Tkinter; if you want to know what the first two arguments mean, you need to read the Tcl/Tk docs, and understand how Tkinter maps your particular StringVar to the Tcl name 'PY_VAR0'… Really, it's a lot easier to just build a separate function for each variable and mode you want to trace, and ignore the args.
The syntax for validation functions is even more complicated, and a lot more flexible than I've shown. For example, you can get the inserted text (which can be more than one character, in case of a paste operation), its position, and all kinds of other things… but none of this is described anywhere in the Tkinter docs, so you will need to go the Tcl/Tk docs. The most common thing you want is the proposed new text as the argument, and for that, use (vcmd, '%P').
Anyway, you should definitely play with doing a variety of different things and see what each mechanism gives you. Move the cursor around or select part of the string before typing, paste with the keyboard and with the mouse, drag and drop the selection, hit a variety of special keys, etc.
* I'm going to ignore this step, because it's different in different versions of Tk, and not very useful anyway. In cases where you really need a modified event, it's probably better to use a Text widget and bind <<Modified>>.
If you just need to do simple things without using trace module you can try
def objchangetext(self, textwidget):
print(textwidget.get()) #print text out to terminal
text1 = tk.Entry(tk.Tk())
text1.bind("<KeyRelease>", lambda event, arg=(0): objchangetext(text1))
I'm using Tkinter for a small Python application. It has a set of ratio buttons, a text box, and a button. Is there a way to make it so the user can simply press Enter/Return on a keyboard and run the same function the button runs? The text box stays selected even when a radio is changed, so that won't cause any problems.
You should be able to bind an event handler to either the text box widget or the whole application that will be called when the event happens. Assuming you have a function to handle the event, something along the lines of:
widget.bind('<Return>', event_handler)
You can also bind a handler function at the application level by calling the bind_all() method of any widget, e.g.:
self.bind_all('<Return>', self.event_handler)
Note the key name is Return not Enter. See Key Names for a list of them all. You can also prefix the key name with a modifier like Shift- and Control- if desired.
There's a decent online reference for tkinter 8.4 here.
I am having a problem configuring a listbox widget such that the selection remains highlighted even while it is set (programmatically) to the DISABLED state. Below code shows the problem:
from Tkinter import *
master = Tk()
listbox = Listbox(master)
listbox.pack()
listbox.insert(END, "Text1")
listbox.insert(END, "Text2")
listbox.insert(END, "Text3")
listbox.selection_set(first=0, last=None)
listbox.configure(exportselection=False)
listbox.configure(state=DISABLED)
Now when I change state to NORMAL, selected item is being highlighted. Is there a way I could disable widget (i.e. No response on mouse clicks) but keep the selected object remain highlighted?
Intent:
I want to utilise this widget on wizard App that I am creating. I would like this widget to indicate the current page / wizard number which the user selected. Is there any other widget I could use instead of it? (Labels possibly?)
You can leave it enabled but remove or override all of the default bindings; that would give you the effect that you want.
You can remove all the default bindings by removing the "Listbox" bindtag, or by adding your own bindings that override the default ones.
Here's how to set the bindtags so that all of the standard Listbox bindings are removed:
listbox.bindtags((listbox, master, "all"))
On OS X, ttk.Style().configure('TLabelframe.label', font='helvetica 14 bold') works to change the font used by the ttk.LabelFrame widget. On Windows, ttk.Style().configure('TLabelframe.label', font='arial 14 bold') has no effect other than returning the same font info to ttk.Style().lookup('TLabelframe.label','font').
I've tried different font names and formats, creating a derived style, using TkDefaultFont and just changing the size, and different widgets (TButton.label, TCheckbutton.label). So far, no matter what I've tried, it always appears to use TkDefaultFont in the default size.
Changing the font setting in python27/tcl/tk8.5/ttk/xpTheme.tcl (the default theme on windows) does change the font being displayed. Removing the -font TkDefaultFont setting from the theme settings does not change what is displayed.
Any suggestions as to how this actually works?
Edit: I hadn't tried changing the font for the Label widget before, and that one actually works.
I believe the code in this area is buggy and will open a ticket. Using 'TLableframe.Label' (note uppercase 'L' in 'Label' works. 'TButton.label' and 'TButton.Label' don't work, but just 'TButton' does; 'TCheckbutton' is the same. I was unable to change the fonts for 'TEntry' with any combination, including adding 'textarea.'
It looks like for ttk.LabelFrame, you have to create a separate ttk.Label widget, and then assign it to the LabelFrame using the labelwidget= operand. You can set whatever font/style on the Label widget that you desire and that will be reflected in the LabelFrame. Note, you don't call the geometry manager for the Label widget. Just instantiate it, then assign it to the LabelFrame.
This also means that you can assign almost any widget you want, such as a ttk.Checkbutton, if you wanted to control the state of child controls within the LabelFrame. You'd have to write the code for this, but visually, it'd enable/disable the child controls based on the state of the Checkbutton.
Source: http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/ttk-LabelFrame.html