QComboBox не показывает свой список элементов

У меня проблема с QComboBox в качестве редактора делегирования элементов для QTableWidget. QTableWidget использует SqlTypeDelegate в качестве делегата элемента.

Когда я рисую QTableWidget внутри QGraphicsScene (через QGraphicsProxyWidget), всплывающий список доступных элементов QComboBox не отображается. Но если я использую QTableWidget как обычный виджет (нарисованный не через QGraphicsScene\View), то поведение QComboBox нормальное - показывает список элементов.

Что мне делать, чтобы заставить QComboBox показать свой список элементов?

ниже пример кода:

основной.cpp:

#include <QtGui/QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QTableWidget>
#include "sqltypedelegate.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QGraphicsScene scene;
    QTableWidget *table = new QTableWidget(4,2);
    table->setItemDelegate(new SqlTypeDelegate(table));
    QGraphicsProxyWidget *proxy = scene.addWidget(table);
    QGraphicsView view(&scene);
    view.show();
    return app.exec();
}

sqltypedelegate.h:

#include <QItemDelegate>
#include <QStyledItemDelegate>
#include <QModelIndex>
#include <QObject>
#include <QSize>
#include <QComboBox>

class SqlTypeDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    SqlTypeDelegate(QObject *parent = 0);
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                          const QModelIndex &index) const;
    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model,
                      const QModelIndex &index) const;
    void updateEditorGeometry(QWidget *editor,
        const QStyleOptionViewItem &option, const QModelIndex &index) const;
};

sqltypedelegate.cpp:

#include <QtGui>
#include "sqltypedelegate.h"

SqlTypeDelegate::SqlTypeDelegate(QObject *parent)
    : QItemDelegate(parent)
{}

QWidget *SqlTypeDelegate::createEditor(QWidget *parent,
    const QStyleOptionViewItem &/* option */,
    const QModelIndex &/* index */) const
{
    QComboBox *editor = new QComboBox(parent);
    editor->addItem(QString("decimal(50)"));
    editor->addItem(QString("integer"));
    editor->addItem(QString("varchar(50)"));
    editor->addItem(QString("char"));

    editor->setEditable(true);
    return editor;
}

void SqlTypeDelegate::setEditorData(QWidget *editor,
                                    const QModelIndex &index) const
{
    QString value = index.model()->data(index, Qt::EditRole).toString();
    QComboBox *comboBox = static_cast<QComboBox*>(editor);
    comboBox->setEditText(value);
}

void SqlTypeDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                   const QModelIndex &index) const
{
    QComboBox *comboBox = static_cast<QComboBox*>(editor);
    model->setData(index, comboBox->currentText(), Qt::EditRole);
}

void SqlTypeDelegate::updateEditorGeometry(QWidget *editor,
    const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
{
    QComboBox *comboBox = static_cast<QComboBox*>(editor);
    comboBox->setGeometry(option.rect);
}

person msnxcp    schedule 09.01.2013    source источник


Ответы (2)


Наконец-то я нашел решение: фильтры событий! Просто спрячьтесь за QEvent::MouseButtonRelease, а затем вызовите showPopup.

bool SqlTypeDelegate::eventFilter(QObject *object, QEvent *event)
{
    QComboBox * comboBox = dynamic_cast<QComboBox*>(object);
    if (comboBox)
    {
        if (event->type() == QEvent::MouseButtonRelease)
        {
            comboBox->showPopup();
            return true;
        }
    }
    else
    {
        return QItemDelegate::eventFilter( object, event );
    }
    return false;
}
person msnxcp    schedule 12.03.2013
comment
Вы уверены, что это работает? В Python (PyQt4) я никогда не получаю QEvent::MOuseButtonRelease, поэтому все события comboBox фильтруются. Я думаю, что проблема в QtCore.QEvent.FocusOut из comboBox. - person Onlyjus; 09.10.2015

У меня та же проблема, и мой обходной путь - добавить два кода строки в createEditor(...).

editor->move(option.rect.x(),option.rect.y());
editor->showPopup();

Затем, дважды щелкнув элемент таблицы, QComboBox покажет всплывающие элементы, вызванные нажатием второй кнопки мыши, и скроет всплывающие элементы, вызванные отпусканием второй кнопки мыши. Это работает для Qt 4.8.

Я также попробовал Qt5.0, и приложение разбилось с этим обходным путем или без него. Я сообщил об этой проблеме как об ошибке.

person ZHAO Peng    schedule 25.01.2013
comment
Я нашел решение, взгляните на мой ответ. - person msnxcp; 12.03.2013