首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >QSplitter嵌套在QSplitter中?

QSplitter嵌套在QSplitter中?
EN

Stack Overflow用户
提问于 2022-08-13 13:30:03
回答 1查看 58关注 0票数 0

更新:

这是一个基于我最初实验的MRE,将一个QSplitter作为另一个QSplitter的直接子部件。我想达到这样的情况:上/下高度比例为66%-33%,上QSplitter的左右宽度比例为66%-33%。

代码语言:javascript
运行
复制
import sys
from PyQt5 import QtWidgets, QtCore, QtGui

MAIN_WINDOW_HEIGHT = 900
TOP_FRAME_PERCENTAGE = 66 # can try with other percentages: 50, 75, 90...

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setMinimumSize(1000, MAIN_WINDOW_HEIGHT)
        self.setStyleSheet('background-color: magenta');
        main_splitter = QtWidgets.QSplitter(self)
        main_splitter.setOrientation(QtCore.Qt.Vertical)
        self.setCentralWidget(main_splitter)

        # try swapping and using a TopSplitter instead of a QFrame        
        # top_frame = QtWidgets.QFrame()
        top_frame = TopSplitter()
        
        self.setStyleSheet('background-color: red');
        main_splitter.addWidget(top_frame)
        
        self.bottom_panel = QtWidgets.QFrame()
        main_splitter.addWidget(self.bottom_panel)
        self.bottom_panel.setStyleSheet("background-color: green");
        print(f'main_splitter.indexOf(self.bottom_panel) {main_splitter.indexOf(self.bottom_panel)}')
        
        def bp_size_hint(*args):
            # NB is never called
            print('YYY') 
            return QtCore.QSize(200, (100 - TOP_FRAME_PERCENTAGE) * int(MAIN_WINDOW_HEIGHT/100))
        self.bottom_panel.sizeHint = bp_size_hint
        
        main_splitter.setStretchFactor(0, TOP_FRAME_PERCENTAGE)
        main_splitter.setStretchFactor(1, 100 - TOP_FRAME_PERCENTAGE)
        print(f'A self.bottom_panel.height() {self.bottom_panel.height()}')
        
    def show(self):
        print(f'B self.bottom_panel.height() {self.bottom_panel.height()}')
        super().show()
        print(f'C self.bottom_panel.height() {self.bottom_panel.height()}')
        # 305 pixels with a QFrame, but 263 pixels with a TopSplitter
        
class TopSplitter(QtWidgets.QSplitter):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setStyleSheet('background-color: cyan');
    
        top_left_panel = QtWidgets.QFrame()
        top_left_panel.setStyleSheet('background-color: yellow');
        self.addWidget(top_left_panel)
        top_right_panel = QtWidgets.QFrame()
        top_right_panel.setStyleSheet('background-color: black');
        self.addWidget(top_right_panel)
        
        # these work exactly as you'd expect, to achieve 66%-33%
        self.setStretchFactor(0, 20)
        self.setStretchFactor(1, 10)
        
    def sizeHint(self):
        # NB called frequently
        print('XXX')
        return QtCore.QSize(200, TOP_FRAME_PERCENTAGE * int(MAIN_WINDOW_HEIGHT/100))

app = QtWidgets.QApplication(sys.argv)

window = MainWindow()
window.show()

app.exec_()

先前对此问题的MRE:

(这是我尝试过的第二件事:让主拆分器QFrame的两个子QFrame,然后将一个左-右QSplitter放在最上面的一个.但同样,它没有得到正确的高度比例.)

这是一个MRE:

代码语言:javascript
运行
复制
import sys
from PyQt5 import QtWidgets, QtCore, QtGui

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setMinimumSize(1000, 800)
        self.main_splitter = QtWidgets.QSplitter(self)
        self.main_splitter.setOrientation(QtCore.Qt.Vertical)
        self.setCentralWidget(self.main_splitter) 
        
        TopFrame(self.main_splitter)
        
        self.bottom_panel = QtWidgets.QFrame(self.main_splitter)
        self.bottom_panel.setStyleSheet("background-color: green");
        print(f'self.main_splitter.indexOf(self.bottom_panel) {self.main_splitter.indexOf(self.bottom_panel)}')
        self.main_splitter.setStretchFactor(0, 20)
        self.main_splitter.setStretchFactor(1, 10)
        
