Пользовательский QTableVIew, обрабатывающий событие нажатия мыши

Я пытался реализовать свою собственную версию QTableView класс в течение некоторого времени Я хотел бы, чтобы строка таблицы реагировала на событие нажатия мыши другим цветом непосредственно перед тем, как будет выбран определенный ряд. Точно так же, как кнопка, когда вы удерживаете на ней левую кнопку мыши.

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

Во-первых, код, который я пишу, находится в Qt 4.8 с использованием виджетов, поэтому QML не вариант.

Я попытался сделать это, установив стильQTableView::item:pressed но нажатое состояние кажется подходящим только для объектов типа QPushButton.

Второй подход состоял в том, чтобы добавить делегата, который в paint Метод будет выполнять эту задачу. Тем не мение, QStyle не имеет pressed статус. Единственное, что я видел, это QStyle::State_Selected но это не так. Кроме того, я пытался с QStyle::State_Down но это тоже не работает.

Мой третий подход был editorEvent реализация.

Здесь я могу захватить интересующее меня событие, то есть MouseButtonPress и MouseMove, но я не знаю, как нарисовать ячейку, которая только что указана индексом.

Не могли бы вы посоветовать что-нибудь? Спасибо заранее за вашу помощь.

Якуб.

Вот код, который я использовал для тестов (взят из: 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 ответов

Другие вопросы по тегам