You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt5中GridLayout布局内QLabel控件显示异常问题

问题描述
  • 预期效果:左右两个QFrame控件共同承载五类QLabel标签,右侧QFrame通过QVBoxLayout放置两个文本标签,显示逻辑符合设计要求。
  • 现存问题:左侧QFrame采用QGridLayout网格布局,需按行放置三类控件:顶部为空或单横线、中部为字符内容、底部为单横线/双横线/三横线,实际运行时控件排布错位,不符合设计。
    问题效果截图
问题原因

代码存在5处逻辑错误:

  • 类型不匹配:配置字典中top_line、bot_line存储的是字符串格式值(如"0"、"1"),代码中直接与整数0/1/2/3做相等判断,条件永远不成立,横线文本赋值逻辑全部失效。
  • 空控件占位:顶部横线配置为0(无需显示)时,仍然将无内容的QLabel添加到网格布局中,占用顶部行空间,挤压中部字符、底部横线的显示区域。
  • 布局配置错误:给整个QGridLayout设置了全局居中对齐,导致网格区域不会撑满整个左侧QFrame;同时未设置网格行拉伸规则,三行高度不会按预期分配。
  • 赋值逻辑错误:底部横线配置为3(三横线)的分支中,设置完三横线文本后又被重新赋值为原始配置字符串,导致三横线无法正常显示。
  • 样式语法错误:QSS样式表末尾多写了一个右大括号,可能导致样式解析异常。
修复后完整代码
import sys
from PyQt5.QtWidgets import QWidget,QFrame,QLabel,QHBoxLayout,QVBoxLayout,QGridLayout,QApplication
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont 

class Left_Right_FrameDesign(QWidget):
    def __init__(self,color_left_lrcd,color_right_lrcd,
                      frame_left_lrcd_width,frame_right_lrcd_width,
                      frame_lrcd_height):
        super().__init__()
        self.color_left_lrcd  = color_left_lrcd
        self.color_right_lrcd = color_right_lrcd
        self.frame_left_lrcd_width = frame_left_lrcd_width
        self.frame_right_lrcd_width = frame_right_lrcd_width
        self.frame_lrcd_height = frame_lrcd_height

        self.frame_left_lrcd = QFrame()
        self.frame_left_lrcd.setProperty("type","1")
        self.frame_left_lrcd.setFixedSize(self.frame_left_lrcd_width,self.frame_lrcd_height)

        self.frame_right_lrcd = QFrame()
        self.frame_right_lrcd.setProperty("type","1")
        self.frame_right_lrcd.setFixedHeight(self.frame_lrcd_height)
        self.frame_right_lrcd.setFixedWidth(self.frame_right_lrcd_width)

        self.principal_lrcd_layout  = QHBoxLayout()
        self.frame_left_lrcd_layout = QGridLayout(self.frame_left_lrcd)
        self.frame_right_lrcd_layout = QVBoxLayout(self.frame_right_lrcd)

        self.frame_left_lrcd_layout.setContentsMargins(0, 0, 0, 0)
        self.frame_right_lrcd_layout.setContentsMargins(0,0,0,0)
        self.frame_right_lrcd_layout.setSpacing(0)
        self.frame_left_lrcd_layout.setSpacing(0)
        # 设置网格行拉伸比例:中部字符行占2份空间,上下横线各占1份
        self.frame_left_lrcd_layout.setRowStretch(0, 1)
        self.frame_left_lrcd_layout.setRowStretch(1, 2)
        self.frame_left_lrcd_layout.setRowStretch(2, 1)

        self.principal_lrcd_layout.setSpacing(0)
        self.principal_lrcd_layout.addWidget(self.frame_left_lrcd)
        self.principal_lrcd_layout.addWidget(self.frame_right_lrcd)
        self.principal_lrcd_layout.setContentsMargins(0, 0, 0, 0)

