Я сделал подкласс QTableWidget
и хотел, чтобы некоторые ячейки имели QPushButtons
в качестве виджетов ячеек, так как я сделал довольно сильно стилизованную кнопку, используя QPropertyAnimations
, а что нет, и действительно хотел встроить виджет вклетка.Я использовал функцию setCellWidget(QWidget* widget)
, которая является частью QTableWidget
, и она была почти идеальной.Так как я делаю некоторые подклассы QStyledItemDelegate
рисования классов на элементах ячейки моей таблицы, я рисую некоторые линии границ, которые, кажется, немного конфликтуют с размером виджета ячейки.
Ранее кто-то спрашивал, как центрировать QCheckBox
в ячейке QTableWidget's
, поэтому она не смещена с левой стороны.Ответ на этот вопрос был по существу следующим:
- Создайте
QWidget
- Создайте
QWidget
, который вы хотите центрировать - Создайте
QH/VLayout
иустановите макет верхнего уровня QWidget's
таким: - Добавьте вспомогательный виджет, который вы хотите центрировать в этом макете
- На
QTableWidget
используйте функцию setCellWidget
и установите его длястрока и столбец с верхним уровнем QWidget
и вуаля, у вас есть центрированный QWidget
в ячейке, которой вы можете манипулировать и выравнивать, как вам захочется
Отлично, это визуально сработало ...Однако я заметил некоторые неприятные побочные эффекты этого.Навигация клавиш со стрелками, кажется, сломалась, и я больше не могу нажимать клавишу Enter или клавишу пробела, чтобы «щелкнуть / нажать» QPushButton
, который я встроил в управляющий QWidget
для этой конкретной ячейки.Кажется, что смена фокуса внутренне что-то портит на QTableWidget
при попытке отойти от клетки с помощью клавиш со стрелками на клавиатуре.
Я читал в Интернете, что некоторые люди сказали отключить setTabKeyNavigation(bool)
на столе, чтобы исправить некоторые подобные проблемы с навигацией после установки фокуса ... Это ничего не сделало в моем случае.Я сделал минимальный компилируемый пример, который показывает случаи поведения
TableWidget.h:
#ifndef TABLEWIDGET_H
#define TABLEWIDGET_H
#include "button.h"
#include "widget.h"
#include <QTableWidget>
#include <QDebug>
class TableWidget : public QTableWidget{
Q_OBJECT
public:
TableWidget(QWidget* parent = nullptr);
Widget *createWidget();
Button *createButton();
void setTableCell(QWidget *selecteditem);
};
#endif // TABLEWIDGET_H
TableWidget.cpp:
#include "tablewidget.h"
TableWidget::TableWidget(QWidget* parent) : QTableWidget(parent){
setFixedSize(750, 500);
setColumnCount(5);
for(int i = 0; i < 5; ++i){
insertRow(rowCount());
for(int j = 0; j < columnCount(); ++j){
QTableWidgetItem* item = new QTableWidgetItem;
item->setFlags(item->flags() ^ Qt::ItemIsEditable);
setItem(j, i, item);
}
}
setCellWidget(0, 0, createButton());
setCellWidget(2, 0, createWidget());
}
Button* TableWidget::createButton(){
Button* button = new Button;
connect(button, &Button::focusReceived, this, [this, button](){ setTableCell(button); }, Qt::DirectConnection);
return button;
}
Widget* TableWidget::createWidget(){
Button* button = new Button;
connect(button, &Button::focusReceived, this, [this, button](){ setTableCell(button); }, Qt::DirectConnection);
return new Widget(button);
}
//Helper to make keyboard focus more intuitive for cell widgets versus regular items
void TableWidget::setTableCell(QWidget* selecteditem){
//Find the sender in the table
for(int row = 0; row < rowCount(); ++row){
for(int col = 0; col < columnCount(); ++col){
if(cellWidget(row, col) == selecteditem){
qDebug() << "TableWidget::setTableCell";
setCurrentCell(row, col);
setCurrentItem(this->item(row, col));
setCurrentIndex(this->indexFromItem(this->item(row, col)));
return;
}
}
}
}
Button.h:
#ifndef BUTTON_H
#define BUTTON_H
#include <QPushButton>
#include <QFocusEvent>
#include <QDebug>
class Button : public QPushButton{
Q_OBJECT
public:
Button(QWidget *parent = nullptr);
void focusIn(QFocusEvent *event);
signals:
void focusReceived();
public slots:
bool event(QEvent* e);
};
#endif // BUTTON_H
Button.cpp:
#include "button.h"
Button::Button(QWidget* parent) : QPushButton(parent){
setStyleSheet(QString("background-color: solid rgba(255, 0, 0, 75);"));
}
bool Button::event(QEvent* event){
switch(event->type()){
case QEvent::FocusIn:
focusIn(static_cast<QFocusEvent*>(event));
return true;
break;
default:
break;
}
return QWidget::event(event);
}
void Button::focusIn(QFocusEvent* event){
qDebug() << "Button::focusIn";
emit focusReceived();
QPushButton::focusInEvent(event);
}
Widget.h:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QFocusEvent>
#include <QHBoxLayout>
#include <QPointer>
#include "button.h"
class Widget : public QWidget{
Q_OBJECT
public:
Widget(Button* button, QWidget *parent = nullptr);
public slots:
bool event(QEvent* event);
void focusIn(QFocusEvent *event);
signals:
void focusReceived();
protected:
QPointer<QHBoxLayout> m_hLayout;
QPointer<Button> m_button;
};
#endif // WIDGET_H
Widget.cpp:
#include "widget.h"
Widget::Widget(Button* button, QWidget* parent) : QWidget(parent){
m_button = button;
setStyleSheet(QString("background-color: solid rgba(0, 0, 0, 0);"));
m_hLayout = new QHBoxLayout;
setLayout(m_hLayout);
m_hLayout->addWidget(m_button);
}
bool Widget::event(QEvent* event){
switch(event->type()){
case QEvent::FocusIn:
focusIn(static_cast<QFocusEvent*>(event));
return true;
break;
default:
break;
}
return QWidget::event(event);
}
void Widget::focusIn(QFocusEvent* event){
qDebug() << "Widget::focusIn";
emit focusReceived();
QWidget::focusInEvent(event);
}
Итак, когдапри навигации по TableWidget
вы ожидаете, что выделенные ячейки будут перемещаться с помощью курсора и «временно» придадут мягкий фокус виджету для событий клавиатуры.Это происходит ТОЛЬКО на объекте Button
.Объект Button
будет правильно печатать то, что в функции focusIn
было отключено, когда выбранная ячейка содержит его.Однако можно ожидать, что такое же поведение будет происходить и с Widget
, поскольку он добавляется точно так же с точно таким же кодом, только с Button
, встроенным в его QHBoxLayout
.Как только вы переходите к Button
или Widget
, клавиатура для TableWidget
кажется сломанной, и нажатия клавиш не пересылаются с Widget
на его дочерний Button
, даже если я должен был установить setFocusProxy
от Widget
до m_button
поля, которое точно такого же типа Button
, которое может правильно получить KeyEvent
.Я не совсем уверен, является ли это ошибкой или я исказил какое-то поведение.