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
相关产品推荐
相关产品推荐

