Layout inside QtGui.QTabWidget PySide - python

How can I add a layout but not a widget inside a QtGui.QTabWidget? Something like this:
tabs = QtGui.QTabWidget()
tabs.addTab(QtGui.QVBoxLayout(), "Layout")

You don't add layouts to a tab widget, you add widgets.
The simplest choice here would be a QFrame (or even a plain QWidget), to which you can set whatever layout you want.

Related

pyqt: how to use scroll area that contains an outsized label [duplicate]

I want to overlay two widgets in QtDesigner:
There is the big QTextBrowser, and below in the down right corner should be a non-interactiv label that I am going to use as a drag-grip to resize the window (the main widget is frameless so I need to implement it).
Usually this label will sit below the QTextBrowser, which leaves on the left of the grip-label a lot of unused space. So I want to put the grip-label above the QTextBrowser. I want to achieve this in QtDesigner. But the code would look like:
QHBoxLayout *layout = new QHBoxLayout(videoWidget);
QLabel *overlayWidget = new QLabel();
overlay->setAlignment(Qt::AlignCenter);
overlay->setText("Overlaid Text");
layout->addWidget(overlay);
Or as I already did in python:
self.textedit = QTextBrowser(self);
...
gripImage=QLabel(self.textedit);
There the part between the brackets is the parent widget.
That's how it looks right now, but this is not what I want:
This is usually simplest to achieve by using QGridLayout. It allows widgets to occupy the same grid cells. For this particular problem, a 1x1 grid is enough.
Steps to try it out with designer:
Create new form, plain Widget for simplicity
Add a text edit to it (drag and drop from Widget Box), and from Object Inspector you should see it becomes child of the root widget
Add a label to it (drag and drop from Widget Box), and from Object Inspector you should see it becomes child of the root widget
Right click on the root widget (easiest in the Object Inspector), and from the bottom of context menu, select Lay out > - Lay out in Grid
Right click on the label, and from Layout alignment > set it aligned to the corner you want
Done. Here's what it looks like in my Designer:
Now adapt above to your real form.
Ok, it appears achieving above with Designer is hard, and perhaps a bit a matter of luck of doing things just right... Designer just doesn't support doing what you want, it seems.
For clarity this is a complete source code:
QGridLayout *layout = new QGridLayout(widget);
QTextBrowser *textBrowser = new QTextBrowser();
QLabel *label = new QLabel();
label->setText("Overlaid Text");
//label gets positioned above textBrowser and is an overlay
layout->addWidget(textBrowser, 0, 0, Qt::AlignLeft | Qt::AlignTop);
layout->addWidget(label, 0, 0, Qt::AlignRight | Qt::AlignBottom);
I had the same problem but I did not manage to add Overlapping widgets in QtDesigner. Instead, I had to create the overlapping one dynamically after initializing my MainWindow.
I've got two widgets:
dataset_tableWidget (tableWidget)
spinner_dataset_tableWidget (QtWaitingSpinner)
and I wanted to make spinner_dataset_tableWidget spin over the dataset_tableWidget.
After initializing the MainWindow you can do:
#Crating QtWaitingSpinners dinamically and positioning it over the tableWidgets
dataset_tableWidget = QtWaitingSpinner(dataset_tableWidget)
dataset_tableWidget.setSizePolicy(dataset_tableWidget.sizePolicy())

Looping over widgets inside widgets inside layouts

Similar question to what we have here Loop over widgets in PyQt Layout but a bit more complex...
I have
QVGridLayout
QGroupBox
QGridLayout
QLineEdit
I'd like to access QLineEdit but so far I dont know how to access children of QGroupBox
for i in range(self.GridLayout.count()):
item = self.GridLayout.itemAt(i)
for i in range(item.count()):
lay = item.itemAt(i)
edit = lay.findChildren(QLineEdit)
print edit.text()
Can any1 point me to right dirrection?
When a widget is added to a layout, it automatically becomes a child of the widget the layout it is set on. So the example reduces to a two-liner:
for group in self.GridLayout.parentWidget().findChildren(QGroupBox):
for edit in group.findChildren(QLineEdit):
# do stuff with edit
However, findChildren is recursive, so if all the line-edits are in group-boxes, this can be simplified to a one-liner:
for edit in self.GridLayout.parentWidget().findChildren(QLineEdit):
# do stuff with edit
Sorted :
for i in range(self.GridLayout.count()):
item = self.GridLayout.itemAt(i)
if type(item.widget()) == QGroupBox:
child = item.widget().children()
I had to use item.widget() to get access to GroupBox.
Hope this helps some1.

