更新:
这是一个基于我最初实验的MRE,将一个QSplitter
作为另一个QSplitter
的直接子部件。我想达到这样的情况:上/下高度比例为66%-33%,上QSplitter
的左右宽度比例为66%-33%。
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:
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
类进行了如下尝试:
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)
发布于 2022-08-15 13:25:40
就像以前一样,音乐人的暗示引领了我们前进的道路:
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主窗口高度)。
https://stackoverflow.com/questions/73344709
复制相似问题