How to disable multiselection on Treeview in tkinter - python

I've a Treeview widget, and I need only one row/item to be selected at a time. I've been reading the doc, but I can't find any property or method to do so, nor I've found something useful on SO.
Is it posible? How to?

The answer is a bit higher up the page:
selectmode
Controls how the built-in class bindings manage the selection. One of “extended”, “browse” or “none”. If set to “extended” (the default), multiple items may be selected. If “browse”, only a single item will be selected at a time. If “none”, the selection will not be changed.
Note that the application code and tag bindings can set the selection however they wish, regardless of the value of this option.
Setting selectmode="browse" should give the behavior you're asking for.

Related

is there a way to set a default button color (on click) for tkinter?

i'm using "activeforeground" in order to make it so that when i click a button the text turns "misty rose." however, i want to apply this to all the buttons in my code without combing through and changing every single one. is there a way to set this as the default "activeforeground" color? similarly to how you can change the default font of text by using this:
root.option_add("*font", "times 14 bold")
if there is an equivalent for "activeforeground" i would appreciate the help!
The name to use with option_add isn't always exactly the same as the option used when directly configuring the widget. You need to use the "database name" which typically uses camelCase.
You can get the database name by reading the original tcl/tk documentation, or by calling the configure method on the given option. It returns a list of five items. The second item is the name to use with the option database.
In this specific case, you need to use activeForeground rather than activeforeground.
For more information on what configure returns see What are these strange options returned by the method configure?

wxPython - Disable a whole menu

I have come across a problem while using wxPython lately: I want to grey out a whole wx.Menu and I can't find a way to do it. I could disable all the wx.MenuItem instances related to the wx.Menu, but I find it less efficient ergonomically speaking than greying out the menu itself.
The wx.Menu class has a method named Enable() which accepts the 'enable' argument, but its solely use is to enable/disable a related wx.MenuItem and not the wx.Menu itself. Actually, I'm not even sure that what I want can be done.
However, I would be glad to listen to your solutions if you have some.
Enable is just for the menu items. EnableTop should counter-intuitively disable the entire menu. See my old tutorial on menus about half-way down for more info. Here's how I did it:
self.menuBar.EnableTop(0, False)
Note that it's zero-based, so zero is the first menu, one is the second, etc.

The order of wxPython events is causing me problems

My GUI consists of a wx.ListCtrl on the left, with a list of objects to edit, and a set of wx.TextCtrls on the right, for editing the selected object.
My strategy for implementing this was:
On a textbox's wx.EVT_KILL_FOCUS , update the relevant attribute of the currently selected object
On the list's wx.EVT_LIST_ITEM_DESELECTED, either hide the textboxes or blank them out and disable them (needed for when the user clicks the blank space in the list control)
On the list's wx.EVT_LIST_ITEM_SELECTED, populate the text controls with the values of the selected object's attributes
With this setup, there are 3 use cases, and 2 of them work:
When the user is clicking/tabbing between textboxes, the correct wx.EVT_KILL_FOCUSs occur, and the attributes get updated.
When the user clicks from a textbox into the blank space in the list, that's OK as well: first wx.EVT_KILL_FOCUS causes the attribute to update, and then wx.EVT_LIST_ITEM_DESELECTED hides the textboxes.
The problem is when the user clicks directly from a textbox to another object in the list control. The order of events in this case is wx.EVT_LIST_ITEM_DESELECTED, wx.EVT_LIST_ITEM_SELECTED, and then finally wx.EVT_KILL_FOCUS. You can probably see the problem: by the time the method that updates attributes is called, a new object has already been selected and the textboxes have been populated with new values.
So I know exactly what the problem is, but I can't come up with a nice, clean way to fix it. Ideally I'd like to be able to change the order of the wx events (putting wx.EVT_KILL_FOCUS at the front), but I doubt that's possible. Is there some other obvious solution I'm missing?
wx.EVT_LIST_ITEM_DESELECTED will only fire when the user changes the selected object in the list box. This serves the same purpose as losing focus on the text box. Call the update routines from that event as well. To skip the subsequent wx.EVT_KILL_FOCUS from the text box set a "isDirty" attribute in the parent object after you update the attributes. You can check the isDirty value anytime to confirm there are changes to commit. This attribute would have to be reset when you populate the text boxes for the new selection and then set during other textbox events.
It looks to me like you are trying to re-implement from scratch the functionality of wxListbook. It seems like a lot of work, perhaps you can use wxListbook
to do what you need.
http://docs.wxwidgets.org/2.9.4/classwx_listbook.html

gtk logic behind treeviewcolumns needing cell renderers

From what I understand about GTK, if I have a TreeView, I can't just use any widget I want to display information about a column. For text, you need a gtk.CellRendererText. For toggle buttons, a gtk.CellRendererToggle. For anything else, it seems you have to implement yourself, which, from a sample one for buttons that I saw, doesn't look straightforward.
Firstly, is this the case? Is there an easy way to set up whatever widget you want to be used to display some text? If not, then why is it implemented this way? If I were designing GTK i would just create some sort of system where when a row was added and when some data model information changes, user-specified callbacks would be called which would add the appropriate widget or change it, respectively.
To write a custom CellRenderer (copy-pasted from this link!):
Register some new properties that your
renderer needs with the type system
and write your own set_property and
get_property functions to set and get
your new renderer's properties.
Write your own cell_renderer_get_size
function and override the parent
object's function (usually the parent
is of type GtkCellRenderer. Note that
you should honour the standard
properties for padding and cell
alignment of the parent object here.
Write your own cell_renderer_render
function and override the parent
object's function. This function does
the actual rendering.
And there is a good/simple example for pyGTK.
Writing a custom CellRenderer is not too hard, the hardness is that how to write a custom widget. If you have learned how to write a custom widget, then writing a custom CellRenderer is easy.
The logic behind this design is flexibility. A TreeViewColumn indicates how the data (from a TreeModel) should be displayed by a CellRenderer, thus a TreeViewColumn which represents a value of boolean type, can be displayed as a text (CellRendererText) or can be displayed as a check box (CellRendererToggle). e.g. a TreeViewColumn which represents a value of integer type, can be displayed as a text (CellRendererText) or can be displayed as a progress bar (CellRendererProgress) or can be displayed as a spin button (CellRendererSpin) or can be displayed as everything that we want.

wxpython: How do I examine dragged data in OnDragOver?

I'm a bit perplexed by drag and drop in wxPython (but perhaps this questions pertains to drag and drop in other GUI frameworks as well). The frameworks provides a couple of callbacks (OnEnter and OnDragOver) that purportedly allow me to inform the system whether the current mouse position is a valid place to drop whatever it is that is being dragged. From these methods I can return wx.DragNone, wx.DragCopy, etc. What baffles me is that from within these methods I am not allowed to call GetData, which means I am not allowed to examine the data that the user is dragging. If I cannot see the data, how am I supposed to know whether it is OK for the user to drop here?
One solution, which is a hack of limited usefulness, is when a drag is initiated, store the dragged data in a global or static reference somewhere. This way, in the OnEnter and OnDragOver handlers, it is possible to get a reference to the data being dragged. This is of course only useful for drags within the same application (the same instance of the application, actually).
There is no way to see dragged data in OnEnter and OnDragOver methods.
The only solution I found is to store the dragged item in some instance variable that is then readable inside these methods.

Categories