【问题标题】:How to reduce the space between Two Widgets in PyQt5 QGridLayout?如何减少 PyQt5 QGridLayout 中两个小部件之间的空间?
【发布时间】:2021-08-06 08:35:31
【问题描述】:

如何根据需要在 QGridLayout 中排列 Widget?例如,在我的代码中,

  1. 我需要减少“国家”和“州”按钮之间的空间

  2. 将小部件放在最左上角(国家按钮在最左上角 - 无边距)

  3. 减少“国家”和“地区”按钮之间的间距

  4. 将“银行”按钮放在“城镇”按钮的中心

  5. 需要/根据附加图片安排布局

import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

class GridLayout_Example(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Grid layout Example")
        self.setGeometry(100,100,1600,600)
        self.initUI()
        self.layout()
        self.show()

    def initUI(self):
        self.btn_country_63 = QPushButton()
        self.btn_country_63.setText("Country")
        self.btn_country_63.setObjectName("ob_btn_country_63")
        self.btn_country_63.setProperty('group', "1")
        self.btn_country_63.setFixedSize(100, 25)
        self.btn_country_63.setStyleSheet("background-color:red;color:white")
        self.btn_country_63.installEventFilter(self)
        # self.btn_country_63.clicked.connect(self.btn_country_63_select)

        self.btn_state_63 = QPushButton()
        self.btn_state_63.setText("State")
        self.btn_state_63.setObjectName("ob_btn_state_63")
        self.btn_state_63.setProperty('group', "1")
        self.btn_state_63.setFixedSize(100, 25)
        self.btn_state_63.setStyleSheet("background-color:red;color:white")
        self.btn_state_63.installEventFilter(self)
        # self.btn_state_63.clicked.connect(self.btn_state_63_select)

        self.btn_district_63 = QPushButton()
        self.btn_district_63.setText("District")
        self.btn_district_63.setObjectName("ob_btn_district_63")
        self.btn_district_63.setProperty('group', "1")
        self.btn_district_63.setFixedSize(100, 25)
        self.btn_district_63.setStyleSheet("background-color:red;color:white")
        self.btn_district_63.installEventFilter(self)
        # self.btn_district_63.clicked.connect(self.btn_district_63_select)

        self.btn_town_63 = QPushButton()
        self.btn_town_63.setText("Town")
        self.btn_town_63.setObjectName("ob_btn_town_63")
        self.btn_town_63.setProperty('group', "1")
        self.btn_town_63.installEventFilter(self)
        self.btn_town_63.setFixedSize(60, 80)
        self.btn_town_63.setStyleSheet("background-color:red;color:white")
        # self.btn_town_63.clicked.connect(self.btn_town_63_select)

        self.btn_bank_63 = QPushButton()
        self.btn_bank_63.setText("Bank")
        self.btn_bank_63.setObjectName("ob_btn_bank_63")
        self.btn_bank_63.setProperty('group', "1")
        self.btn_bank_63.installEventFilter(self)
        self.btn_bank_63.setFixedSize(100, 25)
        # self.btn_bank_63.clicked.connect(self.btn_bank_63_select)

    def layout(self):

        self.layout_main_toppannel_2_right = QGridLayout()
        self.frame_main_toppannel_2_right = QFrame()
        self.frame_main_toppannel_2_right.setProperty('color', "2")
        self.frame_main_toppannel_2_right.setFixedHeight(100)
        self.frame_main_toppannel_2_right.setStyleSheet("background-color: lightgreen")
        self.layout_main_toppannel_2_right = QGridLayout(self.frame_main_toppannel_2_right)

        self.container63 = QWidget()
        self.container63_box = QGridLayout(self.container63)
        self.container63_box.addWidget(self.btn_country_63, 0, 0, Qt.AlignTop)
        self.container63_box.addWidget(self.btn_district_63, 0, 1, Qt.AlignTop)
        self.container63_box.addWidget(self.btn_state_63, 1, 0, Qt.AlignTop)
        self.container63_box.addWidget(self.btn_town_63, 0, 3)
        self.container63_box.addWidget(self.btn_bank_63,0,4)
        self.container63_box.setColumnStretch(0,4)
        self.container63_box.setRowStretch(0,2)

      
        self.stackitem = QStackedWidget()
        self.stackitem.addWidget(self.container63)
        self.layout_main_toppannel_2_right.addWidget(self.stackitem)

        self.main_layout = QHBoxLayout()
        self.main_layout.addWidget(self.frame_main_toppannel_2_right)
        self.setLayout(self.main_layout)

def main():
    app = QApplication(sys.argv)
    mainwindow = GridLayout_Example()
    mainwindow.show()
    sys.exit(app.exec_())
if __name__ == "__main__":
    main()

【问题讨论】:

  • 建议:下一篇文章,去掉不干预问题的代码,比如eventfilter、setProperty等,因为它们只是噪音,我们无法理解问题的原因。还要尝试放置有助于理解问题而又不会分散我们注意力的图像,您的初始图像有很多不必要的空白空间。
  • 好的。著名的。 @eyllanesc
  • @Kumar 我还建议您对 Designer 进行更多试验(查看您的代码,您显然一直在使用它),可能使用不同类型的小部件,从基本的“小部件”(这是一个 QWidget,它位于“容器”部分)。尝试不同的组合和布局(包括嵌套布局)及其属性的变化(最小/最大尺寸、尺寸策略等)。测试各种小部件,在调整大小和修改其属性时观察它们的默认行为和变化,以便您更好地学习如何处理所有这些。
  • 谢谢@musicamante。听从你的指引

标签: python pyqt pyqt5 qgridlayout


【解决方案1】:

a previous post我详细解释了QGridLayout的操作,所以在这篇文章中我只详细介绍最优秀的。

  • 要删除项目之间的空间,您必须使用 setSpacing(0)(您也可以使用 setHorizo​​ntalSpacing(0) 和 setVerticalSpacing(0))。

  • 要使元素被推到左边,你可以设置一个延伸到假想的第五列。

  • 我还修改了“Town”的高度,因为它与 3 个元素的总高度不匹配,强制出现空格。

  • 在设置项目以匹配所需空间并且没有空格后,我还计算了绿色容器的高度。

  • 最后请注意,一些边距不能通过代码更改,因为它们是由操作系统的本机 QStyles 实现的,以避免我强加使用样式融合。

import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *


class GridLayout_Example(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.build_widgets()
        self.build_layout()

        self.resize(640, 480)

    def build_widgets(self):
        self.btn_country_63 = QPushButton(
            text="Country", styleSheet="background-color:red;color:white"
        )
        self.btn_country_63.setFixedSize(100, 25)

        self.btn_state_63 = QPushButton(
            text="State", styleSheet="background-color:red;color:white"
        )
        self.btn_state_63.setFixedSize(100, 25)

        self.btn_district_63 = QPushButton(
            text="District", styleSheet="background-color:red;color:white"
        )
        self.btn_district_63.setFixedSize(100, 25)

        self.btn_town_63 = QPushButton(
            text="Town", styleSheet="background-color:red;color:white"
        )
        self.btn_town_63.setFixedSize(60, 75)

        self.btn_bank_63 = QPushButton(
            text="Bank", styleSheet="background-color:red;color:white"
        )
        self.btn_bank_63.setFixedSize(100, 25)

        self.btn_zip_63 = QPushButton(
            text="Zip Code", styleSheet="background-color:red;color:white"
        )
        self.btn_zip_63.setFixedSize(100, 25)

    def build_layout(self):
        self.container = QFrame()
        self.container.setStyleSheet("background-color: lightgreen")

        grid_layout = QGridLayout(self.container)
        grid_layout.addWidget(self.btn_country_63, 0, 0, 1, 1)
        grid_layout.addWidget(self.btn_state_63, 1, 0, 1, 1)
        grid_layout.addWidget(self.btn_district_63, 0, 1, 1, 1)
        grid_layout.addWidget(self.btn_town_63, 0, 2, 3, 1)
        grid_layout.addWidget(self.btn_bank_63, 1, 3, 1, 1)
        grid_layout.addWidget(self.btn_zip_63, 2, 4, 1, 1)
        grid_layout.setColumnStretch(5, 1)
        grid_layout.setSpacing(0)
        grid_layout.setContentsMargins(0, 0, 0, 0)

        lay = QVBoxLayout(self)
        lay.addWidget(self.container)
        self.container.setFixedHeight(self.container.sizeHint().height())


def main():
    app = QApplication(sys.argv)
    print("default-style: ", app.style().metaObject().className())
    app.setStyle("fusion")
    mainwindow = GridLayout_Example()
    mainwindow.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

【讨论】:

  • 您的回答总是详细、透彻,对其他读者也有帮助,谢谢。我在互联网的某个地方读到QGridLayout 通常被避免使用,并且仅用于类似表格的外观,即使在这种情况下,VerticalHorizontal 布局的组合大部分时间都是首选,我也相信如此,您对此有何看法?由于这个问题也是关于QGridLayout,所以我只是想知道您对此的看法。
  • @Don'tAccept 你给我的意见是没有任何根据的意见。在您指出的帖子中,它是否表明效率、设计或干预软件开发的东西?对我来说,在许多情况下,我可以互换使用布局,也就是说,对我来说,通常可以使用不同的布局来满足相同的要求。所以我的意见很实用:如果 QGridLayout 解决了你的问题,那就继续使用它。另一件事是你会和我争论一些实际问题。
  • @eyllanesc 谢谢你的回复,我明白了。