Как сделать заголовки QTableWidget редактируемыми?
Я хочу чтобы пользователь мог изменять заголовки прямо в программе. Думал сделать через QTableWidgetItem , но это не сработало:
title = QTableWidgetItem() title.setFlags(Qt.ItemIsEditable) self.start.table.setHorizontalHeaderItem(1,title)
Отслеживать
73.5k 110 110 золотых знаков 38 38 серебряных знаков 55 55 бронзовых знаков
задан 5 окт 2019 в 18:57
Николай Михайлов Николай Михайлов
13 2 2 бронзовых знака
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
QTableWidget::setHorizontalHeaderItem(int column, QTableWidgetItem *item)
Устанавливает горизонтальный элемент заголовка для столбца столбца в item.
QTableWidgetItem::setText(const QString &text)
Устанавливает item’s text в указанный text.
from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class Dialog(QDialog): def __init__(self, parent=None): super(Dialog, self).__init__(parent) self.tableWidget = QTableWidget(2, 3) self.tableWidget.setHorizontalHeaderLabels(["A", "B", "C"]) self.lineEdit_0 = QLineEdit() self.lineEdit_1 = QLineEdit() self.lineEdit_2 = QLineEdit() lay = QGridLayout(self) lay.addWidget(self.tableWidget, 0, 0, 1, 3) lay.addWidget(self.lineEdit_0, 1, 0) lay.addWidget(self.lineEdit_1, 1, 1) lay.addWidget(self.lineEdit_2, 1, 2) lay.addWidget(QPushButton("New Header 0", clicked=self.onClick), 2, 0) lay.addWidget(QPushButton("New Header 1", clicked=self.onClick), 2, 1) lay.addWidget(QPushButton("New Header 2", clicked=self.onClick), 2, 2) def onClick(self): sender = self.sender() if sender.text() == "New Header 0": title = QTableWidgetItem() #

Update
Я бы хотел чтобы заголовки редактировались как и ячейки:двойной щелчёк мышкой и пишешь прямо в заголовке.
Класс QHeaderView предоставляет строку заголовка или столбец заголовка для представлений элементов.
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * class HeaderView(QtWidgets.QHeaderView): def __init__(self, parent): super(HeaderView, self).__init__(QtCore.Qt.Horizontal, parent) self.m_labels = [] self.sectionResized.connect(self.adjustPositions) self.sectionCountChanged.connect(self.onSectionCountChanged) self.parent().horizontalScrollBar().valueChanged.connect(self.adjustPositions) @QtCore.pyqtSlot() def onSectionCountChanged(self): while self.m_labels: label = self.m_labels.pop() label.deleteLater() for i in range(self.count()): label = QtWidgets.QLineEdit(self) label.setStyleSheet("QLineEdit < color: red; font-size: 12px; >") self.m_labels.append(label) self.update_data() self.adjustPositions() def setModel(self, model): super(HeaderView, self).setModel(model) if self.model() is not None: self.model().headerDataChanged.connect(self.update_data) def update_data(self): option = QtWidgets.QStyleOptionHeader() self.initStyleOption(option) for i, label in enumerate(self.m_labels): text = self.model().headerData( i, self.orientation(), QtCore.Qt.DisplayRole ) label.setText(str(text)) pal = label.palette() bc = self.model().headerData( i, self.orientation(), QtCore.Qt.BackgroundRole ) if bc is None: bc = option.palette.brush(QtGui.QPalette.Window) pal.setBrush(QtGui.QPalette.Window, bc) fc = self.model().headerData( i, self.orientation(), QtCore.Qt.ForegroundRole ) if fc is None: fc = option.palette.brush(QtGui.QPalette.ButtonText) pal.setBrush(QtGui.QPalette.ButtonText, fc) label.setPalette(pal) textAlignment = self.model().headerData( i, self.orientation(), QtCore.Qt.TextAlignmentRole ) if textAlignment is None: textAlignment = self.defaultAlignment() label.setAlignment(textAlignment) def updateGeometries(self): super(HeaderView, self).updateGeometries() self.adjustPositions() @QtCore.pyqtSlot() def adjustPositions(self): for index, label in enumerate(self.m_labels): geom = QtCore.QRect( self.sectionViewportPosition(index), 0, self.sectionSize(index), self.height(), ) geom.adjust(2, 0, -2, 0) label.setGeometry(geom) class Dialog(QDialog): def __init__(self, parent=None): super(Dialog, self).__init__(parent) self.tableWidget = QTableWidget(2, 3) header = HeaderView(self.tableWidget) self.tableWidget.setHorizontalHeader(header) header_labels = [] for i in range(self.tableWidget.columnCount()): header_label = "Column-<>".format(i) header_labels.append(header_label) self.tableWidget.setHorizontalHeaderLabels(header_labels) lay = QGridLayout(self) lay.addWidget(self.tableWidget) if __name__ == "__main__": import sys app = QApplication(sys.argv) w = Dialog() w.resize(340, 150) w.exec_()
Qt C++ qtableWidget как отловить нажатие на заголовок столбца?
Нужно вызвать событие void при клике на заголовок столбца с передачей индекса этого столбца, как сделать?
- Вопрос задан более трёх лет назад
- 288 просмотров
Комментировать
Решения вопроса 0
Ответы на вопрос 1

