I'm using PySimpleGUI in which I want to update a radio button. According to the documentation the radio button has an update method. But somehow it doesn't work properly.
I wrote the following code which should update the value of the radio button from Test to NewTest. The result is still Test.
Code used below:
import PySimpleGUI as sg
layout1 = [[sg.Radio('Test', "RADIO1", key='_RADIO1_', default=True, font=50)],
[sg.Button('Ok', font=50), sg.Button('Stop', font=50)]]
window = sg.Window('Read').Layout(layout1).Finalize()
while True:
window.Element('_RADIO1_').Update('NewTest')
button, values = window.Read()
exit()
Sounds like you're trying to change the text that's next to an specific radio button.
The problem is that each of the PySimpleGUI Elements has a slightly different Update method. Simply put, the things you can change in a Radio Element are:
Update(self, value=None, disabled=None, visible=None)
While the documentation on the Radio Button element's Update is brief in the documentation, it is described there https://pysimplegui.readthedocs.io/#radio-button-element
Update(value=None, disabled=None, visible=None)
value - bool - if
True change to selected
disabled - if True disables the element
There are 3 things you can currently change in a Radio button, the "state" (true/false), disabled and visibility.
I would suggest logging this as a feature request Issue on the GitHub site (http://www.PySimpleGUI.com). These requests are often implemented quite quickly.
Related
I have an entry field, and as I type into the data field, I want a method, that updates a treeview widget to be ran. Currently, I can type in a search parameter, then press a 'search' button and it will run the method to search through the treeview to find specified clients, but I want to the treeview to be updating whilst typing into the entry, not by a button press
I am unsure as to weather this is possible, if it should be doing by binding keys or if there is a way using the event loop to achieve this?
See this SO post:
TkInter keypress, keyrelease events
Essentially:
from Tkinter import *
def keyup(e):
pass;
# e.char contains the pressed key if you need that info
# use your search function here
Edit (Sorry I forgot this):
You'll need to bind the keyup function to your widget with something like:
frame.bind("<KeyRelease>", keyup) # you can also bind to a search widget
The following code displays a window with a button and tree view. A handle for the 'clicked' signal is attached to the button and focuses the tree view. When the window is initially displayed, the tree selection has no selected items, but when the tree view receives focus, the first item is automatically selected. Is there a way to keep a selection from being made when the tree view receives focus?
Before click, button has focus and tree selection has no selected items. After click, tree view has focus, but an item has been selected.
The issue that arises from this is that I have an interface that keeps some things in sync by attaching to the 'changed' signal on the tree selection of the tree view. When the window is displayed, depending on where the tree views are in the interface, they may receive focus by default. That causes a 'changed' signal, and unexpected synchronization happens. It's possible to call set_can_focus(False) for all the tree views, but that:
only prevents keyboard cycling focus, not programmatic focus, and the selection still turns on with programmatic focus; and
seems to disable the ability to deselect a selection (e.g., by control-clicking on a row).
Similarly I can use grab_default to ensure that something else gets focus first when the window is displayed, but it doesn't keep a stray focus event from making an unexpected selection.
Based on a posted answer that says that says that selection mode SINGLE "requires at least one item to be selected", and that that explains why an element is selected on focus, I looked more into the selection mode constants. Of these, SINGLE and BROWSE seem most relevant. The pygtk documentation, GTK Selection Mode Constants, only says that:
gtk.SELECTION_SINGLE A single selection allowed by clicking.
gtk.SELECTION_BROWSE A single selection allowed by browsing with the pointer.
The GTK+3 documentation, enum GtkSelectionMode, goes into a bit more detail:
GTK_SELECTION_SINGLE Zero or one element may be selected.
GTK_SELECTION_BROWSE Exactly one element is selected. In some
circumstances, such as initially or during a search operation, it’s
possible for no element to be selected with GTK_SELECTION_BROWSE. What
is really enforced is that the user can’t deselect a currently
selected element except by selecting another element.
I don't see anything here to suggest that at least one element must be selected when the selection mode is SINGLE.
Here's code to reproduce the window and serve as an example.
from gi.repository import Gtk
# A ListStore with some words
list_store = Gtk.ListStore(str)
for selection in "Can a machine think?".split():
list_store.append([selection])
# A TreeView with a single column
tree_view = Gtk.TreeView(model=list_store)
cell_renderer = Gtk.CellRendererText()
tree_view_column = Gtk.TreeViewColumn(cell_renderer=cell_renderer,text=0,title='Words')
tree_view.append_column(tree_view_column)
# A button to focus the list
focus = Gtk.Button(label='Focus List')
focus.connect('clicked',lambda *_: tree_view.grab_focus())
# A Box to hold everything, and a Window for the Box.
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
box.add(focus) # button on top gets initial focus
box.add(tree_view) # tree_view below doesn't, and has no selected items
window = Gtk.Window()
window.add(box)
window.show_all()
Gtk.main()
Looking at the source in root/gtk/gtktreeview.c for tree_view.grab_focus(), we can see that gtk_tree_view_focus_to_cursor always gets called, and selects the first element. You can work around this, in some cases, though.
This is a nasty hack.
It overrides the grab_focus method, stores the selection before calling grab_focus, and clears the selection afterwards if there was no selection before.
def tree_view_grab_focus():
selection = tree_view.get_selection()
_, selected = selection.get_selected()
Gtk.TreeView.grab_focus(tree_view)
if selected is None:
selection.unselect_all()
tree_view.grab_focus = tree_view_grab_focus
Unfortunately it only applies when calling grab_focus from Python, other callers (such as GTK's keyboard navigation) don't.
I am making a box that is similar to the tkMessageBox. There are two simple behaviors that I want to the box to have. First I want the button to be selected automatically when the window opens, and second I want to be able to press enter to push the button. Sounds simple and I realize that I could use the tkinterMessageBox to do this same thing, but this is a stepping stone, and I would like to know how to do this in the future for other things.
The current behavior of the window below is that it opens, and if I press tab it will select the button, but then i can only press the button with the mouse. Again the desired functionality is to have the button selected right away and be able to press the button with the enter key.
import Tkinter, tkMessageBox
from Tkinter import *
def closewindow():
Messagebox.destroy()
Messagebox=Tk()
l3=Label( Messagebox, text="This is your preview! Align camera then press ESC")
b3=Button(Messagebox, text="Okay", command=closewindow)
l3.grid(row=1,column=1)
b3.grid(row=2,column=1)
Messagebox.mainloop()
You can actually do this with just two lines of code:
b3.bind('<Return>', lambda _: closewindow())
b3.focus_set()
The first binds the button to the Enter key and the second sets the application's focus on the button.
Note that I had to use a lambda with the binding to handle the event object that will be sent to the callback. You could however change the definition of closewindow to handle this:
def closewindow(event=None):
Messagebox.destroy()
Now you can just do:
b3.bind('<Return>', closewindow)
For more information on bindings in Tkinter, see Events and Bindings over on Effbot.
I have the following problem when using tkinter to create a very simple window containing a matrix of buttons: When one of the buttons is clicked, the event handler changes the text of that button using the configure method on the button widget. This works. But I also want to change the text in one of the other buttons, which does not work. The method I use is that on creating the button, I store the object returned by the Button method before I use the grid geometry manager to place it. This object looks like ".123456789L" when printed and seems to be a pointer to the widget. I also use configure on this to change the button text. But somehow it seems to be wrong, because it works sometimes, and most of the times not. There's unfortunately no error message, just nothing happens when calling configure. I checked and it seems to be the correct pointer to the widget. Do I have to use a special way to affect a widget other that the one that called the event handler? These are the relevant parts of the code:
# CREATING THE BUTTONS:
buttons={} # global
for i in range(3):
for j in range(3):
button = Tkinter.Button(self,text='foo')
buttons[button]=(i,j)
button.grid(column=j,row=i)
button.bind( "<Button-1>", self.OnButtonClick )
# CHANGING BUTTONS:
def find_button(i,j):
"""Return the pointer to the other button to be changed when a button has been clicked."""
for button,key in buttons.items():
if key==(i,j): return button
def OnButtonClick(self,event):
print "You clicked the button",buttons[event.widget]
i,j=buttons[event.widget]
old_button=find_button(i,j) # This is simplified, I don't actually pass i,j, but other values. But I checked this and it returns the reference to the correct button. But this simplified version works the same way, just assume a different button that the one pressed would be returned.
old_button.configure(text = 'blabla') # THIS DOES NOT WORK
event.widget.configure(text = 'something') # THIS WORKS
I have the same problem and i solve it with:
buttons[button]=(i,j,button)
and in the function OnButtonClicK:
i,j,old_button=buttons[event.widget]
old_button.configure(text = 'blabla') # THIS DOES NOT WORK
goal
Understanding how a radiobutton in a Tkinter menu works
code
I have a radio button inside the options menu as so:
v = BooleanVar()
v.set(True)
options.add_radiobutton(label="change pop up", command =togglePopUp,variable=v,onvalue=True,offvalue=False)
togglePopUp is a function that changes the value of variable v from True to False or vice versa. Main window is already opened and this menu will be added later to the window. This is just the fragment of code that is related to the radiobutton.
Question
Now my question is when I press the radiobutton (after running the code) will the value of the variable be changed or will the function togglePopUp be called? If the function will be called then what will happen to the status of the radiobutton? will the status of the radiobutton be updated instantly or will there be a delay?
research
I read about the radiobutton and the Boolean variable from the Tkinter book at effbot.org. But I was not convinced about how it worked. I tried a program but I am not getting the output that I essentially want. So I decided to understand how it works at a deeper level.
specs python 2.7 Tkinter 8.5
Linux Mint 14
Both actions will occur. When you click on a radiobutton, first the variable will change its value, and after that the event handler passed as command option is called if present.
Also your example would not work, since add_radiobutton doesn't allow the onvalue and offvalue options - only value.