Как упаковать с помощью 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_())

person user3755529    schedule 20.10.2017    source источник
comment
вы можете показать изображение того, что вы хотите получить.   -  person eyllanesc    schedule 20.10.2017
comment
@eyllanesc хорошо, спасибо за совет, я отредактировал вопрос   -  person user3755529    schedule 20.10.2017
comment
Зачем создавать QTextBrowser и встраивать в него другой QTextBrowser?   -  person eyllanesc    schedule 20.10.2017
comment
@eyllanesc извините, я запутался, упрощая свой код, создавая пример кода для этого вопроса. Я исправил код сейчас   -  person user3755529    schedule 20.10.2017
comment
Теперь я не понимаю, зачем использовать макет внутри QtextBrowser.   -  person eyllanesc    schedule 20.10.2017
comment
@eyllanesc, лол, да, совершенно бесполезно ... Полагаю, я добавил его в какой-то момент, исследуя, что может вызвать мою проблему. код исправлен   -  person user3755529    schedule 20.10.2017
comment
Предположим, что содержимое каждого QTextBrowser отличается, поэтому идеальный размер варьируется, в этом случае как вы хотите, чтобы ваш виджет отображался?   -  person eyllanesc    schedule 20.10.2017
comment
@eyllanesc в этом случае я все еще сохраняю gridLayout, который принимает наименьший или самый большой (скорее, самый большой) QTextBrowser в качестве стандарта для каждой ячейки в сетке.   -  person user3755529    schedule 20.10.2017
comment
Я реализовал то, что вы хотите, и получил следующие результаты: imgur.com/a/OdmFv, объяснение что вы дали мне в своем предыдущем комментарии, мне не ясно, основываясь на изображениях, которые вы могли бы объяснить мне, если это то, что вы хотите, или указать мне, как вы хотите.   -  person eyllanesc    schedule 20.10.2017
comment
@eyllanesc идеально подходит в обоих случаях   -  person user3755529    schedule 20.10.2017
comment
Попробуйте мой ответ, и если вы не забыли отметить его как правильный, пожалуйста.   -  person eyllanesc    schedule 20.10.2017


Ответы (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_())

Выход:

введите здесь описание изображения

person eyllanesc    schedule 20.10.2017
comment
Спасибо, проверю позже, но вроде работает. Тем не менее, я не понимаю, почему они просто не делают это таким же простым, как HTML-таблица, где ячейки соответствуют содержимому без суеты, а в строках самая высокая ячейка определяет высоту строки, а в столбцах самая широкая ячейка определяет ширину столбца. . Простой. - person user3755529; 20.10.2017
comment
HTML не соответствует размеру, если вы устанавливаете фиксированные размеры, в вашем случае вы разместили ширину = 100, поэтому виджет не знает правильный размер, то же самое должно происходить на веб-странице. - person eyllanesc; 20.10.2017
comment
Я имею в виду, что в HTML, если у меня есть таблица без измерений, и внутри TD этой таблицы я помещаю таблицу с измерением, НЕразмерная таблица будет идеально соответствовать содержимому. PyQt, как и в моем примере выше, кажется, не делает то же самое, что и NON Dimensions QFrame, он не подходит для моей фиксированной (ширина = 100) таблицы (которая является содержимым) - person user3755529; 20.10.2017
comment
если вам интересно, вот репо: github.com/AskBid /scrap-custom-trading-watchlist/tree/gui-mods (guit.py) - person user3755529; 20.10.2017
comment
когда я обновляю MainFrame() с помощью кнопки, макет становится все испорченным - person user3755529; 21.10.2017