[PyQt] QTabWidget's tab bar behavior?

Maurizio Berti maurizio.berti at gmail.com
Sun May 26 03:21:16 BST 2019


Il giorno dom 26 mag 2019 alle ore 00:19 Matic Kukovec <
kukovecmatic at hotmail.com> ha scritto:

> Excellent find on the button stylesheets, I did not know you could do that!
>

That's actually cool, I was surprised about that too! Too bad that it's
buggy, but it can come handy sometimes anyway!


You asked why I'm using a groupbox? It's because there needs to be the
> ability to add as many buttons as needed to any tab.
>

You don't need to use a groupbox for that, a simple QWidget is enough, and
it would also avoid possible cross-platform issues, as group boxes can
behave differently on other platforms. You might not be interested in that
if you're not planning to use your program on other OSs, but since you only
need a "container" it's better to keep it as simple as possible. Just be
aware that, according to system and Qt default settings, you might need to
manually force contents margins for both the widget and the layout, unless
you're using a default setting already set for your QApplication/style.



> Why the constant hiding/showing of different buttons when the index
> changes? That is because only the *close-button* is shown on non-active
> tab, while *all-other-buttons + close-button* are shown only on the
> active tab. Plus there has to be an ability to hide any button on a
> particular tab as needed, even if it is the active tab.
>

Then I'd suggest to hide or show buttons alone, without constantly changing
the tabButton's widget: I think that the issue you're facing comes exactly
from the fact that you're removing/adding widgets to the tabBar's bars. I'm
not sure about that, but, from my experience, it might be the case, since
tab moving (which means painting and mouse interaction) is based on the
tabSizeHint, which includes widgets set as tabButton.
As long as the active tab is moving, there's no need to update other tab
buttons (hence, their size hints): the currentChanged signal is emitted
whenever the order is changed, and it doesn't care if the currentWidget is
the same, since the index has changed anyway (if the currentIndex is 0 and
you move the first tab after the second, tue currentIndex becomes 1, so the
signal is emitted and the slot called).
So I really think that what's happening is that the QTabBar is constantly
updating the tabSizeHints due to the refresh_tab_buttons() which hides or
sets the tabButton, resulting in odd behavior of tab movement.



> So in short, I have two groupboxes:
>
>    - one that holds the close-button (in my complete code it can also be
>    none if the tab is not closable)
>    - one that holds all additionally added buttons plus a close button,
>    if the tab is closable
>
> which I use to switch according to the activity of the tab when the
> current index changes. That is why there is so much code
> for updating the tab index, and also for resizing when the whole
> application scale factor changes.
> If you have any suggestions of how to make this simpler, I would be glad
> to hear it.
>

I don't know why or how your tabs get the closable property, but I think
you should find a better way to implement that.
Also, since the tabs have to be removed from code (usually starting from
the tabCloseRequested signal), you can leave each button where they are,
and just show or hide it/them as soon as the current tab contains them or
not: since moving will change the index but not the current tab widget (you
can easily find a way to check it), you don't need to update anything: just
ensure which tab is the current one, if it's the same, leave things as they
were.
Remember that tab moving requires Qt to be aware of the tab contents (their
size hints), so if you are continuously changing their contents, Qt just
tries to do its best - which, in your case, means a really odd behavior.
Think of it as changing the size of a widget within a resizeEvent(): it's
just a total mess. :-)


Thanks for the PEP8/None suggestion. I have been trying to hold to it, but
> sometimes I just forget, sorry.
>

No worries, I actually needed a couple of years to get used to it. But it
was worth it!


As far as the example, I apologize, I forgot to attach the images. I also
> tried to minimize the code without breaking anything,
> that is why there was stuff like *int(20)* in it, as before it was a more
> complex expression.
>

While I appreciate your effort, don't get me wrong: I'm afraid it's not
enough.
I understand that you tried to minimize the code, but you still left lots
of unnecessary code in it. Unnecessary to us, but to you also.
Sometimes (lot of times, actually) you really need to start from scratch,
and *then* just add what you really need.
In your last attachment there's still a lot of code which just makes
unneeded confusion: as a small example, the useless create_pixmap function,
which is not important in this case and just creates distraction as it's
not a python/Qt function, nor it uses Qt's naming practices. Trust me on
this, keeping naming convention consistency, even in small projects, really
helps out: our minds have to be at their most while debugging, continuously
changing naming conventions *is* a great distraction, greater than you
might think; it's like continuously changing from metric to imperial units:
you can easily do it, but you're losing lots of mental energy in the
process, as a stupid mosquito can distract you while you're finalizing your
code: it's a stupid mosquito, it shouldn't be an issue, but somehow,
sometimes, you find yourself telling "what I was thinking about?!?" just
because of it...

I have a really minimal snippet of code I use for testing. It's less than
400 bytes (a basic QWidget with a base layout and no children widgets),
it's sometimes annoying to implement complex things from that, but it's
really helpful, as you really have to make an effort to re-implement things
from the beginning (the rubber duck thing), which usually allows you to
clear your mind from other useless distractions. I copy it to a new file
and start again from that. It's sometimes a boring and long process, but,
if you keep your head clear and avoid "mindless" copying and pasting,
you'll find that's actually much more helpful and useful than you'd think.

Cheers,
Maurizio

-- 
È difficile avere una convinzione precisa quando si parla delle ragioni del
cuore. - "Sostiene Pereira", Antonio Tabucchi
http://www.jidesk.net
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20190526/a963f495/attachment.html>


More information about the PyQt mailing list