2016-12-12 8 views
1

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

В родительском диалоге моего QTableView есть QStatusBar с виджетами QLineEdit, доступными только для чтения.

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

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

+0

Предполагая, что вы хотите QStatusBar обновить на мыши, вы можете подключить унаследованный сигнал QTableView в [ 'clicked'] (Http: // док. qt.io/qt-4.8/qabstractitemview.html#clicked) к функции, которая получает текст и вызывает QStatusBar :: setText() соответственно –

+0

Идея состоит в том, чтобы обновить строку состояния на основе той ячейки, на которой курсирует мышь. Мне удалось получить это поведение, имея слот для сигнала mouseMoveEvent TableView, но это не удается при фильтрации, и у меня нет доступа к данным модели в этой точке. – jehuty

+0

[Эта тема] (http://www.qtcentre.org/threads/50677-Problem-with-QTableView-and-QSortFilterProxyModel) имеет обсуждение по этому вопросу. –

ответ

3

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

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

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

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

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

screenshot

#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" 
+0

Спасибо за подробный пример - это именно то, что я искал. После игры с вашим примером кода я понял, что мой основной диалог - QDialog, а не QMainWindow. Я не могу изменить это, поэтому я слушаю события мыши и вызываю model-> data() вручную, что является неудачным. – jehuty

+0

@jehuty, Вы все равно можете использовать тот же подход с подклассом 'QDialog'. Если я правильно понял вашу проблему, [здесь] (http://pastebin.com/Dd55dzsB) - это тот же пример после изменения 'MainWindow', чтобы стать подклассом' QDialog'. – Mike

+0

«Вам также нужно включить отслеживание мыши ...». Спасибо! – nicolai