Qt:使 TableView 的宽度适合内容的宽度 [英] Qt : Fit width of TableView to width of content

查看:85
本文介绍了Qt:使 TableView 的宽度适合内容的宽度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含 QTableView 的窗口,它根据内容调整列并且固定宽度.QTableView 嵌套在 QWidget 内,而 QWidget 又嵌套在 QScrollArea 内,而 QScrollArea 又嵌套在 tabbed 内> QMdiAreaQMainWindowcentralWidget.

I have a window that contains a QTableView which columns are adjusted to content and are fixed in width. The QTableView is nested within a QWidget that in turn is nested within a QScrollArea that in turn is nested within a tabbed QMdiArea which is the centralWidget of a QMainWindow.

当显示 QScrollArea 时,QTableView 在我要删除的最后一列的右侧有额外的空间:

When the QScrollArea is shown, the QTableView has extra space to the right of the last column that I want to be removed :

我希望 QTableView 适合列的确切宽度(即最右边的列之后没有额外的空间).

I want the QTableView to fit the exact width of the columns (i.e. no extra space after the rightmost column).

我尝试使用 tableView.setFixedWidth(desired_width) 但后来它可以工作的唯一方法是迭代所有列并获取它们的宽度并将它们汇总在一起并添加 verticalHeader 宽度和滚动条宽度并将其作为 desired_width 传递.

I tried to use tableView.setFixedWidth(desired_width) but then the only way it could work was to iterate over all the columns and get their widths and sum them up together and add the verticalHeader width and the scroll-bars width and pass it as the desired_width.

它确实以这种方式工作,但对于如此明显的要求似乎非常复杂:我认为很多程序开发人员希望他们的表格宽度适合列的宽度,这让我想知道也许有一种无需额外计算即可自动执行此操作的方法,这是我不知道的.

It does work this way but it seems to be very complex for such an obvious requirement : I think a lot of program developers want their tables' width to fit the columns' width and this is what makes me wonder that maybe there is a method that does that automatically without the extra calculations and that I'm unaware of.

所以我的问题是:有没有更简单的方法来达到相同的结果?

So my question is : is there a simpler way to achieve the same result ?

这是我的代码供参考:

负责创建QMainWindowt_main模块的代码:

The code for the t_main module responsible for creating the QMainWindow :

import sys
import t_wdw
from PySide import QtGui

class Main_Window(QtGui.QMainWindow):
    def __init__(self):
        super(Main_Window,self).__init__()
        self.initUI()


    def initUI(self):
        self.statusBar()
        # Defines QActions for menu
        self.new_window=QtGui.QAction("&Window alpha",self)
        self.new_window.triggered.connect(self.open_window)
        # Creates the menu
        self.menu_bar=self.menuBar()
        self.menu1=self.menu_bar.addMenu('&Menu 1')
        self.menu1.addAction(self.new_window)
        # Creates a QMdiArea to manage all windows.
        self.wmanager=QtGui.QMdiArea()
        self.wmanager.setViewMode(QtGui.QMdiArea.TabbedView)
        self.setCentralWidget(self.wmanager)
        self.showMaximized()

    # Opens the new window that holds the QTableView
    def open_window(self):
        t_wdw.launch_window()
        t_wdw.window_alpha=self.wmanager.addSubWindow(t_wdw.window)
        t_wdw.window_alpha.show()

def main():
    app=QtGui.QApplication(sys.argv)
    main_wdw=Main_Window()
    sys.exit(app.exec_())

if __name__=="__main__":
    main()

t_wdw 模块的代码,负责使用 QTableView 创建 SubWindow.

The code for t_wdw module that is responsible for creating the SubWindow with the QTableView.

from PySide import QtGui
from PySide import QtCore

