Пользовательский QTableVIew, обрабатывающий событие нажатия мыши - PullRequest
0 голосов
/ 23 февраля 2019

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

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

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

Iпопытался сделать это, установив стиль 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;
}

...