class TopFrame(QtWidgets.QFrame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # A
        self.lr_splitter = QtWidgets.QSplitter(self)
        self.lr_splitter.setOrientation(QtCore.Qt.Horizontal)
        # B
        self.setLayout(QtWidgets.QHBoxLayout())
        self.x_panel = QtWidgets.QFrame(self.lr_splitter)
        self.x_panel.setStyleSheet("background-color: red");
        self.y_panel = QtWidgets.QFrame(self.lr_splitter)
        self.y_panel.setStyleSheet("background-color: cyan");
        
        
        self.lr_splitter.setStretchFactor(0, 20)
        self.lr_splitter.setStretchFactor(1, 10)


app = QtWidgets.QApplication(sys.argv)

window = MainWindow()
window.show()

app.exec_()

我要做的是让左-右分割器的子部分延伸到上帧的全宽和全高度。当窗口变宽或变宽时,拉伸系数应保持两个组件的宽度之比。

可以使QSplitter成为另一个QSplitter的直接子级.但我在这方面的实验似乎表明,setStretchFactor不起作用。由于这个原因,我选择了使主拆分器的上子部分成为QFrame

但是还有另一个问题:如果你注释掉__init__中“A”行下的所有内容,你会发现拉伸系数和预期的一样:顶部的框架是下一帧的两倍高。但是,如果您取消评论并再次显示,您将看到这个比率已经神秘地改变了。实验表明,罪魁祸首线是线下的"# B",setLayout...

因此,我最终要寻找的是一个解决方案,在这两个QSplitter中,顶级的TopFrame孩子占据了TopFrame的全部房地产,而setStretchFactor设定的比率正是人们所期望的。

编辑

根据讨论,我对TopFrame类进行了如下尝试:

代码语言:javascript
运行
复制
class TopFrame(QtWidgets.QSplitter):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setOrientation(QtCore.Qt.Horizontal)
        
        h_layout = QtWidgets.QHBoxLayout()
        self.setLayout(h_layout)
        # this line causes two errors: 1) can't add layout to splitter; 2) can't add parent widget to its child layout
        # h_layout.addWidget(self)
        
        self.x_panel = QtWidgets.QFrame()
        self.addWidget(self.x_panel)
        self.x_panel.setStyleSheet("background-color: red");
        self.y_panel = QtWidgets.QFrame()
        self.addWidget(self.y_panel)
        self.y_panel.setStyleSheet("background-color: cyan");
        self.setStretchFactor(0, 20)
        self.setStretchFactor(1, 10)
EN

回答 1

Stack Overflow用户

发布于 2022-08-15 13:25:40

就像以前一样,音乐人的暗示引领了我们前进的道路:

代码语言:javascript
运行
复制
import sys
from PyQt5 import QtWidgets, QtCore, QtGui

MAIN_WINDOW_HEIGHT = 900
TOP_FRAME_PERCENTAGE = 66 # can try with other percentages: 50, 75, 90...

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setMinimumSize(1000, 300)
        self.resize(1000, MAIN_WINDOW_HEIGHT)
        self.setStyleSheet('background-color: magenta');
        main_splitter = QtWidgets.QSplitter(self)
        main_splitter.setOrientation(QtCore.Qt.Vertical)
        self.setCentralWidget(main_splitter)
        top_frame = TopSplitter()
        self.setStyleSheet('background-color: red');
        main_splitter.addWidget(top_frame)
        self.bottom_panel = QtWidgets.QFrame()
        main_splitter.addWidget(self.bottom_panel)
        self.bottom_panel.setStyleSheet("background-color: green");
        # to achieve 66%-33% heights ratio
        main_splitter.setStretchFactor(0, TOP_FRAME_PERCENTAGE)
        main_splitter.setStretchFactor(1, 100 - TOP_FRAME_PERCENTAGE)
         
    def show(self):
        super().show()
        print(f'C self.bottom_panel.height() {self.bottom_panel.height()}')
         
class TopSplitter(QtWidgets.QSplitter):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setStyleSheet('background-color: cyan');
        self.top_left_panel = QtWidgets.QFrame()
        self.top_left_panel.setStyleSheet('background-color: yellow');
        self.addWidget(self.top_left_panel)
        top_right_panel = QtWidgets.QFrame()
        top_right_panel.setStyleSheet('background-color: black');
        self.addWidget(top_right_panel)
        # to achieve 66%-33% widths ratio
        self.setStretchFactor(0, 20)
        self.setStretchFactor(1, 10)
         
    def sizeHint(self):
        print(f'super().sizeHint().height() {super().sizeHint().height()}')
        return self.top_left_panel.sizeHint()

app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()

..。上面的想法是,在困惑地观察了为什么一个QFrame导致期望的高度比,但是一个QSplitter做了一些意想不到的事情,来“欺骗”QSplitter,以便它的sizeHint()返回任何典型的QFrame所做的事情。

这远非理想,如果你想弄乱TopSplitter's top_left_panel的几何结构,可能会遇到麻烦,但至少它能给出一个可控的结果。

其结果是较低的QFrame的高度为304像素( 900主窗口高度)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73344709

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档