【问题标题】:QSplitter() doesn't treat a QScrollArea() and QFrame() equallyQSplitter() 不会平等对待 QScrollArea() 和 QFrame()
【发布时间】:2019-05-27 10:31:04
【问题描述】:

1。问题解释

我正在试验 Qt 的 QSplitter() 小部件。我在 PyQt5 中构建了一个非常简单的示例项目,在左侧显示了一个 QSplitter(),在左侧封装了一个 QScrollArea(),在右侧封装了一个 QFrame()

我给QScrollArea()QFrame() 赋予了相等的拉伸因子,但QSplitter() 并没有平等对待它们。 QScrollArea() 总是获得最大的空间。我不知道为什么。

 

最小的、可重现的示例

只需将以下代码复制粘贴到 .py 脚本中并运行它。我在 Windows 10 机器上运行了 Python 3.7PyQt5

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys

class Scroller(QScrollArea):
    '''
    The Scroller(), will be first widget in the Splitter().

    '''
    def __init__(self):
        super().__init__()
        self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
        self.setStyleSheet("""
            QScrollArea {
                background-color:#fce94f;
                border-color:#c4a000;
                padding: 0px 0px 0px 0px;
                margin: 0px 0px 0px 0px;
            }
        """)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)

        # 1. FRAME
        self.__frm = QFrame()
        self.__frm.setStyleSheet("QFrame { background: #ff25292d; border: none; }")
        self.__frm.setMinimumHeight(100)

        # 2. LAYOUT
        self.__lyt = QVBoxLayout()
        self.__frm.setLayout(self.__lyt)

        # 3. SELF
        self.setWidget(self.__frm)
        self.setWidgetResizable(True)
        return

class Frame(QFrame):
    '''
    The Frame(), will be second widget in the Splitter()

    '''
    def __init__(self):
        super().__init__()
        self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
        # 1. FRAME
        self.setStyleSheet("""
            QFrame {
                background-color:#fcaf3e;
                border-color:#ce5c00;
                padding: 0px 0px 0px 0px;
                margin: 0px 0px 0px 0px;
            }
        """)
        self.__lyt = QVBoxLayout()
        self.__lyt.setAlignment(Qt.AlignTop)
        self.__lyt.setSpacing(0)
        self.__lyt.setContentsMargins(10, 10, 10, 10)
        self.setLayout(self.__lyt)
        return

class Splitter(QSplitter):
    '''
    The Splitter().

    '''
    def __init__(self, widg1, widg2):
        super().__init__()
        self.setOrientation(Qt.Horizontal)
        self.addWidget(widg1)
        self.addWidget(widg2)
        self.setStretchFactor(0, 5)
        self.setStretchFactor(1, 5)
        return

    def createHandle(self):
        return QSplitterHandle(self.orientation(), self)

class CustomMainWindow(QMainWindow):
    '''
    CustomMainWindow(), a QMainWindow() to start the whole setup.

    '''
    def __init__(self):
        super().__init__()
        self.setGeometry(100, 100, 600, 300)
        self.setWindowTitle("QSPLITTER TEST")

        # 1. OUTER FRAME
        self.__frm = QFrame()
        self.__frm.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.__frm.setStyleSheet("""
            QFrame {
                background-color: #eeeeec;
                border-color: #2e3436;
            }
        """)
        self.__lyt = QVBoxLayout()
        self.__frm.setLayout(self.__lyt)
        self.setCentralWidget(self.__frm)
        self.show()

        # 2. WIDGETS TO BE PUT IN SPLITTER
        self.__widg1 = Scroller()
        self.__widg2 = Frame()

        # 3. SPLITTER
        self.__splitter = Splitter(self.__widg1, self.__widg2)
        self.__lyt.addWidget(self.__splitter)
        return

if __name__== '__main__':
    app = QApplication(sys.argv)
    QApplication.setStyle(QStyleFactory.create('Plastique'))
    myGUI = CustomMainWindow()
    sys.exit(app.exec_())

【问题讨论】:

    标签: python python-3.x pyqt pyqt5 qsplitter


    【解决方案1】:

    QSplitter 不仅将拉伸因子作为参考,还考虑了 sizeHint()。如果添加以下内容:

    # ...
    # 3. SPLITTER
    self.__splitter = Splitter(self.__widg1, self.__widg2)
    self.__lyt.addWidget(self.__splitter)
    print(self.__widg1.sizeHint(), self.__widg2.sizeHint())
    return
    

    你会得到以下结果:

    PyQt5.QtCore.QSize(38, 22) PyQt5.QtCore.QSize(20, 20)
    

    我们看到 QScrollArea 在 sizeHint() 中的宽度比 QFrame 大,这就解释了观察到的行为的原因。

    解决办法是建立sizeHint()的宽度相同,即不依赖于它所包含的内容。

    class Scroller(QScrollArea):
        # ...
    
        def sizeHint(self):
            s = super().sizeHint()
            s.setWidth(20) # same width
            return s
    
    class Frame(QFrame):
        # ...
    
        def sizeHint(self):
            s = super().sizeHint()
            s.setWidth(20) # same width
            return s
    # ...
    

    输出:

    【讨论】:

    • 太棒了,你又做到了!你是我的救星@eyllanesc。我要多捐些咖啡来让你的大脑继续运转:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多