PyQT - Add a boxlayout to a boxlayout - python

I would like to create a Horizontal BoxLayout and put inside a vertical BoxLayout.
I came up with the following code that does not work: my window shows up, but the BoxLayouts are not there (at least not visible):
self.setTabText(0, "Folders")
layout1 = QHBoxLayout()
l = QLabel();
l.setPixmap(QPixmap("pics/file.png"))
text = QTextEdit("Un fichier")
element = QVBoxLayout()
element.addChildWidget(l)
element.addChildWidget(text)
layout1.addChildWidget(element)
self.tab1.setLayout(layout1)
How can I make this work ?

You need to add some widget to the layout, such the widget itself can have another layout.
import sys
from PyQt4 import QtGui , QtCore
class Viewer(QtGui.QMainWindow):
def __init__(self, parent = None):
super(Viewer, self).__init__(parent)
self.centralwidget = QtGui.QWidget(self)
self.setCentralWidget(self.centralwidget)
layout1 = QtGui.QHBoxLayout()
self.centralwidget.setLayout(layout1)
l = QtGui.QLabel()
l.setPixmap(QtGui.QPixmap("folder.png"))
text = QtGui.QTextEdit("Un fichier")
element = QtGui.QWidget(self)
layout2 = QtGui.QVBoxLayout()
element.setLayout(layout2)
layout2.addWidget(l)
layout2.addWidget(text)
layout1.addWidget(element)
app = QtGui.QApplication(sys.argv)
viewer = Viewer()
viewer.show()
sys.exit(app.exec_())

For me, I usually assign another widget for the inner layout and it works.
self.setTabText(0, "Folders")
layout1 = QHBoxLayout()
l = QLabel();
l.setPixmap(QPixmap("pics/file.png"))
text = QTextEdit("Un fichier")
element = QVBoxLayout()
#widget = QWidget()
#widget.setLayout(element)
element.addWidget(l)
element.addWidget(text)
#layout1.addWidget(widget)
self.tab1.setLayout(layout1)
codes beginning with # are modified or added.

Related

Building Qt Gui from few classes together

Below is a short example of my Gui. I am trying to split my Gui in few parts.
The elements of InputAxis should be on the same height (horizontal split) and self.recipient should be below them (vertical split).
In InputAxis I am trying to place a QLineEdit but in my Gui I don't see it.
import sys
from PySide import QtCore
from PySide import QtGui
class InputAxis(object):
def __init__(self):
self.frame = QtGui.QFrame()
self.input_interface = QtGui.QLineEdit()
self.form_layout = QtGui.QFormLayout()
def genAxis(self):
self.frame.setFrameShape(QtGui.QFrame.StyledPanel)
self.form_layout.addRow('&Input:', self.input_interface)
return self.frame
class Window(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self, parent = None)
self.layout = QtGui.QVBoxLayout()
self.form_layout = QtGui.QFormLayout()
self.axes = list()
self.axes.append(InputAxis())
self.axes.append(InputAxis())
self.splitter1 = QtGui.QSplitter(QtCore.Qt.Horizontal)
for axis in self.axes:
self.splitter1.addWidget(axis.genAxis())
self.form_layout.addWidget(self.splitter1)
self.setMinimumWidth(400)
self.recipient = QtGui.QLineEdit(self)
# Add it to the form layout with a label
self.form_layout.addRow('&Recipient:', self.recipient)
# Add the form layout to the main VBox layout
self.layout.addLayout(self.form_layout, 0)
# Set the VBox layout as the window's main layout
self.setLayout(self.layout)
QtGui.QApplication.setStyle( QtGui.QStyleFactory.create('Cleanlooks') )
def run(self):
self.show()
def main():
qt_app = QtGui.QApplication(sys.argv)
window = Window()
window.run()
sys.exit(qt_app.exec_())
if __name__=="__main__":
main()
the reason it did not work was this line:
self.form_layout = QtGui.QFormLayout()
It should be:
self.form_layout = QtGui.QFormLayout(self.frame)

PyQt QScrollArea within QScrollArea

