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

PyQt6中QTableWidget与QLabel横向并排布局异常问题排查

PyQt6布局问题:QTableWidget与QLabel横向并排显示异常

我用PyQt6开发Python GUI,需要在标签页内将QTableWidget和带Pixmap的QLabel(目前用文本占位)横向并排,要求表格占水平2/3、图片占1/3。但实际运行时表格占满整个屏幕,QLabel完全显示不出来,相关代码和当前效果如下:

def set_tab_info(self, num_rows): # Sets the structure for each tab
    self.num_rows = num_rows
    tab_info = [
        {"name": "Junction", "columns": 11, "header_labels": ["Type", "X", "Shear Plane Location", "Fastener Position", "Bolt/Screw", "Under head", "Thread",
                                                              "Minimum friction coefficient under bolt head", "Maximum friction coefficient under bolt head",
                                                              "Minimum friction coefficient on thread", "Maximum friction coefficient on thread"],
        "editor_types": ["combo_box", "combo_box", "combo_box", "combo_box", "combo_box", "combo_box", "combo_box", "line_edit", "line_edit", "lined_edit", "line_edit"]},
        {"name": "Screw", "columns": 7, "header_labels": ["Type of Screw", "Nominal Diameter", "Material of Screw", "g",
                                                           "Is there a change in diameter (shank)?", "Shank Length", "Shank Diameter"],
        "editor_types": ["combo_box", "line_edit", "combo_box", "line_edit", "combo_box", "line_edit", "line_edit"]},
        {"name": "Plate", "columns": 9, "header_labels": ["Material Plate 1 (Fastener Head)", "Material Plate 2", "muc", "Type of Hole", "Diameter of Hole",
                                                          "Plate 1 Thickness", "Plate 2 Thickness", "Plate 1 Minimum Shear-out Length", "Plate 2 Minimum Shear-out Length"],
        "editor_types": ["combo_box", "combo_box", "line_edit", "combo_box", "line_edit", "line_edit", "line_edit", "line_edit", "line_edit"]},
        {"name": "Nut/Insert", "columns": 8, "header_labels": ["Nut/Insert", "Type of Nut", "Type of Insert", "Diameter", "Height",
                                                                "Material of Nut/Insert", "Maximum Prevailing Torque", "Minimum Prevailing Torque"],
        "editor_types": ["combo_box", "combo_box", "combo_box", "line_edit", "line_edit", "combo_box", "line_edit", "line_edit"]},
        {"name": "Washer", "columns": 11, "header_labels": ["Type of Washer", "Washer present under bolt head?", "Washer present under nut?", "External Diameter (under head)",
                                                            "internal diameter (under head)", "External diameter (under nut)", "internal diameter (under nut)", "Height (under head)",
                                                            "Height (under nut)", "Maximum Prevailing Torque", "Minimum Prevailing Torque"],
        "editor_types": ["combo_box", "combo_box", "combo_box", "line_edit", "line_edit", "line_edit", "line_edit", "line_edit", "line_edit", "line_edit", "line_edit"]},
        {"name": "Loads", "columns": 9, "header_labels": ["Fkreq", "Kkreq", "DT+", "DT-", "CTEc", "CTEb", "Mnom", "External Shear Load", "External Tension Load"],
        "editor_types": ["line_edit", "line_edit", "line_edit", "line_edit", "line_edit", "line_edit", "line_edit", "line_edit", "line_edit"]},
        {"name": "Safety Factors", "columns": 12, "header_labels": ["Bearing Factor", "Kq", "Km", "Kp", "KLD", "Yield", "Ultimate", "Gapping", "Slippage", "Embedding", "omega", "epsilon"],
        "editor_types": ["line_edit", "line_edit", "line_edit", "line_edit", "line_edit", "line_edit", "line_edit", "line_edit", "line_edit", "line_edit", "line_edit", "line_edit"]}
    ]
    self.create_tabs(tab_info)
    
