Hello,
I am trying to use an editor made of two QDoubleSpinBox when subclassing QStyledItemDelegate. I have no problem connecting the delegate and editor to the model but I failed to have my editor to show up in my view. I had no such problem with a simpler editor (e.g. a single QSpinBox).
Constructor for the Editor
Data_editor
::Data_editor( QWidget *parent
){
layout
->addWidget
(new QLabel("Lower",
this));
layout->addWidget(lower_bound_spin_);
layout->addStretch();
layout
->addWidget
(new QLabel("Upper",
this));
layout->addWidget(upper_bound_spin_);
this->setLayout(layout);
this->setFocusPolicy( Qt::StrongFocus );
}
Data_editor::Data_editor( QWidget *parent)
:QFrame(parent)
{
lower_bound_spin_ = new QDoubleSpinBox(this);
upper_bound_spin_ = new QDoubleSpinBox(this);
QHBoxLayout* layout = new QHBoxLayout(this);
layout->addWidget(new QLabel("Lower", this));
layout->addWidget(lower_bound_spin_);
layout->addStretch();
layout->addWidget(new QLabel("Upper", this));
layout->addWidget(upper_bound_spin_);
this->setLayout(layout);
this->setFocusPolicy( Qt::StrongFocus );
}
To copy to clipboard, switch view to plain text mode
Implementation of the delegate
{
Data_editor* editor = new Data_editor( parent);
return editor;
}
{
QStyledItemDelegate::paint(painter, option, index);
}
{
return QStyledItemDelegate::sizeHint(option, index);
}
void Data_delegate
::updateEditorGeometry(QWidget *editor,
{
editor->setGeometry(option.rect);
}
QWidget *Data_delegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
Data_editor* editor = new Data_editor( parent);
return editor;
}
void Data_delegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QStyledItemDelegate::paint(painter, option, index);
}
QSize Data_delegate::sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
return QStyledItemDelegate::sizeHint(option, index);
}
void Data_delegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
{
editor->setGeometry(option.rect);
}
To copy to clipboard, switch view to plain text mode
I played a bit with eventFilter and try to record the log of the events passing through
{
Data_editor *editor = qobject_cast<Data_editor*>(object);
if (!editor)
return false;
QEvent::Type t
= event
->type
();
std::string class_name = (w_focused!=0)?w_focused->metaObject()->className():std::string("000");
ostream_<<class_name <<
" "<<
QString("%1").
arg(t
).
toStdString()+"\n";
if (event
->type
() == QEvent::KeyPress) { switch (static_cast<QKeyEvent *>(event)->key()) {
case Qt::Key_Tab:
emit commitData(editor);
return true;
case Qt::Key_Backtab:
emit commitData(editor);
return true;
case Qt::Key_Enter:
case Qt::Key_Return:
QMetaObject::invokeMethod(this,
"_q_commitDataAndCloseEditor",
Qt
::QueuedConnection, Q_ARG
(QWidget*, editor
));
return false;
case Qt::Key_Escape:
// don't commit data
break;
default:
return false;
}
if (editor->parentWidget())
editor->parentWidget()->setFocus();
return true;
} else if (event
->type
() == QEvent::FocusOut ||
(event
->type
() == QEvent::Hide && editor
->isWindow
())) { //the Hide event will take care of he editors that are in fact complete dialogs
//if (!editor->isActiveWindow() || (QApplication::focusWidget() != editor)) {
if (!editor->isActiveWindow() || (w_focused != editor)) {
//QWidget *w = QApplication::focusWidget();
while (w) { // don't worry about focus changes internally in the editor
if (w == editor)
return false;
w = w->parentWidget();
}
emit commitData(editor);
emit closeEditor(editor, NoHint);
}
} else if (event
->type
() == QEvent::ShortcutOverride) { if (static_cast<QKeyEvent*>(event)->key() == Qt::Key_Escape) {
event->accept();
return true;
}
}
return false;
}
bool Data_delegate::eventFilter(QObject *object, QEvent *event)
{
Data_editor *editor = qobject_cast<Data_editor*>(object);
if (!editor)
return false;
QWidget *w_focused = QApplication::focusWidget();
QEvent::Type t = event->type();
std::string class_name = (w_focused!=0)?w_focused->metaObject()->className():std::string("000");
ostream_<<class_name <<" "<< QString("%1").arg(t).toStdString()+"\n";
if (event->type() == QEvent::KeyPress) {
switch (static_cast<QKeyEvent *>(event)->key()) {
case Qt::Key_Tab:
emit commitData(editor);
emit closeEditor(editor, QAbstractItemDelegate::EditNextItem);
return true;
case Qt::Key_Backtab:
emit commitData(editor);
emit closeEditor(editor, QAbstractItemDelegate::EditPreviousItem);
return true;
case Qt::Key_Enter:
case Qt::Key_Return:
QMetaObject::invokeMethod(this, "_q_commitDataAndCloseEditor",
Qt::QueuedConnection, Q_ARG(QWidget*, editor));
return false;
case Qt::Key_Escape:
// don't commit data
emit closeEditor(editor, QAbstractItemDelegate::RevertModelCache);
break;
default:
return false;
}
if (editor->parentWidget())
editor->parentWidget()->setFocus();
return true;
} else if (event->type() == QEvent::FocusOut || (event->type() == QEvent::Hide && editor->isWindow())) {
//the Hide event will take care of he editors that are in fact complete dialogs
//if (!editor->isActiveWindow() || (QApplication::focusWidget() != editor)) {
if (!editor->isActiveWindow() || (w_focused != editor)) {
QWidget *w = w_focused;
//QWidget *w = QApplication::focusWidget();
while (w) { // don't worry about focus changes internally in the editor
if (w == editor)
return false;
w = w->parentWidget();
}
emit commitData(editor);
emit closeEditor(editor, NoHint);
}
} else if (event->type() == QEvent::ShortcutOverride) {
if (static_cast<QKeyEvent*>(event)->key() == Qt::Key_Escape) {
event->accept();
return true;
}
}
return false;
}
To copy to clipboard, switch view to plain text mode
Which output (first column widget className, second Qcolumn Event type):
Data_tree_view 75
Data_tree_view 70
Data_tree_view 70
Data_tree_view 70
Data_tree_view 70
Data_tree_view 69
Data_tree_view 69
Data_tree_view 69
Data_tree_view 69
Data_tree_view 13
Data_tree_view 14
Data_tree_view 17
Data_tree_view 26
Data_editor 8
Data_editor 67
Data_editor 74
Data_editor 12
Data_editor 10
Data_editor 11
Data_editor 12
Data_tree_view 9
The editor is painted (event 12) but is never shown. The last event (which probably occurred when I moved the cursor) is the FocusOut event which commit the data and close the editor.
So what is missing in my delegate/editor such the editor will be shown in my view? Online comments seem to point out to a focus issue but I cannot get it right.
Thanks
Bookmarks