def launch_window():
    global window
    # Creates a new window
    window=QtGui.QScrollArea()
    window1=QtGui.QWidget()
    row=0
    data=[["VH"+str(row+i),1,2,3] for i in range(20)]
    headers=["HH1","HH2","HH3"]
    # Creates a table view with columns resized to fit the content.
    model=my_table(data,headers)
    tableView=QtGui.QTableView()
    tableView.setModel(model)
    tableView.resizeColumnsToContents()
    # Fixes the width of columns and the height of rows.
    tableView.horizontalHeader().setResizeMode(QtGui.QHeaderView.Fixed)
    tableView.verticalHeader().setResizeMode(QtGui.QHeaderView.Fixed)

    """
    Here is the solution I resorted to to fix the tableView width 
    equal to its content and that I want to make simpler
    """
    vhwidth=tableView.verticalHeader().width()
    desired_width=QtGui.QStyle.PM_ScrollBarExtent*2+vhwidth+1
    for i in range(len(headers)):
        desired_width+=tableView.columnWidth(i)
    tableView.setFixedWidth(desired_width)

    """
    Sets the layouts and widgets using a QHBoxLayout because
    I want the QTableView to be centered on the window
    and more widgets and layouts are to be added later.
    """

    window1.main_layout=QtGui.QHBoxLayout()
    window1.main_layout.addStretch(0)
    window1.main_layout.addWidget(tableView)
    window1.main_layout.addStretch(0)
    window.setLayout(window1.main_layout)
    window.setWidget(window1)

class my_table(QtCore.QAbstractTableModel):

    def __init__(self,data,headers,parent=None):
        QtCore.QAbstractTableModel.__init__(self,parent)
        self.__data=data
        self.__headers=headers

    def rowCount(self,parent):
        return len(self.__data)

    def columnCount(self,parent):
        return len(self.__headers)

    def data(self, index, role):
        if role == QtCore.Qt.DisplayRole:
            row = index.row()
            column = index.column()
            return self.__data[row][column+1]

    def headerData(self,section,orientation,role):
        if role == QtCore.Qt.DisplayRole:
            if orientation == QtCore.Qt.Horizontal:
                return self.__headers[section]
            if orientation == QtCore.Qt.Vertical:
                return self.__data[section][0]

给阅读代码的人一个额外的问题:为什么我需要将 PM_ScrollBarExtent 乘以 2 才能得到正确的结果?

An extra question for those who read the code : Why do I need to multiply PM_ScrollBarExtent by 2 to get the correct result ?

P.S:我使用的是 PySide 1.2.1,但 PyQt 或 C++ 中的答案很好.

P.S : I'm using PySide 1.2.1 but answers in PyQt or C++ are fine.

推荐答案

关于您的宽度计算有一些错误.

There are a couple of things about your width calcualtion that are wrong.

首先,您尝试使用 QtGui.QStyle.PM_ScrollBarExtent 来获取垂直滚动条的宽度 - 但这是一个常量,而不是一个属性.相反,您需要使用 QStyle.pixelMetric:

Firstly, you attempt to use QtGui.QStyle.PM_ScrollBarExtent to get the width of the vertical scrollbar - but that is a constant, not a property. Instead, you need to use QStyle.pixelMetric:

tableView.style().pixelMetric(QtGui.QStyle.PM_ScrollBarExtent)

其次,你没有考虑tableview框架的宽度,可以这样计算:

Secondly, you do not take into account the width of the tableview frame, which can be calculated like this:

tableView.frameWidth() * 2

将这些值与标题的尺寸放在一起,最终计算应为:

Putting these values together with the dimensions of the headers, the final calculation should be:

vwidth = tableView.verticalHeader().width()
hwidth = tableView.horizontalHeader().length()
swidth = tableView.style().pixelMetric(QtGui.QStyle.PM_ScrollBarExtent)
fwidth = tableView.frameWidth() * 2

tableView.setFixedWidth(vwidth + hwidth + swidth + fwidth)

这应该正好为垂直滚动条留下所需的空间.

This should leave exactly the space needed for the vertical scrollbar.

附注:

由于您为 tableview 设置了固定宽度,您还可以去掉水平滚动条,这是多余的:

Since you're setting a fixed width for the tableview, you could also get rid of the horizontal scrollbar, which is redundant:

tableView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)

这篇关于Qt:使 TableView 的宽度适合内容的宽度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