QTableView之二:常用用法

效果图

xumsqf.png


代码下载

GitHub 下载地址:https://github.com/confidentFeng/QtAppProject

添加项

void addItem(QString name); // 添加项

// 添加项
void Widget::addItem(QString name)
{
    // 准备数据模型
    QList<QStandardItem *> listItems;

    // 名称(包括勾选框)
    QStandardItem *pItemName = new QStandardItem(name);
    pItemName->setCheckable(true);
    pItemName->setCheckState(Qt::Unchecked);
    // 年龄
    QStandardItem *pItemAge = new QStandardItem("25");
    // 图标
    QStandardItem *pItemIcon = new QStandardItem(QIcon(":/Image/icon_camera_checked.png"), "");

    // 添加到数据模型
    listItems << pItemName << pItemAge << pItemIcon;
    m_pMyTableView->getModel()->appendRow(listItems); // 加载一行数据

    // 设置各列的宽度
    if(m_pMyTableView->getModel()->rowCount() > ITEM_MAX_COUNT)
        m_pMyTableView->setColumnWidth(0, 200-8);
    else
        m_pMyTableView->setColumnWidth(0, 200);
    m_pMyTableView->setColumnWidth(1, 60);
    m_pMyTableView->setColumnWidth(2, 60);
}

实时获取选中的复选框数目

// 复选框改变也会触发itemChanged信号
connect(m_pMyTableView->getModel(), &QStandardItemModel::itemChanged, [=](QStandardItem *item) {
    // 实时获取选中的复选框数目
    int checkedCount = 0;
    for(int i=0; i < m_pMyTableView->getModel()->rowCount(); i++)
        if(m_pMyTableView->getModel()->item(i, 0)->isEnabled() &&
           Qt::Checked == m_pMyTableView->getModel()->index(i, 0).data(Qt::CheckStateRole))
            checkedCount++;
    //qDebug() << "QStandardItemModel::itemChanged: " << checkedCount;

    // 复选框选中时,同时选中当前行
    m_pMyTableView->selectRow(item->index().row());
});

获取多选的item

void getMultiCheckItem(); // 获取多选的item

// 获取多选的item
void MainWidget::getMultiCheckItem()
{
    QStandardItemModel *standardModel = new QStandardItemModel(this);
    QItemSelectionModel  *selectModel = new QItemSelectionModel(standardModel);

    // 第一种方法: 通过 QItemSelectionModel
    if(!selectModel->hasSelection())
        return;
    QModelIndexList  modelList1 = selectModel->selectedIndexes();

   // 第二种方法:  通过tableView
    QModelIndexList modelList2 = m_pMyTableView->selectionModel()->selectedIndexes();
    foreach(QModelIndex index, modelList1)
    {
       QStandardItem *item = standardModel->itemFromIndex(index);
       QFont font = item->font();
       font.setBold(!font.bold());
       item->setFont(font);
    }
}

获取viewPort当前显示的可见的第一行和最后一行

int getViewFirstNumber(); // 获取viewPort当前显示的可见的第一行
int getViewLastNumber(); // 获取viewPort当前显示的可见的最后一行

// 获取viewPort当前显示的可见的第一行
int MainWidget::getViewFirstNumber()
{
    return m_pMyTableView->verticalScrollBar()->value();
}

// 获取viewPort当前显示的可见的最后一行
int MainWidget::getViewLastNumber()
{
    return m_pMyTableView->verticalScrollBar()->value() + m_pMyTableView->verticalScrollBar()->pageStep();
}

支持右键菜单

QAction *m_actionAdd;
QAction *m_actionDel;
QMenu *m_popMenu; // 右键菜单

// 创建多个动作
m_actionAdd = new QAction;
m_actionDel = new QAction;
m_actionAdd->setText(tr("添加数据"));
m_actionDel->setText(tr("删除数据"));
// 创建右键菜单
m_popMenu = new QMenu(m_pMyTableView);
m_popMenu->addAction(m_actionAdd);
m_popMenu->addAction(m_actionDel);
// QAction绑定槽函数,当点击QAction时触发
connect(m_actionAdd, &QAction::triggered, [=] {
    addItem("王五");
});
connect(m_actionDel, &QAction::triggered, [=] {
    m_pMyTableView->getModel()->removeRow(m_pMyTableView->currentIndex().row());
});
// m_pMyTableView设置可弹出右键菜单
m_pMyTableView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_pMyTableView, &QTableView::customContextMenuRequested, [=] {
    // 检测是否有选中项 && 选中项是否有效
    if (m_pMyTableView->selectionModel()->hasSelection() && m_pMyTableView->currentIndex().isValid())
        m_popMenu->exec(QCursor::pos());
});

实现双击item功能

QTimer *m_pTimerMouseOut; // 鼠标双击超时检测定时器
int m_nCntDouble = 0; // 按键计数
QString m_userClicked = ""; // 第一次点击对应的用户

// 鼠标双击超时检测定时器
m_pTimerMouseOut = new QTimer(this);
m_pTimerMouseOut->setSingleShot(true);
connect(m_pTimerMouseOut, &QTimer::timeout, [=]{
    m_nCntDouble = 0;
    m_pTimerMouseOut->stop();
    m_userClicked = "";
});

// 双击
connect(m_pMyTableView, &QTableView::clicked, [=](const QModelIndex &index){
    //qDebug() << "clicked: " << index.row() << m_pMyTableView->getModel()->item(m_pMyTableView->getModel()->index(index.row(), 0))->statusTip();

    QString curText = m_pMyTableView->getModel()->item(index.row(), 0)->text();

    if(m_userClicked != curText)
        m_pTimerMouseOut->start(400);
    m_nCntDouble++;
    if(m_nCntDouble >= 2) {
        m_nCntDouble = 0;
        m_pTimerMouseOut->stop();

        // 如果item已被禁用,则返回
        if(!m_pMyTableView->getModel()->item(index.row(), 0)->isEnabled())
            return;

        // 如果两次点击的用户名都相同
        if(m_userClicked == curText) {
            qDebug() << "double clicked Success";
            // 进行双击操作
        }

        m_userClicked = "";
        return;
    }

    m_userClicked = curText;
});

支持上下方向、Home、End、翻页键功能

int m_curScrollPos = 0; // 翻页时的当时滑动条位置
int m_pageHeight = 39*10; // 一页的高度(39为一行的高度,10为一页的行数)

// 键盘按下事件
void Widget::keyPressEvent(QKeyEvent *event)
{
    // 自定义实现QTableView的上下方向键功能
    if(event->key() == Qt::Key_Up) {
        int curRow = m_pMyTableView->currentIndex().row();
        curRow--;
        if(curRow < 0)
            curRow = m_pMyTableView->model()->rowCount()-1;
        QModelIndex nextIndex = m_pMyTableView->model()->index(curRow, 0);
        m_pMyTableView->setCurrentIndex(nextIndex);

        return;
    }
    if(event->key() == Qt::Key_Down) {
        int curRow = m_pMyTableView->currentIndex().row();
        curRow++;
        if(curRow > m_pMyTableView->model()->rowCount()-1)
            curRow = 0;
        QModelIndex nextIndex = m_pMyTableView->model()->index(curRow, 0);
        m_pMyTableView->setCurrentIndex(nextIndex);

        return;
    }
    if(event->key() == Qt::Key_Home) { // Home键跳转到第一行
        QModelIndex nextIndex = m_pMyTableView->model()->index(0, 0);
        m_pMyTableView->setCurrentIndex(nextIndex);

        return;
    }
    if(event->key() == Qt::Key_End) { // End键跳转到最后一行
        QModelIndex nextIndex = m_pMyTableView->model()->index(m_pMyTableView->model()->rowCount()-1, 0);
        m_pMyTableView->setCurrentIndex(nextIndex);

        return;
    }
    if(event->key() == Qt::Key_PageUp) { // PageUp键向上翻页
        m_curScrollPos = m_pMyTableView->verticalScrollBar()->value();
        if(m_curScrollPos > 0)
            m_pMyTableView->verticalScrollBar()->setSliderPosition(m_curScrollPos - m_pageHeight);
        return;
    }
    if(event->key() == Qt::Key_PageDown) { // PageUp键向下翻页
        int maxValue = m_pMyTableView->verticalScrollBar()->maximum(); // 当前scroller最大显示值
        m_curScrollPos = m_pMyTableView->verticalScrollBar()->value(); // 获得当前scroller值
        if(m_curScrollPos < maxValue)
            m_pMyTableView->verticalScrollBar()->setSliderPosition(m_pageHeight + m_curScrollPos);
        return;
    }
    else
        event->ignore(); // 不加上这句,其它键盘事件会失效
}

设置单元格内边距

// 子类化QProxyStyle,重写pixelMetric函数,已实现内边距(qss设置内边距不生效)
class TableItemSpaceStyleName : public QProxyStyle
{
public:
    explicit TableItemSpaceStyleName(QWidget *parent = nullptr) { Q_UNUSED(parent); };
    int pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
    {
        switch (metric) {
            case PM_FocusFrameHMargin:
            return 6; // 设置内边距为6
            default:
            break;
        }
        return QProxyStyle::pixelMetric(metric, option, widget);
    }
};

m_pMyTableView->setStyle(new TableItemSpaceStyleName); // 设置单元格内边距

posted @ 2022-09-30 11:44  fengMisaka  阅读(1054)  评论(0编辑  收藏  举报