I am trying to use multiple horizontal sub QScrollAreas with text and one vertical container QScrollArea. The idea being that the text area in the horizontal sub QScrollAreas will always have equivalent vertical heights and I would like to have one vertical QScrollArea to control the data within them.
The code below shows that the horizontal sub QScrollAreas work, but the vertical QScrollArea doesn't detect that the line edits within the widget inside it don't fit vertically. If I change
scroll.setWidgetResizable(True)
for the vertical QScrollArea to False, the vertical QScrollArea detects the widget inside doesn't fit but I want to be able to scroll all the lineEdits up and down not the parent widget. Also I would like all scrollbars to be always visible. Is this possible?
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Widget(QWidget):
def __init__(self, parent= None):
super(Widget, self).__init__()
self.setGeometry(100, 100, 400, 400)
baseWidget = QWidget()
hBox = QHBoxLayout()
hBox.addWidget(self.getWidget())
hBox.addWidget(self.getWidget())
baseWidget.setLayout(hBox)
scroll = QScrollArea()
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
#when set to False all scrolls are not visible and can only scroll parent widget not the data areas
scroll.setWidgetResizable(True)
scroll.setWidget(baseWidget)
vBox = QHBoxLayout()
vBox.addWidget(scroll)
self.setLayout(vBox)
def getWidget(self):
widget = QWidget()
layout = QVBoxLayout()
for i in range(20):
lineEdit = QLineEdit("row: "+str(i)+" data: "+str(list(range(10))))
lineEdit.setMinimumWidth(250)
layout.addWidget(lineEdit)
widget.setLayout(layout)
scroll = QScrollArea()
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll.setWidgetResizable(False)
scroll.setWidget(widget)
return scroll
if __name__ == '__main__':
app = QApplication(sys.argv)
dialog = Widget()
dialog.show()
The answer could be found here:
PyQt4 : is there any signal related to scrollbar?
Just needed to sync vertical scrollbars and hide all but one:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Widget(QWidget):
def __init__(self, parent= None):
super(Widget, self).__init__()
self.setGeometry(100, 100, 200, 200)
baseWidget = QWidget()
hBox = QHBoxLayout()
lscrollArea = self.getWidget(False)
rScrollArea = self.getWidget(True)
rScrollArea.verticalScrollBar().valueChanged.connect(
lscrollArea.verticalScrollBar().setValue)
hBox.addWidget(lscrollArea)
hBox.addWidget(rScrollArea)
baseWidget.setLayout(hBox)
vBox = QHBoxLayout()
vBox.addWidget(baseWidget)
self.setLayout(vBox)
def getWidget(self, vScrollOn):
widget = QWidget()
layout = QVBoxLayout()
for i in range(20):
lineEdit = QLineEdit("row: "+str(i)+" data: "+str(list(range(10))))
lineEdit.setMinimumWidth(250)
layout.addWidget(lineEdit)
widget.setLayout(layout)
scroll = QScrollArea()
if vScrollOn:
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
else:
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll.setWidgetResizable(False)
scroll.setWidget(widget)
return scroll
if __name__ == '__main__':
app = QApplication(sys.argv)
dialog = Widget()
dialog.show()
app.exec_()

Delete space between Combobox and label (QGridlayout)

I'm trying to create a Application form by PySide, and i follow some tutorial , but i have a problem that is a space between QLabel and QCombobox.
This is my code
import sys
from PySide import QtCore, QtGui
from PySide.QtGui import *
from PySide.QtCore import *
class Window(QtGui.QWidget):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.setMinimumHeight(660)
self.setMinimumWidth(700)
self.setMaximumHeight(660)
self.setMaximumWidth(900)
grid = QtGui.QGridLayout()
grid.addWidget(self.First(), 0,0,2,0)
self.setLayout(grid)
self.setWindowTitle("Library")
self.resize(700, 660)
def First(self):
groupBox = QtGui.QFrame()
groupBox.setMaximumWidth(230)
groupBox.setMaximumHeight(700)
lbFile = QtGui.QLabel("File :",self)
lbFolders = QtGui.QLabel("Folders :",self)
cbFile = QtGui.QComboBox(self)
cbFile.addItem("File 1")
cbFile.addItem("File 2")
lvFolders = QtGui.QListView(self)
lvFolders.setMaximumWidth(220)
lvFolders.setMaximumHeight(500)
vbox = QtGui.QGridLayout()
vbox.addWidget(lbFile,0,0)
vbox.addWidget(cbFile,0,1)
vbox.addWidget(lbFolders,2,0)
vbox.addWidget(lvFolders,3,0,1,2)
groupBox.setLayout(vbox)
return groupBox
app = QApplication.instance()
if app is None:
app = QApplication(sys.argv)
clock = Window()
clock.show()
app.exec_()
and this is my Form :
I dont know how to delete the space between QLabel "File" and QCombobox "File 1"
Adjust the stretch factor for the second column of the layout, and possibly also make the folders label span both columns:
vbox = QtGui.QGridLayout()
vbox.addWidget(lbFile,0,0)
vbox.addWidget(cbFile,0,1)
vbox.addWidget(lbFolders,2,0,1,2)
vbox.addWidget(lvFolders,3,0,1,2)
vbox.setColumnStretch(1, 1)

PyQt : How to add a grid layout inside a QGroupBox in PyQt4