Ighor July @IGHOR Куратор тега Qt
Qt/C++ DEV/CTO
Возможно тут ответили на ваш вопрос https://stackoverflow.com/questions/11596267/qtabl.
PS: QTableWidget очень медленный если у вас больше 20 строк, следует использовать модель и QTableView
Ответ написан более трёх лет назад
Комментировать
Нравится 1 Комментировать
Qt C++ qtableWidget как запретить выделение столбца и заменить сортировкой при клике по заголовку?
Есть таблица qtableWidget, при клике на заголовок столбца происходит его выделение, как запретить выделение и вызывать событие void с передачей индекса нажатого столбца для сортировки?
ПС
Как сделать запрет выделения понял, а как передать индекс столбца?
Будущим поколениям в поиске.
// Запрет выделения столбца и выделение всей строки ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); // Запрет массового выделения ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
- Вопрос задан более трёх лет назад
- 1280 просмотров
1 комментарий
Простой 1 комментарий
QTableView, интерактивное изменение заголовков
Здравствуйте.
Нужно добавить возможность изменения заголовков таблицы пользователем.
Кликнув 2 раза на ячейке можно изменить её. С заголовком это не проходит.
1) Как отловить клик мыши по заголовку?
При изменении ячейки мне нужно проверить, что введено число. И в случае ошибки вывести сообщение.
2) Какую функцию переопределить? Куда копать?
ecnpyt
23.01.10 13:38:43 MSK

model->setHeader() — так можно сменить заголовок.
Представление умеет сортировку по клику, значит мышь ловить оно умеет)
wyldrodney ☆
( 23.01.10 14:07:09 MSK )
Ответ на: комментарий от wyldrodney 23.01.10 14:07:09 MSK
Про model->setHeader() я знаю.
Ещё я знаю, что прийдется создать класс, который унаследует QTableView.
Продолжаю копать док-ю.
ecnpyt
( 23.01.10 14:24:48 MSK ) автор топика
Ответ на: комментарий от ecnpyt 23.01.10 14:24:48 MSK

может поможет сделать своего наследника QTableWidgetItem, назначить ему уже события на клики, и потом сделать setHorizontalHeaderItem(i, item) для каждого столбца при создании таблички?
RedPossum ★★★★★
( 23.01.10 14:53:35 MSK )
Ответ на: комментарий от RedPossum 23.01.10 14:53:35 MSK

но это для QTableWidget
RedPossum ★★★★★
( 23.01.10 14:54:30 MSK )

это надо читать маны в сторону делегатов (delegates)
azure ★★
( 23.01.10 16:01:13 MSK )
Секции QHeaderView не имеют индексов в модели (QModelIndex), поэтому редактировать их обычным способом не получится. Можно обрабатывать сигнал QHeaderView::sectionDoubleClicked ( int logicalIndex ), создавая редактор над указанной секцией.
Редактором тогда будет какой-нибудь QLineEdit, через installEventFilter получающий фильтр, который должен будет ловить нажатия Enter, Esc и т.д., подтверждая изменения через QSqlQueryModel::setHeaderData() например, и/или уничтожая редактор.
При изменении ячейки мне нужно проверить, что введено число
Если для указанного QLineEdit при создании вызвать setValidator( new QIntValidator( this ) ), то ввести туда можно будет только целое число.
summatus ★
( 23.01.10 18:39:26 MSK )
Ответ на: комментарий от azure 23.01.10 16:01:13 MSK
Спасибо. Я создал делегата, у которого в качестве редактора используется QDoubleSpinBox. Это решило проблему фильтрации ввода автоматически.
ecnpyt
( 24.01.10 12:49:21 MSK ) автор топика
Ответ на: комментарий от summatus 23.01.10 18:39:26 MSK
Да, спасибо за подсказки.
Из QTableView я смог получить QHeaderView. И соединить сигнал sectionDoubleClicked ( int logicalIndex ) со своим слотом.
Но как создать над заголовком редактор пока не понял.
ecnpyt
( 24.01.10 12:52:06 MSK ) автор топика
Ответ на: комментарий от ecnpyt 24.01.10 12:52:06 MSK
Пока что я сделал проще. При нажатии на заголовок появляется диалог со строкой ввода. А потом я просто устанавливаю новое имя.
Вот кусочек кода из слота:
bool ok;
QString text = QInputDialog::getText(this, tr(«QInputDialog::getText()»), tr(«Заголовок:»), QLineEdit::Normal,
tr("")), &ok);
if (ok && !text.isEmpty()) {
QStandardItem *p_item = new QStandardItem(text);
tablemodel->setVerticalHeaderItem(section, p_item);
}
Но вопрос с созданием редактора внутри заголовка открыт.
Я попробовал применить к QHeaderView делагат, который создал для обычных ячеек. QHeaderView является потомком QAbstractView, у которого есть метод setItemDelegate. Но по нажатию на заголовок редактор не появляется, заголовок просто выделяется. Наверно, надо изменить какие-то свойства заголовка, но я не нашел ничего подходящего.
ecnpyt
( 24.01.10 13:14:19 MSK ) автор топика
Ответ на: комментарий от ecnpyt 24.01.10 12:52:06 MSK
>Но как создать над заголовком редактор пока не понял.
Потомок будет нарисован в родителе, если это указать, например, при его создании. Т.к. QHeaderView - часть QTableView, то если указать таблицу в качестве parent для любого виджета, он будет в ней нарисован.
Для позиционирования редактора в заголовке, видимо, придётся его помещать в какой-нибудь layout, а сам layout создавать в таблице. Методом QXXXLayout::addSpacing, задавать смещение редактора. Нужное смещение и ширину можно узнать при помощи QHeaderView::sectionSize().
Вообще правильный путь в твоём случае - наследовать QHeaderView -> EditableHeaderView, и переопределять методы обработки событий мыши и отрисовки. То что я предлагаю, в сравнении с этим - костыль.