QDockWidget, place the tabs on top and insert text

Are there any methods to make the tabs be placed on top? I think it's more suitable. And is there an easy way to name the tabs, maybe add a QLabel.
Below is a picture of how it looks now.
Use setTabPosition to put the tabs at the top for the relevant dock-areas:
mainwindow.setTabPosition(QtCore.Qt.AllDockWidgetAreas, QtGui.QTabWidget.North)
The tab text is taken from the window title, so it can be set like this:
dockwidget.setWindowTitle('Name')
or indirectly via the QDockWidget constructor:
dockwidget = QtGui.QDockWidget('Name', parent)

how to put widgets inside a PyQt QMdiSubWindow

Sorry, my question may sound very stupid but Frankly i spend a lot of time on internet trying to figure out how to add a widgets to QMdiSubWindow, I mean a Multiple Widgets not just one Widget(this is very important for me .. I need my Sub window to contain a multiple widget not a single widget).
for example i want to add this widgets and layouts to My Sub Window:
QVbox which contains a QlineEdit and Push Button, And QHbox which contain a a Push Button ...
it doesn't matter if you show me how i could do it using the above example, what really matter is to show me how no matter what example you use
Note : Please Use OOP and Python not c++
The hierarchy of widgets and layouts should always follow
widget -> layout -> widget -> layout -> widget -> ...
where each widget can only have one layout, but each layout can contain multiple widgets (note that for simplicity the above only shows one widget per layout).
So, what you need to do is create a widget which contains a layout, and that layout contains the QPushButton andQLineEdit`. For example:
# construct the top level widget
widget = QWidget()
# construct the top level layout
layout = QVBoxLayout(widget)
# create the widgets to add to the layout
button = QPushButton('My Button')
lineedit = QLineEdit()
# add the widgets to the layout
layout.addWidget(button)
layout.addWidget(lineedit)
# set the layout on the widget
widget.setLayout(layout)
# we now have a single widget that contains a layout and 2 widgets
This allows you to effectively encapsulate multiple widgets inside a single widget (and is how a lot of the more complex Qt widgets are created internally, for instance the QSpinBox). So if you want another complex widget inside the layout above, you could again make another widget2 = QWidget(), create a layout (for instance layout2 = QHBoxLayout(widget2)), and then add multiple widgets to it. Once done, add the widget2 widget to the original layout (layout.addWidget(widget2)).
Hopefully you can now see how to construct a single complex widget from an arbitrary number of child widgets and layouts.
At this point you can now set the single widget to an existing QMdiSubWIndow
# now add this widget to the QMdiSubWindow
mdisubwindow.setWidget(widget)
or alternatively, call the convenience function on the QMdiArea to create a new QMdiSubWindow with the widget:
mdisubwindow = mdiarea.addSubWindow(widget)
Note: For your specific example, you don't actually need to construct widget2 to encapsulate the QHBoxLayout. You can add a QHBoxLayout (layout2 in my rough example above) directly to the original layout by calling layout.addLayout(layout2). However, this is more of a special case, and the general principle of encapsulation above of alternating widgets and layouts is more generalisable once you start making your own widget classes in order to re-use code.

How to hide a layout in PyQt?

My code contains a vertical box layout which is a combination of a vertical box layout in left and one at right. I was wondering if there is a way to hide the left layout with all its widgets when a certain signal is emitted.
You could cheat and use a frame instead of a layout: It works exactly the same way, except for the fact you have to set a layout on the frame for it to work properly. You can then do the following:
from PyQt5 import QtWidgets
# create the frame object.
frame = QtWidgets.QFrame()
# you can do this with any layout - vbox, grid, hbox...
# There will not be more than one item in it anyway.
ly = QtWidgets.QVBoxLayout()
frame.setLayout(ly)
# we're assuming here that parent_layout is some outside layout object.
parent_layout.addWidget(frame)
# hide the frame and its contents
frame.hide()
# show the frame and its contents
frame.show()
I was looking for a solution like this, hope this helps :)
You can't hide a layout, but you can hide a widget.
So first put all the widgets in a container widget. Then connect your signal to the setHidden() slot of the container widget. Your signal should emit True or False, depending on whether you want to hide or show the widgets. Alternatively, you could connect your signal to a simple toggle slot, like this:
def toggleLeftWidget(self):
self.leftWidget.setHidden(not self.leftWidget.isHidden())
In which case, it wouldn't matter what your signal emitted.

Categories

Resources