Reputation: 6320
I have a main parent widget, and I want several layouts on top of the parent widget.
Initializing a layout with a parent widget will place the layout on top of the parent widget. I like this and would like to do it multiple times (left, top, bottom, and right sides) for the same parent widget.
I used a QGridLayout with different sub layouts, but this caused the layouts to resize and forced them to be small. Whatever Overlay is added last should be on top of the other items.
Below is a very simple example of what I want.
import sys
from PySide import QtGui, QtCore
class Overlay(QtGui.QBoxLayout):
"""Overlay widgets on a parent widget."""
def __init__(self, parent=None, location="left"):
super().__init__(QtGui.QBoxLayout.TopToBottom, parent)
if location == "left" or location == "right":
self.setDirection(QtGui.QBoxLayout.TopToBottom)
if location == "right":
self.setAlignment(QtCore.Qt.AlignRight)
elif location == "top" or location == "bottom":
self.setDirection(QtGui.QBoxLayout.LeftToRight)
if location == "bottom":
self.setAlignment(QtCore.Qt.AlignBottom)
self.css = "QWidget {background-color: lightskyblue; color: white}"
# end Constructor
def addWidget(self, widget):
super().addWidget(widget)
widget.setStyleSheet(self.css)
# end addWidget
# end class Overlay
def main():
app = QtGui.QApplication(sys.argv)
window = QtGui.QMainWindow()
window.show()
widg = QtGui.QTreeView()
window.setCentralWidget(widg)
left = Overlay(widg, "left")
left.addWidget(QtGui.QLabel("HELLO"))
left.addWidget(QtGui.QLabel("WORLD!"))
top = Overlay(widg, "top")
top.addWidget(QtGui.QLabel("Hello"))
top.addWidget(QtGui.QLabel("World!"))
right = Overlay(location="right")
right.setParent(widg)
right.addWidget(QtGui.QLabel("hello"))
right.addWidget(QtGui.QLabel("world!"))
return app.exec_()
# end main
if __name__ == '__main__':
sys.exit(main())
Is there anyway to have multiple layouts with the same parent? If not is there some way to create a dummy widget that will move with the parent widget and have the Overlays use multiple dummy widgets as their parent?
also
layout = QtGui.QBoxLayout(QtGui.QBoxLayout.TopToBottom, parent_widget)
does not do the same thing as
layout = QtGui.QBoxLayout(QtGui.QBoxLayout.TopToBottom)
layout.setParent(parent_widget)
What does the Initialization do with the parent that is different?
Upvotes: 4
Views: 3747
Reputation: 6320
I solved this by creating my own master custom layout. OverlayCenter has the main widget as it's parent and you just add the other layouts to this layout.
import sys
from PySide import QtGui, QtCore
class OverlayCenter(QtGui.QLayout):
"""Layout for managing overlays."""
def __init__(self, parent):
super().__init__(parent)
# Properties
self.setContentsMargins(0, 0, 0, 0)
self.items = []
# end Constructor
def addLayout(self, layout):
"""Add a new layout to overlay on top of the other layouts and widgets."""
self.addChildLayout(layout)
self.addItem(layout)
# end addLayout
def __del__(self):
"""Destructor for garbage collection."""
item = self.takeAt(0)
while item:
item = self.takeAt(0)
# end Destructor
def addItem(self, item):
"""Add an item (widget/layout) to the list."""
self.items.append(item)
# end addItem
def count(self):
"""Return the number of items."""
return len(self.items)
# end Count
def itemAt(self, index):
"""Return the item at the given index."""
if index >= 0 and index < len(self.items):
return self.items[index]
return None
# end itemAt
def takeAt(self, index):
"""Remove and return the item at the given index."""
if index >= 0 and index < len(self.items):
return self.items.pop(index)
return None
# end takeAt
def setGeometry(self, rect):
"""Set the main geometry and the item geometry."""
super().setGeometry(rect)
for item in self.items:
item.setGeometry(rect)
# end setGeometry
# end class OverlayCenter
class Overlay(QtGui.QBoxLayout):
"""Overlay widgets on a parent widget."""
def __init__(self, location="left", parent=None):
super().__init__(QtGui.QBoxLayout.TopToBottom, parent)
if location == "left":
self.setDirection(QtGui.QBoxLayout.TopToBottom)
self.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
elif location == "right":
self.setDirection(QtGui.QBoxLayout.TopToBottom)
self.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
elif location == "top":
self.setDirection(QtGui.QBoxLayout.LeftToRight)
self.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignHCenter)
elif location == "bottom":
self.setDirection(QtGui.QBoxLayout.LeftToRight)
self.setAlignment(QtCore.Qt.AlignBottom | QtCore.Qt.AlignHCenter)
self.css = "QWidget {background-color: lightskyblue; color: white}"
# end Constructor
def addWidget(self, widget):
super().addWidget(widget)
widget.setStyleSheet(self.css)
# end addWidget
# end class Overlay
def main():
app = QtGui.QApplication(sys.argv)
window = QtGui.QMainWindow()
window.show()
widg = QtGui.QTreeView()
window.setCentralWidget(widg)
left = Overlay("left")
lhlbl = QtGui.QLabel("Hello")
lwlbl = QtGui.QLabel("World!")
lhlbl.setSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Maximum)
lwlbl.setSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Maximum)
left.addWidget(lhlbl)
left.addWidget(lwlbl)
top = Overlay("top")
lhlbl = QtGui.QLabel("HELLO")
lwlbl = QtGui.QLabel("WORLD!")
lhlbl.setSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Maximum)
lwlbl.setSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Maximum)
top.addWidget(lhlbl)
top.addWidget(lwlbl)
right = Overlay("right")
lhlbl = QtGui.QLabel("hellO")
lwlbl = QtGui.QLabel("worlD!")
lhlbl.setSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Maximum)
lwlbl.setSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Maximum)
right.addWidget(lhlbl)
right.addWidget(lwlbl)
bottom = Overlay("bottom")
lhlbl = QtGui.QLabel("hello")
lwlbl = QtGui.QLabel("world!")
lhlbl.setSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Maximum)
lwlbl.setSizePolicy(QtGui.QSizePolicy.Maximum, QtGui.QSizePolicy.Maximum)
bottom.addWidget(lhlbl)
bottom.addWidget(lwlbl)
center = OverlayCenter(widg)
center.addLayout(left)
center.addLayout(top)
center.addLayout(right)
center.addLayout(bottom)
return app.exec_()
# end main
if __name__ == '__main__':
sys.exit(main())
Upvotes: 3