有没有办法在父小部件上叠加多个项目(PySide/Qt)

有没有办法在父小部件上叠加多个项目(PySide/Qt)

问题描述:

我有一个主要的父级小部件,我想要在父级小部件之上有几个布局.

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.

我使用了具有不同子布局的 QGridLayout,但这会导致布局调整大小并迫使它们变小.最后添加的任何 Overlay 都应位于其他项目之上.

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?

还有

layout = QtGui.QBoxLayout(QtGui.QBoxLayout.TopToBottom, parent_widget)

layout = QtGui.QBoxLayout(QtGui.QBoxLayout.TopToBottom)
layout.setParent(parent_widget)

初始化对不同的父对象有什么作用?

What does the Initialization do with the parent that is different?

我通过创建自己的主自定义布局解决了这个问题.OverlayCenter 具有主小部件,因为它是父小部件,您只需将其他布局添加到此布局中即可.

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())