拉伸因子在 Qt 中是如何工作的?
How does stretch factor work in Qt?
我正在使用 pyqt5 开发 GUI 应用程序。在某个对话框中,我需要很多组件,其中一个 QWebEngineView 作为 canvas 用于绘制数据,即使在创建对话框时图表尚未准备好,它也应该占用大部分可用的 space 。
我希望它看起来像这样:
我调查并发现了拉伸因子。我看到 QSizePolicy 只直接适用于小部件而不适用于布局,as shown in this SO answer。但后来我看到 addWidget 和 addLayout 方法允许我在 QBoxLayout 的方向上设置拉伸因子,这似乎很符合我的意图。
所以我尝试了:
from PyQt5.QtWidgets import QWidget, QLabel, QVBoxLayout, QHBoxLayout
from strategy_table import StrategyTable
layout = QVBoxLayout()
layout.addWidget(QLabel("Strategy components"))
# Upper layout for a table. Using a 30% of vertical space
upper_layout = QHBoxLayout() # I'm using a HBox because I also want a small button at the right side of the table
self.table = StrategyTable(self) # Own class derived from QTableWidget
upper_layout.addWidget(self.table)
add_button = QPushButton('Add')
add_button.clicked.connect(self._show_add_dialog)
upper_layout.addWidget(add_button)
layout.addLayout(upper_layout, 3) # Setting 20% of size with the stretch factor
# Then the plot area, using 60% of vertical space
layout.addWidget(QLabel("Plot area"))
canvas = QWebEngineView()
layout.addWidget(self.canvas, 6)
# Finally, a small are of 10% of vertical size to show numerical results
layout.addWidget(QLabel("Results"))
params_layout = self._create_results_labels() # A column with several QLabel-QTextArea pairs, returned as a QHBoxLayout
layout.addLayout(params_layout, 1)
self.setLayout(layout)
但它看起来和以前一模一样:
在底部添加结果布局之前看起来还不错,我猜是因为上面table一开始是空的,所以占用很少space,剩下的留给canvas.
不管怎样,似乎忽略了拉伸因子,所以我不知道我是否在这里遗漏了什么,或者我没有完全理解拉伸因子。
顺便说一句,我知道我会使用 QtEditor 来设计 GUI,但我更喜欢手动完成这些事情。
问题很简单,布局处理小部件的位置和大小,但它有限制,其中包括小部件的最小大小,在您的情况下,最后一个元素的高度高于 10%,所以物理上是不可能的。我们可以通过删除内容或使用 QScrollArea:
来看到
import sys
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets
class StrategyTable(QtWidgets.QTableWidget):
pass
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
table = StrategyTable()
button = QtWidgets.QPushButton("Add")
hlay = QtWidgets.QHBoxLayout()
hlay.addWidget(table)
hlay.addWidget(button)
canvas = QtWebEngineWidgets.QWebEngineView()
canvas.setUrl(QtCore.QUrl("http://www.google.com/"))
scroll = QtWidgets.QScrollArea()
content_widget = QtWidgets.QWidget()
scroll.setWidgetResizable(True)
scroll.setWidget(content_widget)
vlay = QtWidgets.QVBoxLayout()
vlay.addWidget(QtWidgets.QLabel("Results:"))
params_layout = self._create_results_labels()
content_widget.setLayout(params_layout)
vlay.addWidget(scroll)
lay.addLayout(hlay, 3)
lay.addWidget(canvas, 6)
lay.addLayout(vlay, 1)
def _create_results_labels(self):
flay = QtWidgets.QFormLayout()
for text in ("Delta", "Gamma", "Rho", "Theta", "Vega"):
flay.addRow(text, QtWidgets.QTextEdit())
return flay
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
希望这对理解布局和拉伸因子有用
Sample Layout based on percentages (CPP)
QVBoxLayout *topMostVerticalLayout = new QVBoxLayout(this);
QHBoxLayout *upperHorznLayout = new QHBoxLayout();
QHBoxLayout *bottomHorznLayout = new QHBoxLayout();
QVBoxLayout *InnerVerticalLayout1 = new QVBoxLayout(this);
QVBoxLayout *InnerVerticalLayout2 = new QVBoxLayout(this);
QVBoxLayout *InnerVerticalLayout3 = new QVBoxLayout(this);
QVBoxLayout *InnerVerticalLayout4 = new QVBoxLayout(this);
QVBoxLayout *InnerVerticalLayout5 = new QVBoxLayout(this);
bottomHorznLayout->addLayout(InnerVerticalLayout1,15); //(15% stretch)
bottomHorznLayout->addLayout(InnerVerticalLayout2,15); //(15% stretch)
bottomHorznLayout->addLayout(InnerVerticalLayout3,15); //(15% stretch)
bottomHorznLayout->addLayout(InnerVerticalLayout4,15); //(15% stretch)
bottomHorznLayout->addLayout(InnerVerticalLayout5,40); //(40% stretch)
topMostVerticalLayout->addLayout(upperHorznLayout,3); //(30% stretch)
topMostVerticalLayout->addLayout(bottomHorznLayout,7); //(70% stretch)
this->setLayout(topMostVerticalLayout);
我正在使用 pyqt5 开发 GUI 应用程序。在某个对话框中,我需要很多组件,其中一个 QWebEngineView 作为 canvas 用于绘制数据,即使在创建对话框时图表尚未准备好,它也应该占用大部分可用的 space 。
我希望它看起来像这样:
我调查并发现了拉伸因子。我看到 QSizePolicy 只直接适用于小部件而不适用于布局,as shown in this SO answer。但后来我看到 addWidget 和 addLayout 方法允许我在 QBoxLayout 的方向上设置拉伸因子,这似乎很符合我的意图。
所以我尝试了:
from PyQt5.QtWidgets import QWidget, QLabel, QVBoxLayout, QHBoxLayout
from strategy_table import StrategyTable
layout = QVBoxLayout()
layout.addWidget(QLabel("Strategy components"))
# Upper layout for a table. Using a 30% of vertical space
upper_layout = QHBoxLayout() # I'm using a HBox because I also want a small button at the right side of the table
self.table = StrategyTable(self) # Own class derived from QTableWidget
upper_layout.addWidget(self.table)
add_button = QPushButton('Add')
add_button.clicked.connect(self._show_add_dialog)
upper_layout.addWidget(add_button)
layout.addLayout(upper_layout, 3) # Setting 20% of size with the stretch factor
# Then the plot area, using 60% of vertical space
layout.addWidget(QLabel("Plot area"))
canvas = QWebEngineView()
layout.addWidget(self.canvas, 6)
# Finally, a small are of 10% of vertical size to show numerical results
layout.addWidget(QLabel("Results"))
params_layout = self._create_results_labels() # A column with several QLabel-QTextArea pairs, returned as a QHBoxLayout
layout.addLayout(params_layout, 1)
self.setLayout(layout)
但它看起来和以前一模一样:
在底部添加结果布局之前看起来还不错,我猜是因为上面table一开始是空的,所以占用很少space,剩下的留给canvas.
不管怎样,似乎忽略了拉伸因子,所以我不知道我是否在这里遗漏了什么,或者我没有完全理解拉伸因子。
顺便说一句,我知道我会使用 QtEditor 来设计 GUI,但我更喜欢手动完成这些事情。
问题很简单,布局处理小部件的位置和大小,但它有限制,其中包括小部件的最小大小,在您的情况下,最后一个元素的高度高于 10%,所以物理上是不可能的。我们可以通过删除内容或使用 QScrollArea:
来看到import sys
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets
class StrategyTable(QtWidgets.QTableWidget):
pass
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
table = StrategyTable()
button = QtWidgets.QPushButton("Add")
hlay = QtWidgets.QHBoxLayout()
hlay.addWidget(table)
hlay.addWidget(button)
canvas = QtWebEngineWidgets.QWebEngineView()
canvas.setUrl(QtCore.QUrl("http://www.google.com/"))
scroll = QtWidgets.QScrollArea()
content_widget = QtWidgets.QWidget()
scroll.setWidgetResizable(True)
scroll.setWidget(content_widget)
vlay = QtWidgets.QVBoxLayout()
vlay.addWidget(QtWidgets.QLabel("Results:"))
params_layout = self._create_results_labels()
content_widget.setLayout(params_layout)
vlay.addWidget(scroll)
lay.addLayout(hlay, 3)
lay.addWidget(canvas, 6)
lay.addLayout(vlay, 1)
def _create_results_labels(self):
flay = QtWidgets.QFormLayout()
for text in ("Delta", "Gamma", "Rho", "Theta", "Vega"):
flay.addRow(text, QtWidgets.QTextEdit())
return flay
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
希望这对理解布局和拉伸因子有用
Sample Layout based on percentages (CPP)
QVBoxLayout *topMostVerticalLayout = new QVBoxLayout(this);
QHBoxLayout *upperHorznLayout = new QHBoxLayout();
QHBoxLayout *bottomHorznLayout = new QHBoxLayout();
QVBoxLayout *InnerVerticalLayout1 = new QVBoxLayout(this);
QVBoxLayout *InnerVerticalLayout2 = new QVBoxLayout(this);
QVBoxLayout *InnerVerticalLayout3 = new QVBoxLayout(this);
QVBoxLayout *InnerVerticalLayout4 = new QVBoxLayout(this);
QVBoxLayout *InnerVerticalLayout5 = new QVBoxLayout(this);
bottomHorznLayout->addLayout(InnerVerticalLayout1,15); //(15% stretch)
bottomHorznLayout->addLayout(InnerVerticalLayout2,15); //(15% stretch)
bottomHorznLayout->addLayout(InnerVerticalLayout3,15); //(15% stretch)
bottomHorznLayout->addLayout(InnerVerticalLayout4,15); //(15% stretch)
bottomHorznLayout->addLayout(InnerVerticalLayout5,40); //(40% stretch)
topMostVerticalLayout->addLayout(upperHorznLayout,3); //(30% stretch)
topMostVerticalLayout->addLayout(bottomHorznLayout,7); //(70% stretch)
this->setLayout(topMostVerticalLayout);