class example(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("My Widget Example")
        self.setStyleSheet(style_sheet())

        my_font_en = QFont("Arial", 8, QFont.Bold)
        my_font_hi = QFont("Mangal", 11, )
        my_font_ta = QFont("Latha", 8,QFont.Bold)

        lbl_sline = ('\u2015' * 4)  # 单横线,调整长度适配宽度
        lbl_dline = '\u003D' * 4  # 双横线
        lbl_tline = ('\u2261' * 4)  # 三横线

        text = {"lbl01": {"lan_1":"en_Accounts","lan_2":"ta_கணக்கியல்"    ,"char":"ta_ழ்","top_line":"0","bot_line":"1"},
                "lbl02": {"lan_1":"en_Manufacturing","lan_2":"hi_हिसाब किताब","char":"en_F8","top_line":"1","bot_line":"2"},
                "lbl03": {"lan_1":"en_Inventory","lan_2":"ta_சரக்கியல்"     ,"char":"hi_हि","top_line":"1","bot_line":"3"}}

        lst_mainkeys = list(text.keys())
        lst_subkeys  = list(text[lst_mainkeys[0]].keys())

        self.lbl_lan1,self.lbl_lan2 = {},{}
        self.lay = QHBoxLayout()
        self.lay.setSpacing(3)
        self.lay.setContentsMargins(0, 0, 0, 0)

        for i, j in enumerate(lst_mainkeys):
            self.frame_design = Left_Right_FrameDesign(color_left_lrcd="green", color_right_lrcd="blue",
                                                   frame_left_lrcd_width=50, frame_right_lrcd_width=200,
                                                   frame_lrcd_height= 40)
            # 提前创建三个左侧控件
            t_label = QLabel()
            t_label.setAlignment(Qt.AlignCenter)
            c_label = QLabel()
            c_label.setAlignment(Qt.AlignCenter)
            b_label = QLabel()
            b_label.setAlignment(Qt.AlignCenter)
            
            top_line_val = int(text[j]["top_line"])
            bot_line_val = int(text[j]["bot_line"])
            
            # 处理顶部横线
            if top_line_val == 1:
                t_label.setText(lbl_sline)
                self.frame_design.frame_left_lrcd_layout.addWidget(t_label,0,0)
            
            # 处理中部字符
            char_text = text[j]["char"]
            if char_text[:2] == "en":
                c_label.setFont(my_font_en)
            elif char_text[:2] == "ta":
                c_label.setFont(my_font_ta)
            elif char_text[:2] == "hi":
                c_label.setFont(my_font_hi)
            c_label.setText(char_text[3:])
            self.frame_design.frame_left_lrcd_layout.addWidget(c_label,1,0)
            
            # 处理底部横线
            if bot_line_val == 1:
                b_label.setText(lbl_sline)
            elif bot_line_val == 2:
                b_label.setText(lbl_dline)
            elif bot_line_val == 3:
                b_label.setText(lbl_tline)
            self.frame_design.frame_left_lrcd_layout.addWidget(b_label,2,0)
            
            # 处理右侧两个文本标签
            for n in lst_subkeys:
                if n not in ["lan_1", "lan_2"]:
                    continue
                temp_text = text[j][n]
                if temp_text[:2] == "en":
                    cur_font = my_font_en
                elif temp_text[:2] == "ta":
                    cur_font = my_font_ta
                elif temp_text[:2] == "hi":
                    cur_font = my_font_hi
                if n == "lan_1":
                    lbl = QLabel()
                    lbl.setText(temp_text[3:])
                    lbl.setFont(cur_font)
                    lbl.setAlignment(Qt.AlignVCenter|Qt.AlignLeft)
                    self.frame_design.frame_right_lrcd_layout.addWidget(lbl)
                elif  n == "lan_2":
                    lbl = QLabel()
                    lbl.setText(temp_text[3:])
                    lbl.setFont(cur_font)
                    lbl.setAlignment(Qt.AlignVCenter|Qt.AlignLeft)
                    self.frame_design.frame_right_lrcd_layout.addWidget(lbl)

            self.lay.addLayout(self.frame_design.principal_lrcd_layout)
        self.setLayout(self.lay)

def style_sheet():
    return """
    QFrame[type="1"] {background-color : rgb(188,212,114);}
    QFrame[type="1"]::hover{background-color:rgb(255, 223, 0);color: Black;}
    """

if __name__ =="__main__":
    app = QApplication(sys.argv)
    mainwindow = example()
    mainwindow.show()
    sys.exit(app.exec_())
修复说明
  • 统一将配置中的字符串类型的线类型值转为整数再做判断,修复横线文本不生效问题。
  • 顶部横线配置为0时不再添加空标签到布局,避免无效占位。
  • 移除全局布局居中设置,改为给每个标签单独设置对齐规则,同时配置网格行拉伸比例,保证三行高度分配符合预期。
  • 删除三横线分支下的错误重复赋值逻辑,修复三横线显示异常。
  • 修正QSS样式表的语法错误,移除多余的右大括号。
  • 优化控件创建逻辑,避免循环内重复创建无意义的空QLabel,减少资源占用。

内容的提问来源于stack exchange,提问作者tckraomuqnt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 05:42:13