How to Pack with PyQt - 如何让QFrame/Layout适配内容
How to Pack with PyQt - how to make QFrame/Layout adapt to content
我正在构建一个带有 HTML 子集的 QTextEdit 网格,以在 PyQt 的界面中显示一些数据。
目前,我得到了 GridLayout 和包含它的 QFrame 可以为所欲为,但我无法使它们适合 QTextEdit 大小。我使用 SizePolicy 格子,但不起作用。
从图中可以看出每个 QText 的侧面如何出现额外的 space 以及 GridLayout 如何在高度上削减 QTextEdit。
使它工作的唯一方法是,如果我设置正确的 QFrame 大小以使所有内容都适合,但由于 QTextEdit 的大小是可自定义的,我希望 QFrame 能够简单地适应它必须包含的任何内容获得自由意志 +_+
请注意,GridLayout 通常比 mainwindow 大,因此它不需要适合 window 因此为什么需要 scrollArea。
我不想要的:
应该是:
请注意,我想要的图像已通过添加此行(在 MainFrame() 中)获得:
container.resize(1100,1360)
正如我所说,我想获得相同的行为但没有指定 QFrame 的维度,这应该适合内容(子集 HTML 表)
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from random import *
class Box(QTextBrowser):
def __init__(self):
super().__init__()
self.setText('''
<table border="0" cellspacing="0" cellpadding="5" style="background-color: rgba(119, 212, 212, 0.7);">
<tr>
<td width="100">
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
</td>
<tr>
<tr>
<td>
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
</td>
<tr>
</table>
''')
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setContentsMargins(0,0,0,0)
cstring ="""
QTextBrowser {
border: 0;
background-color: #<---->;
margin: 0px;
padding-left:0;
padding-top:0;
padding-bottom:0;
padding-right:0;
}
"""
ncol = randint(300000, 999999)
cstring = cstring.replace('<---->', str(ncol))
self.setStyleSheet(cstring)
class MainFrame(QScrollArea):
def __init__(self):
super().__init__()
container = QFrame(self)
layout = QGridLayout(container)
for row in range(0, 5):
for col in range(0, 10):
QGridLayout.addWidget(layout, Box(), row, col)
self.setWidget(container)
container.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
layout.setContentsMargins(0,0,0,0)
layout.setSpacing(0)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MainFrame()
sys.exit(app.exec_())
要获得正确的大小,您必须使用 document()
的 idealWidth()
方法,但这只有在项目可见时才是正确的,因此您应该在小部件可见时应用它,所以除了每次文本更改时调用它之外,您还应该调用应用此更改的 show()
方法。
要获得正确的高度,请使用 QTextDocument()
的 size()
方法
class Box(QTextBrowser):
def __init__(self, parent=None):
QTextBrowser.__init__(self, parent)
self.setContentsMargins(0, 0, 0, 0)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
cstring = """
QTextBrowser {
border: 0;
background-color: #<---->;
margin: 0px;
padding-left:0;
padding-top:0;
padding-bottom:0;
padding-right:0;
}
"""
ncol = randint(300000, 999999)
cstring = cstring.replace('<---->', str(ncol))
self.setStyleSheet(cstring)
self.document().contentsChange.connect(lambda: self.customGeometry())
self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
self.setContentsMargins(0, 0, 0, 0)
def customGeometry(self):
if self.isVisible():
self.setFixedWidth(self.document().idealWidth())
self.setFixedHeight(self.document().size().height())
def showEvent(self, event):
self.customGeometry()
QTextBrowser.showEvent(self, event)
class MainFrame(QScrollArea):
def __init__(self, parent=None):
QScrollArea.__init__(self, parent)
container = QFrame(self)
layout = QGridLayout(container)
layout.setSpacing(0)
layout.setContentsMargins(0, 0, 0, 0)
self.show()
text = '''
<table border="0" cellspacing="0" cellpadding="5" style="background-color: rgba(119, 212, 212, 0.7);">
<tr>
<td width="100">
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
</td>
<tr>
<tr>
<td>
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
</td>
<tr>
</table>
'''
for row in range(5):
for col in range(10):
box = Box(container)
box.setText(text)
box.show()
layout.addWidget(box, row, col)
self.setWidget(container)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
ex = MainFrame()
ex.show()
sys.exit(app.exec_())
输出:
我正在构建一个带有 HTML 子集的 QTextEdit 网格,以在 PyQt 的界面中显示一些数据。
目前,我得到了 GridLayout 和包含它的 QFrame 可以为所欲为,但我无法使它们适合 QTextEdit 大小。我使用 SizePolicy 格子,但不起作用。 从图中可以看出每个 QText 的侧面如何出现额外的 space 以及 GridLayout 如何在高度上削减 QTextEdit。
使它工作的唯一方法是,如果我设置正确的 QFrame 大小以使所有内容都适合,但由于 QTextEdit 的大小是可自定义的,我希望 QFrame 能够简单地适应它必须包含的任何内容获得自由意志 +_+
请注意,GridLayout 通常比 mainwindow 大,因此它不需要适合 window 因此为什么需要 scrollArea。
我不想要的:
应该是:
container.resize(1100,1360)
正如我所说,我想获得相同的行为但没有指定 QFrame 的维度,这应该适合内容(子集 HTML 表)
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from random import *
class Box(QTextBrowser):
def __init__(self):
super().__init__()
self.setText('''
<table border="0" cellspacing="0" cellpadding="5" style="background-color: rgba(119, 212, 212, 0.7);">
<tr>
<td width="100">
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
</td>
<tr>
<tr>
<td>
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
</td>
<tr>
</table>
''')
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setContentsMargins(0,0,0,0)
cstring ="""
QTextBrowser {
border: 0;
background-color: #<---->;
margin: 0px;
padding-left:0;
padding-top:0;
padding-bottom:0;
padding-right:0;
}
"""
ncol = randint(300000, 999999)
cstring = cstring.replace('<---->', str(ncol))
self.setStyleSheet(cstring)
class MainFrame(QScrollArea):
def __init__(self):
super().__init__()
container = QFrame(self)
layout = QGridLayout(container)
for row in range(0, 5):
for col in range(0, 10):
QGridLayout.addWidget(layout, Box(), row, col)
self.setWidget(container)
container.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
layout.setContentsMargins(0,0,0,0)
layout.setSpacing(0)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MainFrame()
sys.exit(app.exec_())
要获得正确的大小,您必须使用 document()
的 idealWidth()
方法,但这只有在项目可见时才是正确的,因此您应该在小部件可见时应用它,所以除了每次文本更改时调用它之外,您还应该调用应用此更改的 show()
方法。
要获得正确的高度,请使用 QTextDocument()
size()
方法
class Box(QTextBrowser):
def __init__(self, parent=None):
QTextBrowser.__init__(self, parent)
self.setContentsMargins(0, 0, 0, 0)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
cstring = """
QTextBrowser {
border: 0;
background-color: #<---->;
margin: 0px;
padding-left:0;
padding-top:0;
padding-bottom:0;
padding-right:0;
}
"""
ncol = randint(300000, 999999)
cstring = cstring.replace('<---->', str(ncol))
self.setStyleSheet(cstring)
self.document().contentsChange.connect(lambda: self.customGeometry())
self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
self.setContentsMargins(0, 0, 0, 0)
def customGeometry(self):
if self.isVisible():
self.setFixedWidth(self.document().idealWidth())
self.setFixedHeight(self.document().size().height())
def showEvent(self, event):
self.customGeometry()
QTextBrowser.showEvent(self, event)
class MainFrame(QScrollArea):
def __init__(self, parent=None):
QScrollArea.__init__(self, parent)
container = QFrame(self)
layout = QGridLayout(container)
layout.setSpacing(0)
layout.setContentsMargins(0, 0, 0, 0)
self.show()
text = '''
<table border="0" cellspacing="0" cellpadding="5" style="background-color: rgba(119, 212, 212, 0.7);">
<tr>
<td width="100">
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
</td>
<tr>
<tr>
<td>
bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
</td>
<tr>
</table>
'''
for row in range(5):
for col in range(10):
box = Box(container)
box.setText(text)
box.show()
layout.addWidget(box, row, col)
self.setWidget(container)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
ex = MainFrame()
ex.show()
sys.exit(app.exec_())
输出: