如何在 QStatusBar 中显示 QAbstractTableModel 的状态?
How to show QAbstractTableModel's status in a QStatusBar?
我有 QAbstractTableModel 和 QSortFilterProxyModel 的自定义实现,用于过滤。 table 显示在 QTableView 中。
我的 QTableView 的父对话框有一个 QStatusBar,带有一个只读的 QLineEdit 小部件。
在我覆盖 QAbstractTableModel 的 data() 方法中,我正在为 Qt::StatusTipRole 角色设置相关值。
现在我缺少了一部分管道:如何让每个单元格的 StatusTipRole 数据显示在 QStatusBar 内的小部件中?
无需覆盖视图小部件。 Qt 提供内置支持以显示模型中项目的状态提示。
通常情况下,您只需要从模型的 data()
when role
is QStatusTipRole
中 return 一个 QString
,当您将鼠标悬停在项目上时,QString
将显示在状态栏中.
您还需要为 QTableView
启用 mouse tracking,以便在不按下鼠标按钮的情况下获得状态栏更新。这是因为当禁用鼠标跟踪时(默认情况下),小部件仅在按下鼠标按钮时接收鼠标移动事件。
现在,为了在您的 QLineEdit
而不是默认状态栏中显示这些状态提示,您可以覆盖主 window 的 event
函数,拦截 QStatusTipEvent
s,并在 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"
我有 QAbstractTableModel 和 QSortFilterProxyModel 的自定义实现,用于过滤。 table 显示在 QTableView 中。
我的 QTableView 的父对话框有一个 QStatusBar,带有一个只读的 QLineEdit 小部件。
在我覆盖 QAbstractTableModel 的 data() 方法中,我正在为 Qt::StatusTipRole 角色设置相关值。
现在我缺少了一部分管道:如何让每个单元格的 StatusTipRole 数据显示在 QStatusBar 内的小部件中?
无需覆盖视图小部件。 Qt 提供内置支持以显示模型中项目的状态提示。
通常情况下,您只需要从模型的 data()
when role
is QStatusTipRole
中 return 一个 QString
,当您将鼠标悬停在项目上时,QString
将显示在状态栏中.
您还需要为 QTableView
启用 mouse tracking,以便在不按下鼠标按钮的情况下获得状态栏更新。这是因为当禁用鼠标跟踪时(默认情况下),小部件仅在按下鼠标按钮时接收鼠标移动事件。
现在,为了在您的 QLineEdit
而不是默认状态栏中显示这些状态提示,您可以覆盖主 window 的 event
函数,拦截 QStatusTipEvent
s,并在 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"