def create_tabs(self, tab_info): # Creates each tab by receiving the structure from the set_tab_info method
    self.column_inputs = {}
    
    for info in tab_info:
        tab_widget = QWidget()
        tab_layout = QGridLayout(tab_widget)
        
        horizontal_layout = QGridLayout()
        
        table = QTableWidget(self.num_rows, info["columns"])
        table.setHorizontalHeaderLabels(info["header_labels"])
        
        for row in range(self.num_rows):
            for col in range(info["columns"]):
                if info["editor_types"][col] == "line_edit":
                    item = QLineEdit()
                    table.setCellWidget(row, col, item)
                    self.column_inputs[(info["name"], info["header_labels"][col])] = item
                elif info["editor_types"][col] == "combo_box":
                    item = QComboBox()
                    item.addItems(self.get_combo_box_items(info["header_labels"][col]))
                    table.setCellWidget(row, col, item)
                    self.column_inputs[(info["name"], info["header_labels"][col])] = item
                else:
                    item = QTableWidgetItem()
                    
                table.setItem(row, col, QTableWidgetItem())
                
        table.resizeColumnsToContents()
            
        image_label = QLabel("Placeholder")
        horizontal_layout.addWidget(table, 0, 0, 1, 2)
        horizontal_layout.addWidget(image_label, 0, 1, 1, 1)
        
        tab_layout.addLayout(horizontal_layout, 1, 0, 1, 3)
        self.tabs.addTab(table, info["name"])

当前界面效果:
当前界面效果


问题原因及解决办法

  1. 核心错误:添加标签页时直接传入了table,而非包含布局的tab_widget,导致之前设置的横向布局完全失效,表格直接占满整个标签页。
  2. 布局优化:改用QHBoxLayout实现横向比例分配,通过setStretchFactor设置表格与标签的宽度比例为2:1,更贴合需求。

修改后的create_tabs函数代码:

def create_tabs(self, tab_info): # Creates each tab by receiving the structure from the set_tab_info method
    self.column_inputs = {}
    
    for info in tab_info:
        tab_widget = QWidget()
        tab_layout = QVBoxLayout(tab_widget)  # 用垂直布局包裹,方便后续扩展
        
        # 改用QHBoxLayout实现横向比例分配
        horizontal_layout = QHBoxLayout()
        
        table = QTableWidget(self.num_rows, info["columns"])
        table.setHorizontalHeaderLabels(info["header_labels"])
        
        for row in range(self.num_rows):
            for col in range(info["columns"]):
                if info["editor_types"][col] == "line_edit":
                    item = QLineEdit()
                    table.setCellWidget(row, col, item)
                    self.column_inputs[(info["name"], info["header_labels"][col])] = item
                elif info["editor_types"][col] == "combo_box":
                    item = QComboBox()
                    item.addItems(self.get_combo_box_items(info["header_labels"][col]))
                    table.setCellWidget(row, col, item)
                    self.column_inputs[(info["name"], info["header_labels"][col])] = item
                else:
                    item = QTableWidgetItem()
                    
                table.setItem(row, col, QTableWidgetItem())
                
        table.resizeColumnsToContents()
            
        image_label = QLabel("Placeholder")
        image_label.setAlignment(Qt.AlignCenter)  # 文本居中显示
        image_label.setStyleSheet("background-color: #f0f0f0;")  # 设置背景色方便观察
        
        # 设置宽度比例:表格占2份,标签占1份
        horizontal_layout.addWidget(table)
        horizontal_layout.setStretchFactor(table, 2)
        horizontal_layout.addWidget(image_label)
        horizontal_layout.setStretchFactor(image_label, 1)
        
        tab_layout.addLayout(horizontal_layout)
        # 关键:添加包含布局的tab_widget到标签页
        self.tabs.addTab(tab_widget, info["name"])

额外优化建议

  • 若要显示图片,替换文本占位为image_label.setPixmap(QPixmap("你的图片路径")),并调用image_label.setScaledContents(True)让图片自适应标签大小。
  • 表格的resizeColumnsToContents()可能导致列宽过宽,可结合table.setMaximumWidth()或调整表头策略优化显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 07:12:33