簡體   English   中英

PyQt5:直接在 QMainWindow 中放置按鈕與使用 QGridLayout 的區別

[英]PyQt5: Difference in placing buttons directly in QMainWindow versus using QGridLayout

我正在嘗試使用 PyQt5 構建一個將按鈕放置在精確位置的 UI。 我相信 QGridLayout 是一個很好的方法來做到這一點,而不是直接在 QMainWindow 中繪制它們。 我查看 QGridLayout 的原因是因為我希望將按鈕網格與 UI 的其他部分分開,例如按鈕網格右側的圖像(使用 QHBoxLayout)。

當我直接在 QMainWindow 中繪制按鈕時,按鈕出現在正確的位置。 但是,當我使用具有相同坐標的 QGridLayout 時,按鈕未放置在正確的位置並且似乎被壓扁了。

方法 1:我使用 QPushButton .move() 和 .resize() 方法直接在 QMainWindow 中繪制按鈕。 在這種情況下,按鈕繪制在正確的位置。

# below imports, data variable, and main() are used for both examples
import sys
from PyQt5.QtWidgets import (QApplication, QPushButton, QMainWindow, 
                            QGridLayout, QWidget)

data = [{'xmin': 2, 'ymin': 4,  'width': 205, 'height': 54, 'label': 'Go to Page 1'}, 
{'xmin': 34, 'ymin': 22, 'width': 141, 'height': 17, 'label': 'Go to Page 2'}, 
{'xmin': 2, 'ymin': 90, 'width': 187, 'height': 54, 'label': 'Go to Page 3'}, 
{'xmin': 34, 'ymin': 108, 'width': 122, 'height': 17, 'label': 'Go to Page 4'}, 
{'xmin': 2, 'ymin': 176, 'width': 231, 'height': 54, 'label': 'Go to Page 5'}]

class VisualizerWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        for rect in data:
            button = QPushButton(rect['label'], parent=self)
            button.move(rect['xmin'], rect['ymin'])
            button.resize(rect['width'], rect['height']+10)

def main():
    app = QApplication(sys.argv)
    viz_window = VisualizerWindow()
    viz_window.showMaximized()
    sys.exit(app.exec())

if __name__ == '__main__':
    main()

方法 1 窗口截圖 - 正確位置

方法 2:當我采用使用 QMainWindow、QGridLayout 的方法,然后通過 layout.addWidget() 添加 QPushButtons 時,即使我在 .addWidget 中提供了確切的坐標,按鈕也沒有放置在屏幕上的正確位置() 方法。

class VisualizerWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        layout = QGridLayout()
        
        for rect in data:
            button = QPushButton(rect['label'], parent=self)
            layout.addWidget(button, rect['xmin'], 
                                rect['ymin'], rect['width'], 
                                rect['height']+10)
        widget = QWidget(self)
        widget.setLayout(layout)
        self.setCentralWidget(widget)

方法 2 窗口截圖 - 位置不正確

方法 2 中的網格布局似乎在主窗口中被壓扁了。 為什么我看到這兩種方法之間的繪圖行為不同? 如何正確使用 QGridLayout 在正確的位置繪制按鈕?

前提:使用固定幾何圖形(您稱之為“繪制按鈕”)很少是一個好主意。 布局管理器,如 QGridLayout,通過考慮所有小部件用於計算其大小的字體和樣式,確保您的界面始終針對任何窗口分辨率進行優化,並確保它們始終正確顯示,彼此不重疊,如果窗戶太小,或者如果有更多可用空間,將它們留在一個小區域。

您的網格代碼的問題在於您嘗試使用像素作為引用向網格添加小部件,但addWidget()參數被引用到網格的
使用布局管理器時,手動設置小部件的位置是沒有用的,因為布局管理器負責根據添加小部件的行/列(和行/列跨度)設置它們的位置。

由於布局管理器還負責調整小部件的大小(如果有足夠的空間,則將它們變大,如果沒有,則將它們變小),如果您想設置特定大小,則需要使用小部件setFixedSize()setFixedWidth()setFixedHeight()函數。

布局管理器也總是嘗試使用所有可用空間,因此在設置固定或最大小部件尺寸時,布局管理器會將這些小部件平均放置在可用空間中。 如果您需要在其網格單元的一側放置一個固定大小的小部件,請使用addWidget()alignment參數。
此外,在您的情況下,結果將是按鈕將垂直均勻分布,因此您需要添加一個“間隔”。

最后,要添加邊距(將應用於整個布局或小部件),可以使用QWidget.setContentsMargins()QLayout.setContentsMargins()

這是您的代碼的修訂版本:

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QApplication, QPushButton, QMainWindow, 
                            QGridLayout, QWidget, QSpacerItem, QSizePolicy)

leftMargin = 2
topMargin = 4
data = [
    {'row': 0, 'column': 0, 'width': 205, 'height': 54, 'label': 'Go to Page 1'}, 
    {'row': 1, 'column': 0, 'width': 141, 'height': 54, 'label': 'Go to Page 2'}, 
    {'row': 2, 'column': 0, 'width': 187, 'height': 54, 'label': 'Go to Page 3'}, 
]

class VisualizerWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        layout = QGridLayout()

        layout.setContentsMargins(leftMargin, topMargin, 0, 0)

        for rect in data:
            button = QPushButton(rect['label'], parent=self)
            layout.addWidget(button, rect['row'], rect['column'], alignment=Qt.AlignLeft)
            button.setFixedSize(rect['width'], rect['height'])

        # add a spacer item at the bottom of the layout, so that it will occupy all
        # the remaining available space, and will "put" the buttons on top
        spacer = QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Expanding)
        layout.addItem(spacer, layout.rowCount(), 0)

        widget = QWidget(self)
        widget.setLayout(layout)
        self.setCentralWidget(widget)

請注意,我只使用了從您的示例中提取的三個按鈕,因為我真的不明白您為什么使用重疊按鈕。

我強烈建議您閱讀有關布局管理器的文檔並在 Designer 中使用布局進行一些實驗,這可能會澄清您的大部分疑問。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM