Qt实现复杂列表

发布时间:2024年01月12日

界面效果

在这里插入图片描述

layeritemdelegate.h

#ifndef LAYERITEMDELEGATE_H
#define LAYERITEMDELEGATE_H

#include <QStyledItemDelegate>
#include <QLineEdit>
#include <QDebug>
#include <QPainter>

class LayerItemDelegate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    LayerItemDelegate(QObject *parent=0);
    ~LayerItemDelegate();


    void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const;
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
        const QModelIndex &index) const;
    bool editorEvent(QEvent * event,
        QAbstractItemModel * model,
        const QStyleOptionViewItem & option,
        const QModelIndex & index);
    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model,
        const QModelIndex &index) const;
    void updateEditorGeometry(QWidget *editor,
        const QStyleOptionViewItem &option, const QModelIndex &index) const;

private:
    QPixmap m_gridPixmap;
};

#endif // LAYERITEMDELEGATE_H

layeritemdelegate.cpp

#include "layeritemdelegate.h"

LayerItemDelegate::LayerItemDelegate(QObject *parent)
    : QStyledItemDelegate(parent)
{
    QImage gridImage(200, 200, QImage::Format_RGB32);
    QRgb grey = QColor(204, 204, 204).rgb();
    QRgb white = QColor(255, 255, 255).rgb();
    for (int i = 0; i < 200; i++)
    for (int j = 0; j < 200; j++)
    {
        int tmpX = i % 10;
        int tmpY = j % 10;
        if (tmpX < 5)
        {
            gridImage.setPixel(i, j, tmpY < 5 ? grey : white);
        }
        else
        {
            gridImage.setPixel(i, j, tmpY < 5 ? white : grey);
        }
    }

    m_gridPixmap = QPixmap::fromImage(gridImage);
}

LayerItemDelegate::~LayerItemDelegate()
{

}



void LayerItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
{


    if (index.column() == 1) // value column
    {
        if (option.state & QStyle::State_Selected)
            painter->fillRect(option.rect, option.palette.highlight());

        QImage image = qvariant_cast<QImage>(index.data(Qt::DecorationRole));
        //QImage image = index.model()->data(index, Qt::DecorationRole).toString();
        QRect rect = option.rect;
        int x = rect.x() + 10;
        int y = rect.y() + 5;

        QBrush brush;
        //Draw grid background
        brush.setTexture(m_gridPixmap);
        painter->fillRect(x, y, 40, 40, brush);

        //Draw image
        painter->drawImage(x, y, image);

        QRect textRect(rect.x() + 60, rect.y(), rect.width() - 60, rect.height());

        QString layerName = index.model()->data(index, Qt::DisplayRole).toString();
        QTextOption textOption = Qt::AlignLeft | Qt::AlignVCenter;
        painter->drawText(textRect, layerName, textOption);

    }
    else
    {
        QStyledItemDelegate::paint(painter, option, index);
    }
}


bool LayerItemDelegate::editorEvent(QEvent * event,
    QAbstractItemModel * model,
    const QStyleOptionViewItem & option,
    const QModelIndex & index)
{
    return false;
}

QWidget *LayerItemDelegate::createEditor(QWidget *parent,
    const QStyleOptionViewItem &option,
    const QModelIndex &index) const
{
    qDebug() << "createEditor";
    if (index.column() == 1) // value column
    {
        QLineEdit* edit = new QLineEdit(parent);
        edit->setFixedHeight(33);
        edit->setContentsMargins(48, 15, 50, 0);
        return edit;
    }
    else return 0;  // no editor attached
}

void LayerItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    QString value = index.model()->data(index, Qt::EditRole).toString();

    QLineEdit *edit = static_cast<QLineEdit*>(editor);
    edit->setText(value);
    qDebug() << "setEditorData";
}

void LayerItemDelegate::updateEditorGeometry(QWidget *editor,
    const QStyleOptionViewItem &option, const QModelIndex & index ) const
{
    editor->setGeometry(option.rect);
}

void LayerItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
    const QModelIndex &index) const
{
    qDebug() << "setModelData";
    QLineEdit *edit = static_cast<QLineEdit*>(editor);
    model->setData(index, edit->text(), Qt::EditRole);
}

layertablemodel.h

#ifndef LAYERLISTMODEL_H
#define LAYERLISTMODEL_H

#include <QAbstractTableModel>
#include <QStringList>
#include <QList>
#include <QPixmap>
#include <QImage>
#include <QIcon>
#include <QDebug>
#include <QItemSelectionModel>

class LayerTableModel : public QAbstractTableModel
{
    Q_OBJECT

public:
    LayerTableModel(QObject *parent = 0);
    ~LayerTableModel();

    int rowCount(const QModelIndex &parent) const;
    int columnCount(const QModelIndex &parent) const;
    QVariant data(const QModelIndex &index, int role) const;
    QVariant headerData(int section,
        Qt::Orientation orientation,
        int role = Qt::DisplayRole) const;
    Qt::ItemFlags flags(const QModelIndex &index) const;

    bool setData(const QModelIndex &index, const QVariant &value, int role);
    void deleteItem(int index);
    void addItem(const QString &layerName,const QImage &thumbnail, bool isShow = true);
    void refreshModel();
//    QModelIndex& selecttedIndex(int row);
    QModelIndex selecttedIndex(int row);
//    QPersistentModelIndex& selecttedIndex(int row);

    void setSelecttedRow(int row);
    int getSelecttedRow() const;


public slots:
    void changeLayerVisibility(const QModelIndex&);

private:
    struct LayerItem
    {
        QString layerName;
        QImage thumbnail;
        float transparence;
        bool isShow;
    };
    QList<LayerItem> layerList;

    int selectedRow;

};

#endif // LAYERLISTMODEL_H

layertablemodel.cpp

#include "layertablemodel.h"
#include"QString"

LayerTableModel::LayerTableModel(QObject *parent)
: QAbstractTableModel(parent)
{
    QImage image("images\\sample.jpg");
    layerList.reserve(3);
    selectedRow = 0;
    for (int i = 0; i < 1; i++)
    {
        addItem(QString(),image,true);
    }
}

LayerTableModel::~LayerTableModel()
{

}

QVariant LayerTableModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    int column = index.column();
    if (column == 0)
    {
        if(role ==  Qt::CheckStateRole)
        {
            return layerList.at(index.row()).isShow ? Qt::Checked : Qt::Unchecked;
        }
        if (role == Qt::SizeHintRole)
        {
            return QSize(20, 50);
        }
    }
    else
    {
        if (role == Qt::EditRole)
        {
            return QVariant(layerList.at(index.row()).layerName);
        }
        if (role == Qt::DisplayRole)
        {
            return QVariant(layerList.at(index.row()).layerName);
        }

        if (role == Qt::DecorationRole)
        {
            if (layerList.at(index.row()).thumbnail.isNull())
            {
                return  layerList.at(index.row()).thumbnail;
            }else
            {
                return  layerList.at(index.row()).thumbnail.scaledToHeight(40);

            }
        }
        if (role == Qt::SizeHintRole)
        {
            return QSize(200, 50);
        }
        if (role == Qt::TextAlignmentRole)
        {
            return int(Qt::AlignVCenter);
        }
    }

    return QVariant();
}

int LayerTableModel::rowCount(const QModelIndex &parent) const
{
    return (parent.isValid() && parent.column() != 0) ? 0 : layerList.size();
}

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

QVariant LayerTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role == Qt::DisplayRole)
        return QString::number(section);
    //if (role == Qt::DecorationRole)
        //return QVariant::fromValue(services);
    return QAbstractItemModel::headerData(section, orientation, role);
}

Qt::ItemFlags LayerTableModel::flags(const QModelIndex &index) const
{

    if (!index.isValid())
        return 0;

    if (index.column() == 0)
        return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;

    return  Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
}

bool LayerTableModel::setData(const QModelIndex &index, const
    QVariant &value, int role)
{
    if (!index.isValid())
    {
        return false;
    }

    if (role == Qt::CheckStateRole && value.type() == QVariant::Bool)
    {
        layerList[index.row()].isShow = value.toBool();
        emit(dataChanged(index, index));
        return true;
    }
    if (role == Qt::EditRole && index.column() == 1)
    {
        layerList[index.row()].layerName = value.toString();
        emit(dataChanged(index, index));
        return true;
    }
    return false;;
}

void LayerTableModel::changeLayerVisibility(const QModelIndex& index)
{
    if (index.isValid()&&index.column() == 0)
    {
        setData(index, !(layerList.at(index.row()).isShow), Qt::CheckStateRole);
    }
}

void LayerTableModel::deleteItem(int index)
{
    QList<LayerItem>::iterator it = layerList.begin();
    layerList.erase(it + index);
}

void LayerTableModel::addItem(const QString &name,const QImage &thumb, bool show)
{
    LayerItem item;
    if (name.size() == 0)
    {
        item.layerName = QString("Layer ") + QString::number(layerList.size());
    }else{
        item.layerName = name;
    }
    item.isShow = show;

    item.thumbnail = thumb;
    layerList.append(item);
    //this->insertRow()
    //emit(dataChanged(index, index));
    qDebug()<<layerList.size();
}

void LayerTableModel::refreshModel()
{
    beginResetModel();
    endResetModel();
    //emit updateCount(this->rowCount(QModelIndex()));
}

//QModelIndex& LayerTableModel::selecttedIndex(int row)
//{
//    return this->createIndex(row, 1);
//}

QModelIndex LayerTableModel::selecttedIndex(int row)
{
    return this->createIndex(row, 1);
}

//QPersistentModelIndex& LayerTableModel::selecttedIndex(int row)
//{
//    static QPersistentModelIndex invalidIndex;  // 返回一个无效的引用,因为不能返回临时对象的引用
//    return this->createIndex(row, 1);
//}




void LayerTableModel::setSelecttedRow(int row)
{
    selectedRow = row;
}

int LayerTableModel::getSelecttedRow() const
{
    return selectedRow;
}

layertableview.h

#ifndef LAYERLISTVIEW_H
#define LAYERLISTVIEW_H

#include <QTableView>
#include <QMouseEvent>
#include <QDebug>
#include <QHeaderView>
#include <QStandardItemModel>
#include <QContextMenuEvent>
#include <QMenu>
#include "layertablemodel.h"
#include "layeritemdelegate.h"

class LayerTableView : public QTableView
{
    Q_OBJECT

public:
    LayerTableView(QWidget *parent = 0);
    ~LayerTableView();
    void setLayerSize(QSize s);

public slots:
    void addNewLayer();
    void deleteLayer();

protected:
    void mouseMoveEvent(QMouseEvent * event);
    void contextMenuEvent(QContextMenuEvent * event);

private:
    LayerItemDelegate *delegate;
    LayerTableModel *model;
    QSize layerSize;

private slots:
    void itemClicked(const QModelIndex&);

};

#endif // LAYERLISTVIEW_H

layertableview.cpp

#include "layertableview.h"
#include <QMessageBox>
LayerTableView::LayerTableView(QWidget *parent)
    : QTableView(parent)
{
    delegate = new LayerItemDelegate();
    model = new LayerTableModel();

    this->setContentsMargins(0, 0, 0, 0);
    this->setModel(model);
    this->setItemDelegate(delegate);

    this->horizontalHeader()->setStretchLastSection(true);
    this->horizontalHeader()->setHighlightSections(false);
    this->setFrameShape(QFrame::NoFrame);
    this->setColumnWidth(0, 30);
    this->setColumnWidth(1, 170);
    this->verticalHeader()->setVisible(false);
    this->horizontalHeader()->setVisible(false);
    this->resizeColumnsToContents();
    this->resizeRowsToContents();
    /*this->setEditTriggers(QAbstractItemView::NoEditTriggers);
    this->setSelectionBehavior(QAbstractItemView::SelectRows);*/
    this->setMouseTracking(true);//important

    //When click on the checkbox it will emit signal twice.Click on the cell emit only once.
    connect(this, SIGNAL(clicked(const QModelIndex&)), this, SLOT(itemClicked(const QModelIndex&)));
}

LayerTableView::~LayerTableView()
{

}

void LayerTableView::mouseMoveEvent(QMouseEvent * event)
{
    Q_UNUSED(event);
}

void LayerTableView::contextMenuEvent(QContextMenuEvent * event)
{

    QMenu *pMenu = new QMenu(this);
    QAction *pAddGroupAct = new QAction(tr("Delete"), pMenu);
    pMenu->addAction(pAddGroupAct);
    pMenu->popup(mapToGlobal(event->pos()));

}

void LayerTableView::addNewLayer()
{
    model->addItem(QString(), QImage(layerSize, QImage::Format_RGB32), true);
    //model->addItem(QString(), QImage("images\\sample.jpg"), true);
    model->refreshModel();
    this->resizeRowsToContents();
}

void LayerTableView::itemClicked(const QModelIndex& index)
{
    if (index.isValid() )
    {
        //When click in column 0.
        if (index.column() == 0)
        {
            // 弹出一条信息框
//            QMessageBox::information(this, "提示", "这是一条消息"); //加this可以有图标
            model->changeLayerVisibility(index);
            QModelIndex tmp = model->selecttedIndex(model->getSelecttedRow());
            this->selectionModel()->select(tmp, QItemSelectionModel::Select);
        }
        //When click in column 1.
        else if (index.column() == 1)
        {
            model->setSelecttedRow(index.row());
        }
    }
}

void LayerTableView::deleteLayer()
{
    model->deleteItem(model->getSelecttedRow());
    model->refreshModel();

    QModelIndex tmp = model->selecttedIndex(0);
    this->selectionModel()->select(tmp, QItemSelectionModel::Select);
}

void LayerTableView::setLayerSize(QSize s)
{
    layerSize = s;
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include"layertableview.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    LayerTableView *myLayerTableView;
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include"QHBoxLayout"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // 创建 LayerTableView
    myLayerTableView = new LayerTableView();

    // 创建一个水平布局
    QHBoxLayout *layout = new QHBoxLayout;

    // 将 LayerTableView 添加到布局中
    layout->addWidget(myLayerTableView);

    // 创建一个中央部件并设置布局
    QWidget *centralWidget = new QWidget;
    centralWidget->setLayout(layout);

    // 设置中央部件
    setCentralWidget(centralWidget);
}

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


文章来源:https://blog.csdn.net/weixin_42797483/article/details/135543787
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。