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.
Related
I've only just started learning to code and i'm using Python 3. I'm making a GUI in PySide2 and have been struggling with customising a slider object. I've managed to bodge some code together to change the shape and size of various components of the QSlider object, but could really use a full list of editable parameters for each objects' stylesheet ideally. The doc.qt.io site either lists every object with a small portion of the changeable parameters and some limited examples, or there is a list of every single parameter on stylesheets from every single object, but doesn't specify if certain properties are exclusive to objects (and some definitely are).
Is there documentation anywhere that lists each object in QT and its associated stylesheet options? The main reason for me making this post is that i was looking for a way to edit a QSlider's handle when it is in a pressed state but cannot find what the parameter for that would be. I managed to find that mouseover is done with "hover" but not much else.
When a window-level event (such as a mouse click or a drag-n-drop) occurs in a Kivy application, it gets passed to the entire widget tree. I have multiple widgets of the same class spread across my UI, and need to know which the event occured over. Although I can filter using self.collide(), once I've done that I need to know WHICH widget it is - i.e. is it the top widget in my UI, or the bottom, or what.
I had intended to do this by giving unique names to the "id" value in the kv file for each relevant widget, then run cases in my code based on that. But I was disappointed to find out that "...note that the id will not be available in the widget instance..."
so what's the best practice for giving each widget a unique ID in the kv lang file that can be reference in code? Certainly I could use object properties, but that seems like overkill. Is there some simpler method?
Just give the widgets an identifying attribute or property. If you wanted a string ID, use a StringProperty. It isn't really clear to me that this app structure is the best way to do solve your problem, but it will work fine.
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.
Widget "visit" (tab key) order is determined by the order of widget creation. Is there a simple, pure Python (3.x) way to force the widgets to be visited in a different, user-determined order? If not, is there a simple "Tk" way of doing this? (BTW, This is about about widgets, not notebook tabs).
I couldn't find anything about how to do this while researching the usual tkinter sites, on stackoverflow etc. Have I missed something basic, a widget parameter, universal method, etc.?
Example of why this ability is needed:
The python code (an application/package/class) uses several different widget types and implemented as several files. The definition/creation of all widgets of the same type, e.g. checkboxes, are placed (isolated) inside their own file (e.g. there is a Checkbox file, a Notebook file, a Button File, etc). At initialization this organization causes all occurances of one widget type to be created (and thus tab-ordered) sequentially - and before/after any widgets of any other type.
The resulting widget "visit" order is not (from the users viewpoint) the natural order. How can I force the natural order without resorting to changing the order of widget creation (or doing somethlng as kludgey/artificial as placing every widget in it's own frame and then arranging the frame creation order to match the natural order)?
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