Как заставить QGridLayout изменять размер ячеек точно такого же размера? - PullRequest
1 голос
/ 21 июня 2020

image representation of code

Whenever I resize the window (a QDialog), Reference Viewer and Selected Viewer (subclasses of QScrollArea) should have the exact same size at all time, even after a resize event. However, once out of twice, I get a size 1 pixel smaller for the Selected Viewer (QScrollArea widget on the right). By once out of twice, I mean every odd pixel count.

It seems that the QGridLayout is forcing the right-most panel to that smaller size, probably due to rounding down the value of the space still available.

I use a QGridLayout because I need the toolbar to stay aligned in the center between the panels and it works well.

Вот скринкаст , демонстрирующий проблему: вы можете видеть, что полоса прокрутки появляется каждый раз, когда размер выбранного средства просмотра (панель справа) изменяется на один пиксель короче по ширине по сравнению с панелью слева.

Вот в основном то, что я делаю:

       verticalLayout = QVBoxLayout(self)
       verticalLayout.setSpacing(0)
       verticalLayout.setContentsMargins(0, 0, 0, 0)
       gridLayout = QGridLayout()
       # Minimum width for the toolbar in the middle:
       gridLayout.setColumnMinimumWidth(1, 30)
       gridLayout.setColumnStretch(0,1)
       gridLayout.setColumnStretch(1,0)
       gridLayout.setColumnStretch(2,1)
       gridLayout.setSpacing(3)
    
       selectedImageViewer = ScrollAreaImageViewer(self)
       gridLayout.addWidget(selectedImageViewer, 0, 0, 3, 1)

       verticalToolBar = QToolBar(self)
       verticalToolBar.setOrientation(Qt.Orientation(Qt.Vertical))

       gridLayout.addWidget(verticalToolBar, 1, 1, 1, 1, Qt.AlignCenter)

       referenceImageViewer = ScrollAreaImageViewer(self)
       gridLayout.addWidget(referenceImageViewer, 0, 2, 3, 1)

       verticalLayout.addLayout(gridLayout)

Я добавляю еще один виджет ниже в QVBoxLayout, но здесь он не имеет значения. Я пробовал добавлять разделители, но это, похоже, ничего не меняет:

gridLayout.addItem(QSpacerItem(5,0, QSizePolicy.Minimum), 1, 3, 1, 1, Qt.Alignment(Qt.AlignCenter))

Есть ли способ гарантировать, что оба Viewer'а будут иметь одинаковый размер, без использования resize () для них при каждом resizeEvent ()? Или это действительно должно считаться ошибкой в ​​Qt? дважды.

Изменить: вот минимальный воспроизводимый пример

from PyQt5.QtCore import QSize, Qt
from PyQt5.QtWidgets import (QDialog, QLayout, QVBoxLayout,
    QLabel, QSizePolicy, QToolBar, QGridLayout,
    QWidget, QApplication )

class MyWidget(QWidget):
    def __init__(self, parent):
        super().__init__(parent)
        self.label = QLabel(self)

    def resizeEvent(self, event):
        self.label.setText(f"{self.size()}")

class MyDialog(QDialog):
    def __init__(self, parent):
        super().__init__(parent)
        self.setMinimumSize(QSize(500, 100))
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setSpacing(0)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout = QGridLayout()
        self.gridLayout.setColumnMinimumWidth(1, 30)
        self.gridLayout.setColumnStretch(0,1)
        self.gridLayout.setColumnStretch(1,0)
        self.gridLayout.setColumnStretch(2,1)
        self.gridLayout.setSpacing(3)

        self.selectedImageViewer = MyWidget(self)
        self.gridLayout.addWidget(self.selectedImageViewer, 0, 0, 3, 1)
        self.verticalToolBar = QToolBar(self)
        self.verticalToolBar.setOrientation(Qt.Orientation(Qt.Vertical))
        self.gridLayout.addWidget(self.verticalToolBar, 1, 1, 1, 1, Qt.AlignCenter)
        self.referenceImageViewer = MyWidget(self)
        self.gridLayout.addWidget(self.referenceImageViewer, 0, 2, 3, 1)
        self.verticalLayout.addLayout(self.gridLayout)

def main():
    app = QApplication([()])
    window = QWidget()
    dialog = MyDialog(window)
    dialog.show()
    return app.exec()

if __name__ == "__main__":
    main()

1 Ответ

2 голосов
/ 21 июня 2020

Я предполагаю, что проблема связана с тем, что ScrollArea используется для referenceImageViewer, поэтому в каждом событии изменения размера фактический referenceImageViewer пытается добавить себе горизонтальную полосу прокрутки.

В качестве решения вы можете

  1. Установите для политики настройки referenceImageViewer значение (QAbstractScrollArea.AdjustIgnored или QAbstractScrollArea.AdjustToContents).
  2. Попробуйте использовать Widgets вместо экземпляров ScrollAreaImageViewer в gridLayout, а затем добавьте ScrollAreaImageViewer * 1009. * 1009 внутри этого widget *. * Отредактировано.

    Должна быть разница между шириной 1-го и 3-го виджетов, пока ширина ToolBar фиксирована. Например, когда ширина окна равна 501, а ширина панели инструментов зафиксирована на 20, автоматическое выравнивание не может равномерно разделить оставшиеся 481 пиксель пополам ..

    В качестве решения размер вашей панели инструментов также должен изменяться. Для уменьшения изменений ширины ToolBar вы можете увеличить растяжение 1-го и 3-го столбца в GridLayout, например, до значения 8 и установить растяжение 2-го столбца на 1, чтобы макет автоматически настраивал ширину каждого столбца.

...