如何使QGridLayout调整单元格的大小完全相同?

时间:2020-06-20 22:32:38

标签: python pyqt pyqt5 qgridlayout

image representation of code

每当我调整窗口大小(QDialog)时,即使在发生调整大小事件之后,Reference Viewer和Selected Viewer(QScrollArea的子类)也应始终具有完全相同的大小。 但是,一次两次,我为“选定的查看器”(右侧的QScrollArea小部件)缩小了1个像素。每2次出现一次,我的意思是每个奇数像素计数。

QGridLayout似乎将最右边的面板强制为较小的尺寸,这可能是由于舍入了仍然可用的空间的值。

我使用QGridLayout是因为我需要工具栏在面板之间的中心保持对齐,并且效果很好。

Here is a screencast演示了此问题:每次将“选定查看器”(右侧面板)的尺寸调整为比左侧面板的宽度短一像素时,您会看到滚动条显示。

这主要是我在做什么:

       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))

是否有一种方法可以确保两个查看器都具有相同的大小,而不必在每个resizeEvent()上都使用resize()? 还是应该将其实际上视为Qt中的错误?

我尝试了以下解决滚动条闪烁问题的方法:

def resizeEvent(self, event):
    self.gridLayout.setColumnMinimumWidth(0, self.selectedImageViewer.size().width())
    self.gridLayout.setColumnMinimumWidth(2, self.selectedImageViewer.size().width())

但是大小仍然相差一像素一次。

编辑:这是一个最小的可复制示例

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 个答案:

答案 0 :(得分:1)

我认为问题是ScrollArea用于referenceImageViewer,因此在每个调整大小事件中,实际的referenceImageViewer都会尝试向其自身添加水平滚动条。

作为解决方案,您可以

  1. 将referenceImageViewer的调整策略设置为(QAbstractScrollArea.AdjustIgnored或QAbstractScrollArea.AdjustToContents)。
  2. 尝试在GridLayout中使用Widget而不是ScrollAreaImageViewer实例,然后在该Widget中添加ScrollAreaImageViewer。

已编辑。

第一个和第三个小部件的宽度之间必须有相同的长 因为工具栏的宽度是固定的。例如,当窗口宽度为501和工具栏时 宽度固定为20自动对齐无法将剩余的481均分 一半的像素。

作为解决方案,您的工具栏也必须可调整大小。 为了减少工具栏的宽度变化,您可以增加第一列和第三列 例如在GridLayout中拉伸到值8,并设置第二列 拉伸到1,因此布局会自动调整每个宽度 列。