I am trying to create an application window with PyQt4. I want to create a window with a frame and inside that frame some widgets such as labels and text editors.
I created the frame as a QGroupBox to be able to put a title on it.
I know that HBox and VBox seem to be the prefered layout when you deal with frames, however, I would like to manage the positionning of the widgets inside my frame with a grid Layout, which I find easier to manage.
So I tried this piece of code :
import sys
from PyQt4 import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
hbox = QtGui.QHBoxLayout()
grid = QtGui.QGridLayout()
#Definition des Tracing Parameters widgets
WindowSize = QtGui.QLabel("Window size (m)")
SampPts = QtGui.QLabel("Sampling points")
WindowSizeEdit = QtGui.QLineEdit()
SampPtsEdit = QtGui.QLineEdit()
TracParamFrame = QtGui.QGroupBox(self)
TracParamFrame.setTitle("Tracing Parameters")
hbox.addLayout(grid)
grid.addWidget(WindowSize,0,0)
grid.addWidget(WindowSizeEdit,0,1)
grid.addWidget(SampPts,1,0)
grid.addWidget(SampPtsEdit,1,1)
self.setLayout(hbox)
self.setGeometry(300,300,350,300)
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
The main idea here was to create an hbox where I put the QGroupBox and then place a grid layout inside.
The problem is that in the application generated, the widgets are placed outside the frame, and in addition I get the error :
QLayout: Attempting to add QLayout "" to Example "", which already has a layout
QWidget::setLayout: Attempting to set QLayout "" on Example "", which already has a layout
I modified your code, by adding this statement: TracParamFrame.setLayout(hbox)
The code with this added is as:
import sys
from PyQt4 import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
hbox = QtGui.QHBoxLayout()
grid = QtGui.QGridLayout()
#Definition des Tracing Parameters widgets
WindowSize = QtGui.QLabel("Window size (m)")
SampPts = QtGui.QLabel("Sampling points")
WindowSizeEdit = QtGui.QLineEdit()
SampPtsEdit = QtGui.QLineEdit()
TracParamFrame = QtGui.QGroupBox(self)
TracParamFrame.setTitle("Tracing Parameters")
hbox.addLayout(grid)
grid.addWidget(WindowSize,0,0)
grid.addWidget(WindowSizeEdit,0,1)
grid.addWidget(SampPts,1,0)
grid.addWidget(SampPtsEdit,1,1)
TracParamFrame.setLayout(hbox)
#self.setLayout(hbox)
self.setGeometry(300,300,350,300)
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Ok forget it, I found the solution. I had to use the setLayout method of the GroupBox as follows :
TracParamFrame.setLayout(grid)

Add widgets on the fly in pyside

Very new to pyside so maybe a stupid question. I want to create a pyside UI which has a variable number of items in it and also has the possibility to add items while it is running and to make it even more complex it also needs a scroll bar to fit it all on screen!
This is what I've got right now:
import sys
from PySide import QtGui
from PySide import QtCore
class example(QtGui.QWidget):
def __init__(self, parent= None):
super(example, self).__init__()
grid = QtGui.QGridLayout()
grid.setSpacing(10)
self.widget = QtGui.QWidget()
self.layout = QtGui.QGridLayout(self)
for i in range(5):
btn = QtGui.QPushButton("test"+str(i))
self.layout.addWidget(btn,i,0)
btn.clicked.connect(self.buttonClicked)
self.count = i
self.widget.setLayout(self.layout)
self.scroll = QtGui.QScrollArea()
self.scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.scroll.setWidget(self.widget)
grid.addWidget(self.scroll,3,0)
self.setLayout(grid)
def buttonClicked(self):
title = QtGui.QLabel('Title'+str(self.count))
self.layout.addWidget(title,self.count + 1,0)
self.count += 1
self.widget.addLayout(self.layout,0)
self.scroll.addWidget(self.widget,0)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
dialog = example()
dialog.show()
sys.exit(app.exec_())
But somehow the layout gets messed up when adding items through one of the buttons.
Does anybody have an idea how to fix this?
Thanx!
You're not far off. The key piece you're missing is QScrollArea.setWidgetResizable, which will ensure the scrollarea automatically resizes its viewport to fit the contents.
I've made some other adjustments to your example and added comments where appropriate:
class example(QtGui.QWidget):
def __init__(self, parent= None):
super(example, self).__init__()
grid = QtGui.QGridLayout()
grid.setSpacing(10)
self.widget = QtGui.QWidget()
# set the widget as parent of its own layout
self.layout = QtGui.QGridLayout(self.widget)
for i in range(5):
btn = QtGui.QPushButton("test"+str(i))
self.layout.addWidget(btn,i,0)
btn.clicked.connect(self.buttonClicked)
# following lines are redundant
# self.count = i
# self.widget.setLayout(self.layout)
self.scroll = QtGui.QScrollArea()
# need this so that scrollarea handles resizing
self.scroll.setWidgetResizable(True)
# these two lines may not be needed now
self.scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.scroll.setWidget(self.widget)
grid.addWidget(self.scroll, 3, 0)
self.setLayout(grid)
def buttonClicked(self):
title = QtGui.QLabel('Title' + str(self.layout.count()))
self.layout.addWidget(title)
# following lines are redundant
# self.layout.addWidget(title, self.count + 1, 0)
# self.count += 1
# self.widget.addLayout(self.layout,0)
# self.scroll.addWidget(self.widget,0)

Categories