Python qt: layouts: Difference between revisions
No edit summary |
|||
Line 1: | Line 1: | ||
This page contains <code>QLayout</code> subclasses, and container widgets. | This page contains <code>QLayout</code> subclasses, and container widgets. | ||
= General Info = | = General Info = | ||
Line 42: | Line 41: | ||
btn = { 'a':'', 'b':'', 'c':'' } | btn = { 'a':'', 'b':'', 'c':'' } | ||
for ctrl in btn: | for ctrl in btn: | ||
ctrl = QtGui.QPushButton( ctrl ) | |||
ctrl.setSizePolicy( QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Expanding) | |||
vbox.addWidget( ctrl ) | |||
win.setLayout(vbox) | win.setLayout(vbox) | ||
win.show() | win.show() | ||
</syntaxhighlight> | </syntaxhighlight> | ||
</blockquote><!-- Object Stretchiness --> | </blockquote><!-- Object Stretchiness --> | ||
Line 58: | Line 56: | ||
branchVertLayout.setContentsMargins(0,0, 0,0) | branchVertLayout.setContentsMargins(0,0, 0,0) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
</blockquote><!-- Space Between Objects --> | </blockquote><!-- Space Between Objects --> | ||
Line 65: | Line 62: | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
h = QtGui.QHBoxLayout() | h = QtGui.QHBoxLayout() | ||
h.addStretch(1) | h.addStretch(1) # All objects will be pushed all the way to the end of the layout | ||
</syntaxhighlight> | </syntaxhighlight> | ||
</blockquote><!-- Attach to Form Edge --> | </blockquote><!-- Attach to Form Edge --> | ||
</blockquote><!-- General Info --> | </blockquote><!-- General Info --> | ||
= Layouts = | = Layouts = | ||
<blockquote> | <blockquote> | ||
== QHBoxLayout/QVBoxLayout == | == QHBoxLayout/QVBoxLayout == | ||
<blockquote> | <blockquote> | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
# Create Buttons | |||
okButton = QtGui.QPushButton("OK") | okButton = QtGui.QPushButton("OK") | ||
cancelButton = QtGui.QPushButton("Cancel") | cancelButton = QtGui.QPushButton("Cancel") | ||
# Layouts | |||
hbox = QtGui.QHBoxLayout() # Create Horizonal BoxLayout | hbox = QtGui.QHBoxLayout() # Create Horizonal BoxLayout | ||
hbox.addStretch(1) # Push edge of layout all the way to it's maximum (right) | hbox.addStretch(1) # Push edge of layout all the way to it's maximum (right) | ||
Line 95: | Line 82: | ||
hbox.addWidget(cancelButton) | hbox.addWidget(cancelButton) | ||
vbox = QtGui.QVBoxLayout() # Create Vertical BoxLayout | vbox = QtGui.QVBoxLayout() # Create Vertical BoxLayout | ||
vbox.addStretch(1) # Push edge of vertical layout to it's maximum (bottom) | vbox.addStretch(1) # Push edge of vertical layout to it's maximum (bottom) | ||
vbox.addLayout(hbox) # Add horizontal boxLayout | vbox.addLayout(hbox) # Add horizontal boxLayout | ||
# Combination of both means layout hbox items are at bottomRight | # Combination of both means layout hbox items are at bottomRight | ||
self.setLayout(vbox) # Attach 'vbox' layout to the window (so grows/shrinks with it) | self.setLayout(vbox) # Attach 'vbox' layout to the window (so grows/shrinks with it) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
</blockquote><!-- | </blockquote><!-- QHBoxLayout/QVBoxLayout --> | ||
== GridLayout == | == GridLayout == | ||
Line 113: | Line 98: | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
# Simple GridLayout | |||
## Array of ButtonNames | # ================= | ||
# Array of ButtonNames | |||
names = ['Cls' , 'Bck' , '' , 'Close' , | names = ['Cls' , 'Bck' , '' , 'Close' , | ||
'7' , '8' , '9' , '/' , | |||
'4' , '5' , '6' , '*' , | |||
'1' , '2' , '3' , '-' , | |||
'0' , '.' , '=' , '+' ] | |||
# Build GridLayout | |||
grid = QtGui.QGridLayout() | grid = QtGui.QGridLayout() | ||
j = 0 | j = 0 | ||
pos = [ (0, 0), (0, 1), (0, 2), (0, 3), # This Array is unecessary, gridLayouts | pos = [ (0, 0), (0, 1), (0, 2), (0, 3), # This Array is unecessary, gridLayouts | ||
(1, 0), (1, 1), (1, 2), (1, 3), # seem to automatically adjust to the | (1, 0), (1, 1), (1, 2), (1, 3), # seem to automatically adjust to the | ||
(2, 0), (2, 1), (2, 2), (2, 3), # largest index an item is assigned to | (2, 0), (2, 1), (2, 2), (2, 3), # largest index an item is assigned to | ||
(3, 0), (3, 1), (3, 2), (3, 3), | (3, 0), (3, 1), (3, 2), (3, 3), | ||
(4, 0), (4, 1), (4, 2), (4, 3) ] | (4, 0), (4, 1), (4, 2), (4, 3) ] | ||
# Assign a button per-gridLayout-position | |||
for i in names: | for i in names: | ||
button = QtGui.QPushButton(i) | |||
if j == 2: grid.addWidget( QtGui.QLabel(''), 0, 2 ) | |||
else: grid.addWidget( button, pos[j][0], pos[j][1] ) # GridLayouts work a little differently here | |||
j=j + 1 # you seem to attach controls to a position | |||
# rather than their left/right side... | |||
# Attach a (primary) layout to the window | |||
self.setLayout(grid) | self.setLayout(grid) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
# More Complicated Layout | |||
## Create GUI Objects | # ======================= | ||
title = QtGui.QLabel('Title' ) | |||
# Create GUI Objects | |||
title = QtGui.QLabel('Title' ) # Left Column GUI Objects | |||
author = QtGui.QLabel('Author') | author = QtGui.QLabel('Author') | ||
review = QtGui.QLabel('Review') | review = QtGui.QLabel('Review') | ||
titleEdit = QtGui.QLineEdit() | titleEdit = QtGui.QLineEdit() # Right Column GUI Objects | ||
authorEdit = QtGui.QLineEdit() | authorEdit = QtGui.QLineEdit() | ||
reviewEdit = QtGui.QTextEdit() | reviewEdit = QtGui.QTextEdit() | ||
Line 161: | Line 146: | ||
# Create GridLayout | |||
grid = QtGui.QGridLayout() | grid = QtGui.QGridLayout() | ||
grid.setSpacing(90) | grid.setSpacing(90) ## Space between GUI elements in grid. | ||
# Can also adjust vertically/horizontally | |||
# separately ( setHorizontalSpacing ) | |||
# Add Objects to Layout | |||
grid.addWidget( title ,1 ,0 ) | grid.addWidget( title ,1 ,0 ) ## ( object, y,x ) Note that like curses, these are y/x | ||
grid.addWidget( titleEdit ,1 ,1 ) | grid.addWidget( titleEdit ,1 ,1 ) | ||
Line 174: | Line 159: | ||
grid.addWidget( authorEdit ,2 ,1 ) | grid.addWidget( authorEdit ,2 ,1 ) | ||
grid.setRowMinimumHeight( 3, 50 ) | grid.setRowMinimumHeight( 3, 50 ) ## Create an emtpy 'spacer' column in a gridLayout. | ||
# (you can also use this to set a minimum height for a column with items) | |||
grid.addWidget( review ,4 ,0 ) | grid.addWidget( review ,4 ,0 ) | ||
grid.addWidget( reviewEdit ,4 ,1 ,5 ,1 ) | grid.addWidget( reviewEdit ,4 ,1 ,5 ,1 ) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
</blockquote><!-- GridLayout --> | </blockquote><!-- GridLayout --> | ||
Line 200: | Line 183: | ||
{{ WARNING | | {{ WARNING | | ||
A Vanilla QT Application will not draw anything to represen a splitter (no 3 dots, mayastyle). | A Vanilla QT Application will not draw anything to represen a splitter (no 3 dots, mayastyle). | ||
You can create global presets for this using CSS. | You can create global presets for this using CSS. | ||
}} | }} | ||
Create Horizontal QSplitter | |||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
splitH = QtGui.QSplitter( QtCore.Qt.Orientation( QtCore.Qt.Horizontal ) ) | |||
splitH = QtGui.QSplitter( QtCore.Qt.Orientation( QtCore.Qt.Horizontal ) ) | |||
# Add 3 Objects to QSplitter | |||
for i in xrange(0, 3): | |||
splitH.addWidget( QtGui.QPushButton( str(i)) ) | |||
# Make QPushButton at index[1]'s split occupy 50% | |||
# of window's room by default | |||
splitH.setStretchFactor( 1, 50 ) | |||
# Assign Parent Layout | |||
mainV.addWidget(splitH) | |||
</syntaxhighlight> | |||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
# Add Layouts to QSplitter | |||
logVSP = QtGui.QSplitter(QtCore.Qt.Orientation(QtCore.Qt.Vertical)) | |||
logVSP = QtGui.QSplitter( QtCore.Qt.Orientation( QtCore.Qt.Vertical ) ) | |||
log = QtGui.QWidget() # Create a QWidget to contain layouts | log = QtGui.QWidget() # Create a QWidget to contain layouts | ||
Line 234: | Line 216: | ||
logVSP.addWidget( log ) # Add QWidget to QSplitter | logVSP.addWidget( log ) # Add QWidget to QSplitter | ||
</syntaxhighlight> | </syntaxhighlight> | ||
</blockquote><!-- QSplitter --> | </blockquote><!-- QSplitter --> | ||
== QScrollArea == | == QScrollArea == | ||
<blockquote> | <blockquote> | ||
{{ WARNING | | {{ WARNING | | ||
A QScrollArea's widget's layout does not behave the same when setting alignment on it. | A QScrollArea's widget's layout does not behave the same when setting alignment on it. | ||
Line 250: | Line 229: | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
# build widgets | |||
main_layout = QtGui.QVBoxLayout() | main_layout = QtGui.QVBoxLayout() | ||
scroll = QtGui.QScrollArea() | scroll = QtGui.QScrollArea() | ||
Line 256: | Line 235: | ||
layout_widget = QtGui.QWidget() | layout_widget = QtGui.QWidget() | ||
# widget properties | |||
scroll.setWidgetResizable(1) # allows widget to change size (ex: if adding several widgets to a layout inside widget) | scroll.setWidgetResizable(1) # allows widget to change size (ex: if adding several widgets to a layout inside widget) | ||
layout.setAlignment(QtCore.Qt.AlignTop) # align all widgets inside scrollArea to top | layout.setAlignment(QtCore.Qt.AlignTop) # align all widgets inside scrollArea to top | ||
# populate layout | |||
main_layout.addItem(scroll) | main_layout.addItem(scroll) | ||
scroll.setWidget(layout_widget) | scroll.setWidget(layout_widget) | ||
layout_widget.setLayout(layout) | layout_widget.setLayout(layout) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
</blockquote><!-- QScrollArea --> | </blockquote><!-- QScrollArea --> | ||
</blockquote><!-- Container widgets --> |
Latest revision as of 16:00, 2 July 2022
This page contains QLayout
subclasses, and container widgets.
General Info
Useful Methods
layout = QtWidgets.QVBoxLayout() layout.setAlignment( QtCore.Qt.AlignTop ) # pin objects to the top of layout layout.setSpacing(0) # space between all controls in a layout layout.setContentsMargins(0,0, 0,0) # marginSize inside layout before controls drawn ## QLayouts do not have a way to set a maximum size for themselves ## **but** QWidgets do. You can set a maximum layout size by adding ## the layout to a QWidget widget = QtGui.QWidget() widget.setLayout(hbox) widget.setMaximumSize(0, 100) layout.addLayout(layout) # Nest Layout (from parent) layout.addWidget(button) # Add Widget to Layout layout.addItem(spacer) # Add Spacer item to Layout layout.indexOf(spacer) # get the index of an item in a layoutObject Stretchiness
Controls have default size-policies. For instance, buttons stretch horizontally (not vertically) even if their parent layout should make them do otherwise. You can override their sizePolicy with setSizePolicy.
Note
In the documentation, note that setSizePolicy is a member of the QtGui.QWidget class. Remember that this library is object-oriented, and QPusButtons are in the inheritance heirarchy as QtGui.QWidget.QPushButton. This means that they will inherit all the methods/attributes that belong to QtGui.QWidget.
btn = { 'a':'', 'b':'', 'c':'' } for ctrl in btn: ctrl = QtGui.QPushButton( ctrl ) ctrl.setSizePolicy( QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Expanding) vbox.addWidget( ctrl ) win.setLayout(vbox) win.show()Space Between Objects
branchVertLayout.setSpacing(0) branchVertLayout.setContentsMargins(0,0, 0,0)Attach Controls to Form Edge
h = QtGui.QHBoxLayout() h.addStretch(1) # All objects will be pushed all the way to the end of the layout
Layouts
QHBoxLayout/QVBoxLayout
# Create Buttons okButton = QtGui.QPushButton("OK") cancelButton = QtGui.QPushButton("Cancel") # Layouts hbox = QtGui.QHBoxLayout() # Create Horizonal BoxLayout hbox.addStretch(1) # Push edge of layout all the way to it's maximum (right) hbox.addWidget(okButton) # Add items to Layout hbox.addWidget(cancelButton) vbox = QtGui.QVBoxLayout() # Create Vertical BoxLayout vbox.addStretch(1) # Push edge of vertical layout to it's maximum (bottom) vbox.addLayout(hbox) # Add horizontal boxLayout # Combination of both means layout hbox items are at bottomRight self.setLayout(vbox) # Attach 'vbox' layout to the window (so grows/shrinks with it)GridLayout
Gridlayouts are interesting, and different than they are treated in MEL. You attach objects to specific positions in the grid, then adjust the space between the elements.
# Simple GridLayout # ================= # Array of ButtonNames names = ['Cls' , 'Bck' , '' , 'Close' , '7' , '8' , '9' , '/' , '4' , '5' , '6' , '*' , '1' , '2' , '3' , '-' , '0' , '.' , '=' , '+' ] # Build GridLayout grid = QtGui.QGridLayout() j = 0 pos = [ (0, 0), (0, 1), (0, 2), (0, 3), # This Array is unecessary, gridLayouts (1, 0), (1, 1), (1, 2), (1, 3), # seem to automatically adjust to the (2, 0), (2, 1), (2, 2), (2, 3), # largest index an item is assigned to (3, 0), (3, 1), (3, 2), (3, 3), (4, 0), (4, 1), (4, 2), (4, 3) ] # Assign a button per-gridLayout-position for i in names: button = QtGui.QPushButton(i) if j == 2: grid.addWidget( QtGui.QLabel(''), 0, 2 ) else: grid.addWidget( button, pos[j][0], pos[j][1] ) # GridLayouts work a little differently here j=j + 1 # you seem to attach controls to a position # rather than their left/right side... # Attach a (primary) layout to the window self.setLayout(grid)# More Complicated Layout # ======================= # Create GUI Objects title = QtGui.QLabel('Title' ) # Left Column GUI Objects author = QtGui.QLabel('Author') review = QtGui.QLabel('Review') titleEdit = QtGui.QLineEdit() # Right Column GUI Objects authorEdit = QtGui.QLineEdit() reviewEdit = QtGui.QTextEdit() # Create GridLayout grid = QtGui.QGridLayout() grid.setSpacing(90) ## Space between GUI elements in grid. # Can also adjust vertically/horizontally # separately ( setHorizontalSpacing ) # Add Objects to Layout grid.addWidget( title ,1 ,0 ) ## ( object, y,x ) Note that like curses, these are y/x grid.addWidget( titleEdit ,1 ,1 ) grid.addWidget( author ,2 ,0 ) grid.addWidget( authorEdit ,2 ,1 ) grid.setRowMinimumHeight( 3, 50 ) ## Create an emtpy 'spacer' column in a gridLayout. # (you can also use this to set a minimum height for a column with items) grid.addWidget( review ,4 ,0 ) grid.addWidget( reviewEdit ,4 ,1 ,5 ,1 )
Container Widgets
These aren't actually layouts, but their sole purpose is to contain other widgets. The above information about layouts does not apply to these widgets.
QSplitter (drag-resize)
QSplitters let you create a layout that is resizeable by mouse.
NOTE:
The most effective place to use QSplitter()setStretchFactor is immediately after you add widgets to it. It does not seem to take effect if used too early, or too late.
WARNING:
A Vanilla QT Application will not draw anything to represen a splitter (no 3 dots, mayastyle). You can create global presets for this using CSS.
Create Horizontal QSplitter
splitH = QtGui.QSplitter( QtCore.Qt.Orientation( QtCore.Qt.Horizontal ) ) # Add 3 Objects to QSplitter for i in xrange(0, 3): splitH.addWidget( QtGui.QPushButton( str(i)) ) # Make QPushButton at index[1]'s split occupy 50% # of window's room by default splitH.setStretchFactor( 1, 50 ) # Assign Parent Layout mainV.addWidget(splitH)# Add Layouts to QSplitter logVSP = QtGui.QSplitter(QtCore.Qt.Orientation(QtCore.Qt.Vertical)) log = QtGui.QWidget() # Create a QWidget to contain layouts logV = QtGui.QVBoxLayout() # Add Layout logT = Title() # Add Title logT.new( label='test', parent=logV ) logCont = QtGui.QTextEdit() # Add TextEdit logV.addWidget( logCont ) log.setLayout( logV ) # Set QWidget layout logVSP.addWidget( log ) # Add QWidget to QSplitterQScrollArea
WARNING:
A QScrollArea's widget's layout does not behave the same when setting alignment on it. (ex: QVBoxLayout().setAlignment( QtCore.Qt.AlignTop ). You can work around this by nesting another layout/widget/layout combo underneath that layout. The childmost widget will handle alignment as you originally expected.
# build widgets main_layout = QtGui.QVBoxLayout() scroll = QtGui.QScrollArea() layout = QtGui.QVBoxLayout() layout_widget = QtGui.QWidget() # widget properties scroll.setWidgetResizable(1) # allows widget to change size (ex: if adding several widgets to a layout inside widget) layout.setAlignment(QtCore.Qt.AlignTop) # align all widgets inside scrollArea to top # populate layout main_layout.addItem(scroll) scroll.setWidget(layout_widget) layout_widget.setLayout(layout)