Qt: установите ширину TableView на ширину содержимого
у меня есть окно, которое содержит QTableView
, который столбцы настраиваются на содержание и фиксированной ширины. The QTableView
вложен в QWidget
это, в свою очередь, вложено в QScrollArea
это, в свою очередь, вложено в вкладки QMdiArea
что это centralWidget
of a QMainWindow
.
когда QScrollArea
показал,QTableView
имеет дополнительное пространство справа от последнего столбца, который я хочу удалить :
я хочу QTableView
чтобы соответствовать точной ширине столбцов (т. е. без дополнительного пространства после самого правого столбца).
я пытался использовать tableView.setFixedWidth(desired_width)
но тогда единственный способ, которым он мог работать, - это перебрать все столбцы, получить их ширину, суммировать их вместе и добавить verticalHeader
ширина и ширина полосы прокрутки и передать его как desired_width
.
это работает, но это кажется очень сложным для такой явный требование: я думаю, что многие разработчики программ хотят, чтобы ширина их таблиц соответствовала ширине столбцов, и это заставляет меня задуматься, что, возможно, есть метод, который делает это автоматически без дополнительных вычислений, и что я не знаю.
Итак, мой вопрос : есть ли более простой способ достичь того же результата ?
вот мой код для ссылки :
код t_main
модуль, ответственный за создание 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
модуль, который отвечает за создание SubWindow
С 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, чтобы получить правильный результат ?
P. S: Я использую PySide 1.2.1, но ответы на PyQt или C++ в порядке.
3 ответов
есть несколько вещей о вашей калькуляции ширины, которые являются неправильными.
во-первых, вы пытаетесь использовать QtGui.QStyle.PM_ScrollBarExtent
чтобы получить ширину вертикальной полосы прокрутки - но это константа, а не собственность. Вместо этого вам нужно использовать класса qstyle.pixelMetric:
tableView.style().pixelMetric(QtGui.QStyle.PM_ScrollBarExtent)
во-вторых, вы не учитываете ширину рамки tableview, которая может быть рассчитана следующим образом:
tableView.frameWidth() * 2
сложение этих значений вместе с размерами заголовки, окончательный расчет должен быть:
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)
Это должно оставить точно пространство, необходимое для вертикальной полосы прокрутки.
PS:
поскольку вы устанавливаете фиксированную ширину для tableview, вы также можете избавиться от горизонтальной полосы прокрутки, которая является избыточной:
tableView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
В C++ можно сделать что-то вроде этого:
tableview->resizeColumnsToContents();
QHeaderView* header = tableview->horizontalHeader();
header->setStretchLastSection(true);
tablewview->setHorizontalHeader(header);
начиная с Qt 5.2 вы можете использовать следующее:
view->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContentsOnFirstShow);
или
view->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);