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

4
我希望您能够等比例地更改 QTableView 窗口部件中所有列的列宽,以便每个列都具有相同的宽度,无论数据如何。例如,如果表格有三列,则每列的宽度应始终为可用水平空间的三分之一,并且每当用户调整对话框大小时,宽度应自动更新。
到目前为止,我只能将列调整为其内容的大小,这不是我想要的。以下是我目前的代码:
main.ui
<?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>

test.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
这可以通过设置节大小调整模式来实现。为了获得相等的列宽度:
self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

将内容垂直包裹:

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

不需要调用 resizeToContents, setWordWrap, 或者 setStretchLastSection。调用 setWordWrap(False) 将切换为将文本截断在右侧,而不是换行。

请注意,由于行/列调整大小是自动完成的,因此这些大小不再能够被用户或编程方式更改。


2

下面是一个例子(使用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”信号才能运行。每当“QTableWidget”改变宽度时都会执行“dynamic_column_resize”方法,但不应该触发“section_resized”方法,因为这样会导致无限循环,因为在“section_resized”方法结束时将调用“dynamic_column_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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接