Can't scroll to the end of TreeView PyGTK / GTK - python

When I try to scroll down to the end of my TreeView, which is inside a ScrolledWindow, it doesn't scroll where it should but one or two lines before.
I tried several methods and they all provide the same behavior :
self.wTree.get_widget("tree_last_log").scroll_to_cell((self.number_results-1,))
# or
self.wTree.get_widget("tree_last_log").set_cursor((self.number_results-1,))
# or
adj = self.wTree.get_widget("scrolledwindow1").get_vadjustment()
adj.set_value(adj.get_property('upper'))
self.wTree.get_widget("scrolledwindow1").set_vadjustment(adj)
# or
self.wTree.get_widget("scrolledwindow1").emit('scroll-child', gtk.SCROLL_END, False)
Where is the problem ?

The C API docs may be helpful:
http://library.gnome.org/devel/gtk/stable/GtkTreeView.html#gtk-tree-view-scroll-to-cell
You can see there are arguments there that would mess things up, depending on how pygtk defaults them. You might try specifying explicitly all the args.
One trick to TreeView and TextView is that they do asynchronous layout so the "upper" on the adjustment may well just be zero if row heights haven't been computed yet.
if messing with the adjustment, there's no need to set it back, though it should be harmless.
'scroll-child' signal is not what you want, that's a keybinding signal used to bind keys to.

Related

Can we delete the label and repack it during second time code runs PYTHON

if bool(suggestion_label.winfo_ismapped()):
suggestion_label.destroy()
else:
suggestion_label.pack()
I wanted to ask that anything i do the label packs on the screen and its not deleted second time PART of the code runs.
If you call destroy on a widget, it's gone and can't be used again.
If you want to hide and reveal it, use pack_forget instead of destroy. Be aware that pack is dependent on the order it's called. Re-packing the widget may not put it back in the same place unless you explicitly use the before or after options.
If you use grid, it has a grid_remove function where it will remember where it was replaced. Calling grid with no arguments will restore it with the same grid settings.

PyGObject: Gtk.Fixed Z-order

I'm using Gtk.Fixed and a viewport putting images that, sometimes, overlaps. How can I set the z-index like in html?
Gtk.Fixed doesn't support setting the z-order. It's not meant for overlapping widgets, so the z-order is arbitrary and probably depends on what order the widgets were added in.
It's not clear from your question what your intention is; if you are purposely overlapping widgets, use Gtk.Overlay instead. If you are not intending to overlap them, then you should use a more versatile container such as Gtk.Grid which will take the widgets' sizes into account.
Like ptomato said, I had to use the Gtk.Overlay. I used an overlay with 3 Gtk.Layout, like layers and it works fine.
I only used the C bindings, but I'll try my best to hopefully answer it correctly for the Python bindings as well.
Generally, since GTK4 you can move around your widget using
widget.insert_before (sibling, parent)
Where you might want to obtain the sibling (which will be in front of your widget) and it's parent first.
The function expects the parent to be the parent of the sibling.
So it can be assumed that:
parent = sibling.get_parent ()
At least within a GtkFixed (but possibly other containers as well), siblings are sorted bottom to top, so the first child is the one that's the furthest to the back. "Inserting before" thereby moves your widget behind.
Be aware though, that according to a maintainer, this should only be used within a custom widget and not on an application scale. This is also mentioned in the API of the functions.
From the documentation however, it's not clear to me if this is considered legal. I doubt that this way is supported. However I also doubt, that GtkFixed keeps any track regarding the children order and therefore, I assume that moving children around within a GtkFixed is fine, although illegal.
Moving the widgets around like this also made my application crash, as long as the inspector is open, just as a heads up.
To iterate through the widgets, bottom to top, you can use sibling = parent.get_first_child() as well as sibling = parent.get_next_sibling()
or alternatively use the iterator defined on Widget.

PyQt toolbar in 2nd row by default

