PyQt toolbar in 2nd row by default - python

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.

Related

Add side panel without resizing parent

I'm using PySide2 to write a gui (witout QtDesigner).
The mainwindow contains plots and some other widgets. Through a menu option I want to open a side panel widget. The way I want it to work is that the whole window simply grows to contain that new widget without changing the size of anything else in the main window. How can this be done?
Currently the widget is just added to the central layout with addWidget, I've also tried making it a QDockWidget but it is still resized (and anyway I would like to avoid the extra fluff that comes with having a DockWidget).
So I have
---------
|content|
---------
which should turn into
-------------
|new|content|
-------------
but currently I get
---------
|new|cnt|
---------
It's hard to do well on the "client" side of Qt; this would really belong within Qt itself. I have implemented a slightly more general variant of this a couple of years ago, and just to make it work well across Windows, Mac and KDE, the code ballooned to over a thousand lines to cover all the icky corner cases, with another thousand for the test harness. It was surprisingly hard to implement the tests - especially on X11, where there was no way around using native X APIs to verify intended behavior. I got rid of that monstrosity soon later - the effort was unnecessary.
You can have the side panel as a separate top-level frameless widget that moves itself so that its top-right corner is aligned with the top-left corner of the content window, and resizes itself vertically to match the vertical size of the content window. You can of course make it slightly shorter (vertically) while still center-aligning it vertically with the content window.
You'd want to capture the resize events of the content window to do this: the side panel should install itself as an event filter for the content window.
You'll want the side panel to be a Qt child of the content window, but you also need to make it a top-level window, i.e. set the Qt::Window flag on it, so that it becomes top-level and not a sub-widget of the content window.

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.

Arranging pyqt combobox in toolbar

I have made a toolbar in qt designer with a few buttons. I have found some answers on stack that say you can not add a combobox in qt designer. With this I found an example of adding it manually. The method was:
self.combo=QtGui.QComboBox(self.toolBar)
self.combo=insertItems(1,["One","Two","Three"])
However, this puts the combobox all the way on the left ontop of my other buttons. How do I add this to the end? I read the doc that says the QComboBox is QStandardItemModel, which either takes self or a parent. I have tried giving extra arguments like some sort of index but the error says it only takes one argument. How can I specify which location the combobox will go?
Thanks
You added QComboBox as a child of QToolbar. It doesn't belong to any layout, so it doesn't take space in toolbar's layout. You need to use QToolbar::addWidget or QToolbar::insertWidget instead.
self.combo=QtGui.QComboBox()
toolBar.addWidget(self.combo)
self.combo.insertItems(1,["One","Two","Three"])
Note that I've replaced = to . in the last line. It should have been typing error.

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.

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

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.

Categories

Resources