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

时间:2014-05-28 19:01:08

标签: qt pyqt pyside

我有一个主要的父窗口小部件,我想在父窗口小部件的顶部放置几个布局。

使用父窗口小部件初始化布局会将布局放在父窗口小部件的顶部。我喜欢这个,并希望为同一个父窗口小部件多次(左侧,顶部,底部和右侧)。

我使用了具有不同子布局的QGridLayout,但这导致布局调整大小并强制它们变小。无论最后添加什么叠加都应该在其他项目之上。

以下是我想要的一个非常简单的例子。

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

是否有多个布局与同一个父级?如果没有,是否有某种方法可以创建一个虚拟窗口小部件,它将与父窗口小部件一起移动并使叠加层使用多个虚拟窗口小部件作为其父窗口?

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

不做同样的事情
layout = QtGui.QBoxLayout(QtGui.QBoxLayout.TopToBottom)
layout.setParent(parent_widget)

初始化对不同的父级做了什么?

1 个答案:

答案 0 :(得分:2)

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

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