I'm adding a simple toolbar to my PyQt application and trying to get the toolbar to start by default in the top position, but in the 2nd row beneath another toolbar.
I have called:
self.addToolBar(Qt.TopToolBarArea, navBar)
This combines the toolbar with my first toolbar which is much shorter into the same row. Is there a way to force these toolbars to be in separate rows?
Finally found the solution after scouring the documentation and trying different options. I think I was looking for something along the lines of "toolBarRow" so I missed it.
The solution is to insert a toolBarBreak. The same way a separator can be added to a toolbar itself, a "break" simply breaks up one of the four areas provided for tool bars: either top, bottom, left, or right. It is added with similar functions to the way separators are added to toolbars, with:
QMainWindow.addToolBarBreak() which adds to the "end" of the toolbar area, which really means the most inward position.
or
QMainWindow.insertToolBarBreak(toolBarBefore) which adds right before the passed in toolbar reference.

How can a wxpython frame "steal" and "return" focus similar to the Dash app?

I want to make a heads-up display that pops up it's frame, taking focus from the previous application and then gives focus back to that application when it's done.
wxPython frames have Hide and Show methods that work but don't focus the application. Also, there's SetFocus which you'd think would do it but doesn't.
Update
I found a nasty hack that works. Rather than hide and show the frame, you save the app state and close the app instead of hiding. Then when you want to show again you spark a new one in a new multiprocessing.Process. Hardly ideal though. I hope someone has something better.
Clarification
To clarify, I'm trying to get the keyboard focus, not just to get the frame on top of the stack.
This issue might be specific to OS X.
You might be able to steal focus by calling Raise on the frame. There is the wx.STAY_ON_TOP style flag that could also be applied. Then you might be able to just use the frame's Show and Hide methods to make it work.
Depending on what exactly you want to do, you might take a look at the ToasterBox widget. I can't recall if it actually steals focus, but it just pop up and go away on its own, which is handy in some cases.

Select text over multiple TextCtrls in wxpython

So I currently have a ScrolledPanel that contains a number of TextCtrls that are placed in a vertical BoxSizer programmatically. The reason I'm doing this instead of just appending lines to one big scrolled TextCtrl is so that I can also add other controls in between the TextCtrl, such as images or stylized expand/contract folding stuff.
However, this particular implementation is causing a problem - namely that it is impossible for the user to select text across multiple TextCtrls. Is there a way to do this that will be fast, clean, idiomatic, and not especially kludgy? Is my best bet to write a pointer-location text selection algorithm that essentially reinvents the wheel for the text selection stuff of the underlying native libraries, or is there an easier way to embed other controls inside a multiline scrollable TextCtrl, or even select text across multiple TextCtrls natively?
I would stay away from trying to reimplement text selection controls if at all possible, since that is bound to turn very messy very fast. Another way you could tackle this issue would be to use a single multi-line textctrl widget with the other widgets tacked on over it. This is also messy, but less so.
You can place the other widgets over the textctrl simply by placing them directly over the same position as the textctrl, so long as the other widgets have the same parent as the textctrl. This should work, so long as you don't overlap with the vscrollbar (or, better yet, remove it entirely with style=wx.TE_NO_VSCROLLBAR).
The next thing you'll need to do is pre-fill and space your textctrl so that the user has control of text only right after the position of each widget. You should have each line of text with a different spacing setting, set with the spacing options of wx.TextAttr (the more generic versions of double-spacing, etc), which you calculate based on the particular widget spacing you've given your app. This is necessary to force the user to type only exactly where you want them to.
Next, you'll need to set up a binding to the textctrl newline character that recalculates the spacing needed for each line. Once you've figured out how to handle spacing, this shouldn't be too difficult.
Finally, after you select the text, just reset everything to the same spacing, or whatever else suits your fancy, so that you don't get awkward linebreaks when you paste it back in elsewhere.
I know this is a complicated answer, but it's a complicated issue you raised. This is, I believe, the most efficient way to solve it, and avoids all the bugs that would arise from completely overhauling the textctrl, but it does involve messing around with auto-correcting linebreaks and spacings, which can be a little tricky at first.

Categories

Resources