Как показать статус QAbstractTableModel в QStatusBar?

У меня есть собственная реализация QAbstractTableModel и QSortFilterProxyModel, используемая для фильтрации. Таблица отображается в QTableView.

Родительский диалог моего QTableView имеет QStatusBar с виджетом QLineEdit только для чтения.

В моем переопределяющем методе data() QAbstractTableModel я устанавливаю соответствующие значения для роли Qt::StatusTipRole.

Теперь мне не хватает части сантехники: как мне получить данные StatusTipRole для каждой ячейки, чтобы они отображались в моем виджете внутри QStatusBar?


person jehuty    schedule 12.12.2016    source источник
comment
Предполагая, что вы хотите, чтобы QStatusBar обновлялся по щелчку мыши, вы можете подключить унаследованный сигнал QTableView clicked в функцию, которая получает текст и соответственно вызывает QStatusBar::setText()   -  person Felipe Lema    schedule 12.12.2016
comment
Идея состоит в том, чтобы обновить строку состояния в зависимости от того, над какой ячейкой находится указатель мыши. Мне удалось получить такое поведение, имея слот для сигнала mouseMoveEvent TableView, но это не удается, когда задействована фильтрация, и у меня нет доступа к данным модели в этот момент.   -  person jehuty    schedule 12.12.2016
comment
В этой теме обсуждается этот вопрос.   -  person Felipe Lema    schedule 12.12.2016


Ответы (1)


Нет необходимости переопределять виджет представления. Qt предоставляет встроенную поддержку для отображения подсказок о состоянии элементов в модели.

Обычно вам просто нужно вернуть QString из data() вашей модели, когда role — это QStatusTipRole, и этот QString будет отображаться в строка состояния при наведении курсора на элемент.

Вам также необходимо включить отслеживание мыши для QTableView так что вы получаете обновления строки состояния без нажатия кнопки мыши. Это связано с тем, что когда отслеживание мыши отключено (по умолчанию), виджет получает события перемещения мыши только при нажатии кнопки мыши.

Теперь, чтобы отображать эти подсказки в вашем QLineEdit вместо строки состояния по умолчанию, вы можете переопределить event, перехватывать QStatusTipEvent и показывать подсказки в QLineEdit.

Вот пример реализации:

скриншот

#include <QtWidgets>

//model to provide dummy data
class MyModel : public QAbstractTableModel{
public:
    explicit MyModel(QObject* parent= nullptr):QAbstractTableModel(parent){}
    ~MyModel() = default;
    int columnCount(const QModelIndex &parent) const{
        if(parent.isValid()) return 0;
        return 4;
    }
    int rowCount(const QModelIndex &parent) const{
        if(parent.isValid()) return 0;
        return 20;
    }
    QVariant data(const QModelIndex &index, int role) const{
        QVariant val;
        switch(role){
        case Qt::DisplayRole: case Qt::EditRole:
            val= QString("Display (%1, %2)")
                    .arg(index.row(), 2, 10, QChar('0'))
                    .arg(index.column(), 2, 10, QChar('0'));
            break;
        case Qt::ToolTipRole:
            val= QString("Tooltip (%1, %2)")
                    .arg(index.row(), 2, 10, QChar('0'))
                    .arg(index.column(), 2, 10, QChar('0'));
            break;
        case Qt::StatusTipRole:
            val= QString("StatusTip (%1, %2)")
                    .arg(index.row(), 2, 10, QChar('0'))
                    .arg(index.column(), 2, 10, QChar('0'));
            break;

        }
        return val;
    }
};


class MainWindow : public QMainWindow{
    Q_OBJECT
public:
    explicit MainWindow(QWidget* parent= nullptr):QMainWindow(parent){
        //set up GUI
        layout.addWidget(&lineEditFilter);
        layout.addWidget(&tableView);
        setCentralWidget(&cw);
        lineEditStatusBar.setReadOnly(true);
        statusBar()->addPermanentWidget(&lineEditStatusBar);

        //set up models
        filterModel.setSourceModel(&model);
        tableView.setModel(&filterModel);
        connect(&lineEditFilter, &QLineEdit::textChanged, this, &MainWindow::updateFilter);

        //turn on mouse tracking for the table view
        tableView.setMouseTracking(true);

    }
    ~MainWindow()= default;

    Q_SLOT void updateFilter(const QString& text){
        filterModel.setFilterFixedString(text);
    }
protected:

    //in order to intercept QStatusTipEvents
    //and show tips in the line edit instead of the normal status bar
    bool event(QEvent *event){
        if(event->type() != QEvent::StatusTip) return QMainWindow::event(event);
        QStatusTipEvent* statusTipEvent= static_cast<QStatusTipEvent*>(event);
        lineEditStatusBar.setText(statusTipEvent->tip());
        statusTipEvent->ignore();
        return true;
    }

private:
    QWidget cw;
    QVBoxLayout layout{&cw};
    QLineEdit lineEditFilter;
    QTableView tableView;
    MyModel model;
    QSortFilterProxyModel filterModel;
    QLineEdit lineEditStatusBar;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    MainWindow mw;
    mw.show();


    return a.exec();
}

#include "main.moc"
person Mike    schedule 12.12.2016