Qt: начать редактирование ячейки после одного клика

По умолчанию ячейка в QTableView начинает редактироваться после двойного щелчка. Как изменить это поведение. Мне нужно, чтобы начать редактирование после одного клика.

Я установил делегат со списком в ячейку. При нажатии на ячейку он только выбирает ее. При двойном щелчке по ячейке QComboBox Редактор активирован, но не расширен. Я хочу, чтобы он расширялся после одного клика, как будто я добавил QComboBox от setCellWidget функция QTableWidget, Мне нужен тот же эффект, используя модель-представление-делегат.

5 ответов

Решение

Редактировать после одного клика Вы можете переопределить mousePressEvent в представлении, которое вы используете

void YourView::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        QModelIndex index = indexAt(event->pos());
        if (index.column() == 0) { // column you want to use for one click
            edit(index);
        }
    }
    QTreeView::mousePressEvent(event);
}

Расширенный QCombobox при редактировании. Вы должны реализовать setEditorData в своем подклассе QItemDelegate и в конце вызвать showPopup.

Но у него есть неожиданное поведение. QComboBox исчезает, когда мышь покидает свою область. Но для меня это преимущество. Я могу выбрать другой элемент одним щелчком мыши и отпустить.

void IconDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    Q_UNUSED(index);
    QComboBox *comboBox = qobject_cast<QComboBox*>(editor);
    // Add data
    comboBox->addItem(QIcon(":/icons/information16.png"), "info");
    comboBox->addItem(QIcon(":/icons/warning16.png"), "warning");
    comboBox->addItem(QIcon(":/icons/send16.png"), "send");
    comboBox->addItem(QIcon(":/icons/select16.png"), "select");
    comboBox->showPopup(); // <<<< Show popup here
}

Вместе это работает быстро. Нажмите и удерживайте, чтобы выбрать элемент и зафиксировать данные о выпуске (только один щелчок и отпустите)

Если вы хотите щелкнуть, чтобы показать развернутый qcombobox, а затем нажмите, чтобы выбрать / скрыть, я пока не знаю решения.

Вы можете просто установить триггер редактирования, используя эту функцию setEditTriggers

C++

yourView->setEditTriggers(QAbstractItemView::AllEditTriggers)

Python:

yourView.setEditTriggers(QAbstractItemView.AllEditTriggers)

enum QAbstractItemView:: EditTrigger flags QAbstractItemView:: EditTriggers

Это перечисление описывает действия, которые будут инициировать редактирование элемента.

Constant    Value   Description
QAbstractItemView::NoEditTriggers   0   No editing possible.
QAbstractItemView::CurrentChanged   1   Editing start whenever current item changes.
QAbstractItemView::DoubleClicked    2   Editing starts when an item is double clicked.
QAbstractItemView::SelectedClicked  4   Editing starts when clicking on an already selected item.
QAbstractItemView::EditKeyPressed   8   Editing starts when the platform edit key has been pressed over an item.
QAbstractItemView::AnyKeyPressed    16  Editing starts when any key is pressed over an item.
QAbstractItemView::AllEditTriggers  31  Editing starts for all above actions.

Тип EditTriggers - это typedef для QFlags. Он хранит комбинацию ИЛИ значений EditTrigger.

Основываясь на идее, предложенной Джейсоном, я придумал это решение.

Чтобы запустить редактор одним кликом, я подключил QAbstractItemView::clicked(const QModelIndex &index) сигнал моего взгляда, чтобы QAbstractItemView::edit(const QModelIndex &index) слот той же точки зрения.

Если вы используете Qt4, вам нужно создать слот в вашем делегате. Передайте свой комбобокс в качестве аргумента в этот слот. В этом слоте вы звоните QComboBox::showPopup, Так это будет выглядеть так:

void MyDelegate::popUpComboBox(QComboBox *cb)
{
    cb->showPopup();
}

Но сначала нам нужно зарегистрировать QComboBox* тип. Вы можете вызвать это в конструкторе вашего делегата:

qRegisterMetaType<QComboBox*>("QComboBox*");

Причина, по которой нам нужен этот слот, в том, что мы не можем сразу показать всплывающее окно в MyDelegate::createEditor, потому что позиция и прямоугольник представления списка неизвестны. Так что мы делаем в MyDelegate::createEditorмы называем этот слот с подключением в очереди:

QComboBox *cb = new QComboBox(parent);
// populate your combobox...
QMetaObject::invokeMethod(const_cast<MyDelegate*>(this), "popUpComboBox", Qt::QueuedConnection, Q_ARG(QComboBox*, cb));

Это покажет представление списка в выпадающем списке правильно, когда редактор активирован.

Теперь, если вы используете Qt5, слот не нужен. Все, что вы делаете, это звоните QComboBox::showPopup с подключением в очередь из MyDelegate::createEditor, Самый простой способ сделать это с QTimer:

QTimer::singleShot(0, cb, &QComboBox::showPopup);

Для получения дополнительной информации вы можете нарисовать комбинированный список так, чтобы он отображался постоянно, а не только при отображении редактора:

void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if(index.column() == 1) // show combobox only in the second column
    {
        QStyleOptionComboBox box;
        box.state = option.state;

        box.rect = option.rect;
        box.currentText = index.data(Qt::EditRole).toString();

        QApplication::style()->drawComplexControl(QStyle::CC_ComboBox, &box, painter, 0);
        QApplication::style()->drawControl(QStyle::CE_ComboBoxLabel, &box, painter, 0);
        return;
    }
    QStyledItemDelegate::paint(painter, option, index);
}

Это решение прекрасно работает для меня. Один щелчок по ячейке, и всплывающее меню.

class GFQtComboEnumItemDelegate : public QStyledItemDelegate
{
    void setEditorData(QWidget *editor, const QModelIndex &index) const
    {
        QComboBox* pE = qobject_cast<QComboBox*>(editor);
        ... // init the combo here
        if(m_must_open_box)
        {
            m_must_open_box = false;
            pE->showPopup();
        }
    }


    bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
    {
        if (event->type() == QEvent::MouseButtonRelease)
        {
            QMouseEvent* pME = static_cast<QMouseEvent*>(event);
            if(pME->button() == Qt::LeftButton)
            {
                QAbstractItemView* pView = qobject_cast<QAbstractItemView*>( const_cast<QWidget*>(option.widget) );
                if(pView != nullptr)
                {
                    emit pView->setCurrentIndex(index);
                    m_must_open_box = true;
                    emit pView->edit(index);
                }
                return true;
            }
        }
        return QStyledItemDelegate::editorEvent(event, model, option, index);
    }
    mutable bool m_must_open_box;
};

Если вы переопределите QStyledItemDelegate::createEditor() затем вы можете развернуть поле со списком после его создания.

Другие вопросы по тегам