Как упаковать с PyQt - как заставить QFrame/Layout адаптироваться к контенту
Я строю сетку QTextEdit с HTML-подмножеством, чтобы показать некоторые данные в интерфейсе в PyQt.
В настоящий момент я получаю GridLayout и QFrame, который содержит его, который делает все, что они хотят, и я не могу заставить их соответствовать размеру QTextEdit. Я плед с SizePolicy, но не работает. Посмотрите на изображение, как дополнительное пространство появляется на стороне каждого QText и как GridLayout режет QTextEdit по высоте.
Единственный способ заставить его работать, если я установлю правильный размер QFrame, чтобы все подходило, но так как размер QTextEdit настраивается, я бы хотел, чтобы QFrame просто помещал все, что он должен содержать вместо получения свободной воли +_+
Обратите внимание, что GridLayout обычно больше, чем основное окно, поэтому ему не нужно помещаться в окно, поэтому нужно использовать 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_())
1 ответ
Чтобы получить правильный размер, вы должны использовать idealWidth()
метод document()
, но это будет правильно только тогда, когда элемент виден, поэтому вы должны применять его, когда виджет виден, поэтому вы должны вызвать show()
метод, к которому применяется это изменение, помимо вызова его каждый раз, когда изменяется текст.
Чтобы получить правильную высоту, используйте size()
метод QTextDocument()
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_())
Выход: