自定义QTableVew处理鼠标按下事件

时间:2019-02-22 23:08:41

标签: c++ qt qtableview qitemdelegate

一段时间以来,我一直在尝试实现自己的QTableView类版本。我希望表格的行在选择特定行之前对鼠标按下事件具有不同的颜色作出反应。就像按住鼠标左键一样。

我可能可以通过在设置了表格视图组件的小部件中连接某些信号和插槽来实现这一点,但我希望将该功能密封在一个类中,该类可以在很多地方重用而无需重复相同的代码。

有一件事,我正在编写的代码是在Qt 4.8中使用小部件的,因此QML不是一个选择。

我试图通过设置样式来实现 QTableView::item:pressed,但按下状态似乎仅适用于QPushButton类型的对象。

第二种方法是添加一个委托,该委托可以在paint方法中执行此任务。但是,QStyle不具有pressed状态。我唯一看到的是QStyle::State_Selected,不是。另外,我尝试使用QStyle::State_Down,但它也不起作用。

我的第三种方法是editorEvent实现。

在这里,我能够捕捉到我感兴趣的事件,即MouseButtonPress和MouseMove,但是我不知道如何绘制仅由索引指示的单元格。

你能建议点什么吗? 预先感谢您的帮助。

Jakub。

这是我用于测试的代码(摘自:https://riptutorial.com/qt/example/13705/a-simple-read-only-table-to-view-data-from-a-model

  • mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QAbstractTableModel>

namespace Ui {
class MainWindow;
}

class TestModel : public QAbstractTableModel
{
    Q_OBJECT

public:
    TestModel(QObject *parent = 0);

    void populateData(const QList<QString> &contactName,const QList<QString> &contactPhone);

    int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
    int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;

private:
    QList<QString> tm_contact_name;
    QList<QString> tm_contact_phone;

};

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

};

#endif // MAINWINDOW_H

  • mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QList<QString> contactNames;
    QList<QString> contactPhoneNums;

    // Create some data that is tabular in nature:
    contactNames.append("Thomas");
    contactNames.append("Richard");
    contactNames.append("Harrison");
    contactPhoneNums.append("123-456-7890");
    contactPhoneNums.append("222-333-4444");
    contactPhoneNums.append("333-444-5555");

    // Create model:
    TestModel *PhoneBookModel = new TestModel(this);

    // Populate model with data:
    PhoneBookModel->populateData(contactNames,contactPhoneNums);

    // Connect model to table view:
    ui->tableView->setModel(PhoneBookModel);

    ui->tableView->show();
}

MainWindow::~MainWindow()
{
    delete ui;
}

TestModel::TestModel(QObject *parent) : QAbstractTableModel(parent)
{
}

// Create a method to populate the model with data:
void TestModel::populateData(const QList<QString> &contactName,const QList<QString> &contactPhone)
{
    tm_contact_name.clear();
    tm_contact_name = contactName;
    tm_contact_phone.clear();
    tm_contact_phone = contactPhone;
    return;
}

int TestModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return tm_contact_name.length();
}

int TestModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return 2;
}

QVariant TestModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid() || role != Qt::DisplayRole) {
        return QVariant();
    }
    if (index.column() == 0) {
        return tm_contact_name[index.row()];
    } else if (index.column() == 1) {
        return tm_contact_phone[index.row()];
    }
    return QVariant();
}

QVariant TestModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
        if (section == 0) {
            return QString("Name");
        } else if (section == 1) {
            return QString("Phone");
        }
    }
    return QVariant();
}
  • ctableview.h
#ifndef CTABLEVIEW_H
#define CTABLEVIEW_H
#include <QTableView>

class CTableView : public QTableView
{
public:
    explicit CTableView(QWidget* parent = nullptr);
};

#endif // CTABLEVIEW_H
  • ctableview.cpp
#include "ctableview.h"
#include "ctableitemdelegate.h"
#include <QHeaderView>

CTableView::CTableView(QWidget* parent) : QTableView (parent)
{
    horizontalHeader()->setVisible(true);
    setSelectionBehavior(QAbstractItemView::SelectRows);
    setSelectionMode(QAbstractItemView::SingleSelection);
    setItemDelegate(new CTableItemDelegate(this));

}
  • ctableitemdelegate.h
#ifndef CTABLEITEMDELEGATE_H
#define CTABLEITEMDELEGATE_H
#include <QItemDelegate>

class CTableItemDelegate : public QItemDelegate
{
public:
    explicit CTableItemDelegate(QWidget* parent = nullptr);

    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
    bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override;
};

#endif // CTABLEITEMDELEGATE_H
  • ctableitemdelegate.cpp
#include "ctableitemdelegate.h"
#include <QPainter>
#include <QEvent>
#include <QMouseEvent>

#include <iostream>
CTableItemDelegate::CTableItemDelegate(QWidget* parent) : QItemDelegate (parent)
{   
}

void CTableItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if((option.state & QStyle::State_Selected) && (option.state & QStyle::State_HasFocus))
    {
        painter->save();
        painter->fillRect(option.rect, QBrush(Qt::red));
        painter->drawText(option.rect, index.model()->data(index, Qt::DisplayRole).toString());
        painter->restore();
    } else {
        QItemDelegate::paint(painter, option, index);
    }
}

bool CTableItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
    Qt::ItemFlags flags = model->flags(index);
    if (!(flags & Qt::ItemIsUserCheckable) || !(option.state & QStyle::State_Enabled) || !(flags & Qt::ItemIsEnabled))
    {
        if ((event->type() == QEvent::MouseButtonPress) || (event->type() == QEvent::MouseMove) )
        {
            std::cerr << "Mouse press at row [" << index.row() << "\n";
            //return true;
        }
    }
    return false;
}

0 个答案:

没有答案
相关问题