【发布时间】:2014-01-14 20:24:21
【问题描述】:
我有一个包含QTableView 的窗口,其中列已调整为内容并且宽度固定。 QTableView 嵌套在 QWidget 中,而 QScrollArea 又嵌套在 QMdiArea 中,QMdiArea 是 centralWidget 的 QMainWindow .
当显示QScrollArea 时,QTableView 在我要删除的最后一列右侧有额外的空间:
我希望QTableView 适合列的确切宽度(即最右边的列之后没有多余的空间)。
我尝试使用tableView.setFixedWidth(desired_width),但唯一可行的方法是遍历所有列并获取它们的宽度并将它们相加并添加verticalHeader 宽度和滚动条宽度并传递它作为desired_width。
它确实以这种方式工作,但对于如此明显的要求似乎非常复杂:我认为很多程序开发人员希望他们的表格宽度适合列的宽度,这让我想知道也许有一种无需额外计算即可自动执行此操作且我不知道的方法。
所以我的问题是:有没有更简单的方法可以达到同样的效果?
这是我的参考代码:
负责创建QMainWindow 的t_main 模块的代码:
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。
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 才能得到正确的结果?
P.S:我使用的是 PySide 1.2.1,但 PyQt 或 C++ 中的答案很好。
【问题讨论】:
-
您可以使用
tableView.visualRect(model.index(0, model.columnCount() - 1)).right()之类的东西,而不是遍历所有列。 -
谢谢,但似乎不起作用,visualRect 返回 (0,0,0,0)。
-
我设法使用
tableView.horizontalHeader().length()来避免迭代,但我仍然需要用tableView.verticalHeader().width()和PM_ScrollBarExtent*2来总结它。
标签: qt pyside qtableview