代码之家  ›  专栏  ›  技术社区  ›  Nemo XXX

如何在QTableView中按比例调整列宽?

  •  3
  • Nemo XXX  · 技术社区  · 7 年前

    我想 按比例地 更改QTableView小部件中所有列的列宽,以便无论数据如何,每列都具有相同的宽度。例如,如果一个表有三列,则每列的宽度应始终为可用水平空间的三分之一,并且每当用户调整对话框的大小时,宽度应自动更新。

    到目前为止,我只设法将列调整为其内容,这不是我想要的。以下是我目前掌握的代码:

    主要的用户界面

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>Dialog</class>
     <widget class="QDialog" name="Dialog">
      <property name="geometry">
       <rect>
        <x>0</x>
        <y>0</y>
        <width>624</width>
        <height>329</height>
       </rect>
      </property>
      <property name="sizePolicy">
       <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
        <horstretch>0</horstretch>
        <verstretch>0</verstretch>
       </sizepolicy>
      </property>
      <property name="windowTitle">
       <string>Dialog</string>
      </property>
      <layout class="QVBoxLayout" name="verticalLayout">
       <item>
        <layout class="QHBoxLayout" name="horizontalLayout">
         <item>
          <widget class="QTableView" name="tableView">
           <property name="alternatingRowColors">
            <bool>true</bool>
           </property>
           <property name="selectionBehavior">
            <enum>QAbstractItemView::SelectRows</enum>
           </property>
          </widget>
         </item>
         <item>
          <layout class="QVBoxLayout" name="verticalLayout_2">
           <item>
            <widget class="QPushButton" name="btnPopulate">
             <property name="text">
              <string>Populate</string>
             </property>
            </widget>
           </item>
          </layout>
         </item>
        </layout>
       </item>
      </layout>
     </widget>
     <tabstops>
      <tabstop>btnPopulate</tabstop>
     </tabstops>
     <resources/>
     <connections/>
    </ui>
    

    测验py公司

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    import sys, os
    from PyQt5 import uic
    from PyQt5.QtGui import QStandardItemModel
    from PyQt5.QtWidgets import QDialog, QApplication, QHeaderView
    
    class GUI(QDialog):
    
        def __init__(self):
            super(GUI, self).__init__()
            dirname = os.path.dirname(os.path.abspath(__file__))
            uic.loadUi(os.path.join(dirname,'main.ui'), self)
            # button
            self.btnPopulate.clicked.connect(self.populate)
            # table model
            self.header = ['col1', 'col2', 'col3']
            self.QSModel = QStandardItemModel()
            self.QSModel.setColumnCount(3)
            self.QSModel.setHorizontalHeaderLabels(self.header)
            # table view
            self.tableView.setModel(self.QSModel)
            self.tableView.setWordWrap(True)
            self.tableView.horizontalHeader().setStretchLastSection(False)
    
        def populate(self):
            self.longtext = '''Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ac tellus nunc. Phasellus imperdiet leo metus, et gravida lacus. Donec metus ligula, elementum at pellentesque pellentesque, suscipit ac nunc.'''
            row = self.QSModel.rowCount()
            for x in range(7):
                self.QSModel.insertRow(row)
                self.QSModel.setData(self.QSModel.index(row, 0), 'Lorem ipsum')
                self.QSModel.setData(self.QSModel.index(row, 1), self.longtext)
                self.QSModel.setData(self.QSModel.index(row, 2), 'Lorem ipsum')
            self.tableView.resizeColumnsToContents()
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        window = GUI()
        window.show()
        sys.exit(app.exec_())
    

    我有以下问题:

    1. 如何更改代码以按比例调整列宽?
    2. 为什么不 setWordWrap(True) 是否包装文本?
    2 回复  |  直到 7 年前
        1
  •  5
  •   ekhumoro    7 年前

    这可以通过以下方式实现 setting the section resize mode . 要获得相等的列宽,请执行以下操作:

    self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
    

    要垂直包装内容,请执行以下操作:

    self.tableView.verticalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
    

    没有必要打电话 resizeToContents , setWordWrap setStretchLastSection . 使命感 setWordWrap(False) 将切换到删除右侧的文本,而不是换行。

    请注意,由于行/列的大小调整是自动完成的,因此用户或程序无法再更改大小。

        2
  •  2
  •   Kurtbs    4 年前

    下面的示例(PySide,使用QT 4.8)将按比例将列宽更改为QTableView的宽度。当用户手动调整列的宽度时(双击或拖动节标题),从那时起,该特定列的宽度将保持不变,而其他列将按比例填充剩余空间。

    from PySide.QtGui import *
    from PySide.QtCore import QEvent
    
    class CustomTableView(QTableView):
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.verticalHeader().hide()
            self.horizontalHeader().sectionResized.connect(self.section_resized)
            self.dynamically_resized = False
            self.fixed_section_widths = dict()
    
        @disconnect_section_resized
        def dynamic_column_resize(self):
            flexible_width = self.width() - 2 - sum(self.fixed_section_widths.values())
            column_count = self.model().columnCount()
            flexible_column_count = column_count - len(self.fixed_section_widths)
            column_width = flexible_width // flexible_column_count if flexible_column_count else 1
            last_flexible_column_width = column_width + flexible_width % column_width
            for column_index in range(column_count):
                if column_index not in self.fixed_section_widths:
                    width = column_width if flexible_column_count > 1 else last_flexible_column_width
                    flexible_column_count = flexible_column_count - 1
                else:
                    width = self.fixed_section_widths[column_index]
                self.setColumnWidth(column_index, width)
            self.dynamically_resized = True
    
        def section_resized(self, column_index, old_size, new_size):
            if not self.dynamically_resized:
                return
            self.fixed_section_widths[column_index] = self.columnWidth(column_index)
            self.dynamic_column_resize()
    
        def eventFilter(self, obj, event):
            if event.type() == QEvent.Resize:
                self.dynamic_column_resize()
                return True
            return super(QTableView, self).eventFilter(obj, event)
    

    这个 section_resized 方法旨在为某一列应用固定宽度,只应在以下情况下运行 sectionResized 信号已由(手动)用户交互发出。这个 dynamic_column_resize 方法(每次 QTableWidget 更改宽度)不应触发 section\u已调整大小 方法,因为这样会有一个无限循环,因为在 section\u已调整大小 这个 dynamic\u column\u resize动态调整列大小 方法被调用。以下装饰器用于防止出现这种情况:

    def disconnect_section_resized(func):
        def wrapper(self):
            self.horizontalHeader().sectionResized.disconnect(self.section_resized)
            func(self)
            self.horizontalHeader().sectionResized.connect(self.section_resized)
        return wrapper