QListView配合Model和Delegate工作的例子

主要代码:


#ifndef STUDENT_H
#define STUDENT_H
 
#include <QString>
 
class Student
{
public:
    Student();
    void setId(int id);
    int id();
    void setName(const QString &name);
    QString name();
 
private:
    int m_id;
    QString m_name;
};
 
#endif // STUDENT_H
#include "student.h"
 
Student::Student()
{
    m_id=0;
    m_name="";
}
 
void Student::setId(int id)
{
    this->m_id=id;
}
 
int Student::id()
{
    return this->m_id;
}
 
void Student::setName(const QString &name)
{
    this->m_name=name;
}
 
QString Student::name()
{
    return this->m_name;
}
#ifndef STUDENTFRAME_H
#define STUDENTFRAME_H
 
#include <QFrame>
 
namespace Ui {
class StudentFrame;
}
 
class StudentFrame : public QFrame
{
    Q_OBJECT
 
public:
    explicit StudentFrame(QWidget *parent = 0);
    ~StudentFrame();
 
    void setName(const QString &name);
 
    void setSelected(bool selected);
 
private:
    Ui::StudentFrame *ui;
};
 
#endif // STUDENTFRAME_H
#include "studentframe.h"
#include "ui_studentframe.h"
 
StudentFrame::StudentFrame(QWidget *parent) :
    QFrame(parent),
    ui(new Ui::StudentFrame)
{
    ui->setupUi(this);
}
 
StudentFrame::~StudentFrame()
{
    delete ui;
}
 
void StudentFrame::setName(const QString &name)
{
    ui->lineName->setText(name);
}
 
void StudentFrame::setSelected(bool selected)
{
    if(selected)
    {
        this->setStyleSheet("#StudentFrame{border:2px solid red;}");
    }
    else
    {
        this->setStyleSheet("#StudentFrame{border:none;}");
    }
}

#ifndef STUDENTLISTVIEWMODEL_H
#define STUDENTLISTVIEWMODEL_H
 
#include <QAbstractListModel>
 
class Student;
 
class StudentListViewModel : public QAbstractListModel
{
    Q_OBJECT
public:
    explicit StudentListViewModel(QObject *parent = 0);
    ~StudentListViewModel();
 
    int rowCount(const QModelIndex &parent) const;
 
    int columnCount(const QModelIndex &parent) const;
 
    QVariant data(const QModelIndex &index, int role) const;
 
    void add();
 
    Student *at(int index);
 
private:
    QList<Student*> m_studentList;
 
    int m_testNumber;
 
signals:
 
public slots:
};
 
#endif // STUDENTLISTVIEWMODEL_H

 

#include "studentlistviewmodel.h"
#include "entity/student.h"
#include <QSize>
 
StudentListViewModel::StudentListViewModel(QObject *parent) : QAbstractListModel(parent)
{
    m_testNumber=10000;
}
 
StudentListViewModel::~StudentListViewModel()
{
}
 
int StudentListViewModel::rowCount(const QModelIndex &parent) const
{
    return m_studentList.size();
}
 
int StudentListViewModel::columnCount(const QModelIndex &parent) const
{
    return 1;
}
 
QVariant StudentListViewModel::data(const QModelIndex &index, int role) const
{
    Student *student=m_studentList.at(index.row());
    if(student==NULL)
    {
        return QVariant();
    }
    else
    {
        switch (role) {
        case Qt::UserRole:
            return student->id();
        case Qt::DisplayRole:
            return student->name();
        case Qt::SizeHintRole:
            return QSize(0, 100);
        default:
            return QVariant();
        }
    }
    return QVariant();
}
 
void StudentListViewModel::add()
{
    Student *student=new Student;
    student->setId(m_testNumber);
    student->setName(QString::number(m_testNumber));
    m_studentList.push_back(student);
    emit layoutChanged();
    m_testNumber++;
}
 
Student *StudentListViewModel::at(int index)
{
    return m_studentList.at(index);
}
#ifndef STUDENTITEMDELEGATE_H
#define STUDENTITEMDELEGATE_H
 
#include <QStyledItemDelegate>
 
class StudentListViewModel;
class StudentFrame;
 
class StudentItemDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    explicit StudentItemDelegate(StudentListViewModel *studentListViewModel, QObject *parent = 0);
    ~StudentItemDelegate();
 
protected:
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
 
private:
    StudentListViewModel *m_studentListViewModel;
    StudentFrame *m_studentFrame;
 
signals:
 
public slots:
};
 
#endif // STUDENTITEMDELEGATE_H

#include "studentitemdelegate.h"
#include "model/studentlistviewmodel.h"
#include "entity/student.h"
#include "widget/studentframe.h"
#include <QPainter>
 
StudentItemDelegate::StudentItemDelegate(StudentListViewModel *studentListViewModel,QObject *parent) : QStyledItemDelegate(parent)
{
    this->m_studentListViewModel=studentListViewModel;
    m_studentFrame=new StudentFrame;
}
 
StudentItemDelegate::~StudentItemDelegate()
{
    if(m_studentFrame)
    {
        m_studentFrame->deleteLater();
        m_studentFrame=NULL;
    }
}
 
void StudentItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if(index.column()==0)
    {
        Student *student=m_studentListViewModel->at(index.row());
        if(student!=NULL)
        {
            m_studentFrame->setName(student->name());
            m_studentFrame->resize(option.rect.width(), option.rect.height());
            if (option.state & QStyle::State_Selected)
            {
                m_studentFrame->setSelected(true);
            }
            else
            {
                m_studentFrame->setSelected(false);
            }
            QPixmap pixmap=m_studentFrame->grab();
            painter->drawPixmap(option.rect, pixmap);
            return;
        }
    }
    QStyledItemDelegate::paint(painter, option, index);
}
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
 
#include <QWidget>
#include "entity/student.h"
 
class StudentListViewModel;
class StudentItemDelegate;
 
namespace Ui {
class MainWidget;
}
 
class MainWidget : public QWidget
{
    Q_OBJECT
 
public:
    explicit MainWidget(QWidget *parent = 0);
    ~MainWidget();
 
 
private slots:
    void on_buttonAdd_clicked();
 
private:
    Ui::MainWidget *ui;
 
    StudentListViewModel *m_studentListViewModel;
    StudentItemDelegate *m_studentItemDelegate;
};
 
#endif // MAINWIDGET_H
#include "mainwidget.h"
#include "ui_mainwidget.h"
#include "model/studentlistviewmodel.h"
#include "delegate/studentitemdelegate.h"
 
MainWidget::MainWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MainWidget)
{
    ui->setupUi(this);
    this->setWindowTitle("List View Test");
 
    m_studentListViewModel=new StudentListViewModel(this);
    m_studentItemDelegate=new StudentItemDelegate(m_studentListViewModel, this);
    ui->listView->setModel(m_studentListViewModel);
    ui->listView->setItemDelegate(m_studentItemDelegate);
}
 
MainWidget::~MainWidget()
{
    delete ui;
}
 
 
void MainWidget::on_buttonAdd_clicked()
{
    m_studentListViewModel->add();
}

 

运行效果:

(------------完------------)

### QListView 样式设置与 Qt 自定义外观 #### 使用 QSS 设置 QListView 的基本样式 Qt 提供了强大的样式表机制(QSS),允许开发者轻松定制控件的外观。对于 `QListView` 控件,可以通过设置样式表来调整其视觉效果。例如,可以修改字体大小、背景颜色以及交替行的颜色等属性[^3]。 以下是通过 QSS 实现的一个简单示例: ```css QListView { font-size: 14px; background-color: lightgray; alternate-background-color: yellow; selection-background-color: blue; selection-color: white; } ``` 上述代码设置了 `QListView` 的字体大小为 14 像素,背景颜色为浅灰色,并启用了交替行功能,其中偶数行的背景颜色被设为黄色。选中项的背景颜色变为蓝色,文字颜色改为白色。 --- #### 定制更复杂的外观 如果需要进一步增强 `QListView` 的显示效果,则可能需要用到自定义委托 (`QStyledItemDelegate`) 来控制每一项的具体渲染方式[^1]。这种方式提供了更高的灵活性,能够满足复杂场景下的需求。 以下是一个简单的例子,展示如何创建并应用自定义委托类: ```python from PyQt5.QtWidgets import QApplication, QListView, QStyledItemDelegate, QStyleOptionViewItem, QWidget, QVBoxLayout, QLabel from PyQt5.QtCore import QModelIndex, QSize class CustomDelegate(QStyledItemDelegate): def paint(self, painter, option, index): super().paint(painter, option, index) # 添加额外的内容到 Item 中 if option.state & QStyle.State_Selected: painter.fillRect(option.rect, QColor(200, 200, 255)) # 修改选中状态下的背景色 def sizeHint(self, option, index): return QSize(100, 50) # 调整每项的高度宽度 app = QApplication([]) list_view = QListView() delegate = CustomDelegate(list_view) list_view.setItemDelegate(delegate) # 创建模型数据 model = QStringListModel(["Item 1", "Item 2", "Item 3"]) list_view.setModel(model) list_view.show() app.exec_() ``` 在这个 Python 示例中,我们继承了 `QStyledItemDelegate` 并重写了两个方法: - **`paint()`**: 可用于覆盖默认绘制逻辑,在这里实现了当项目处于选中状态下改变背景颜色的功能。 - **`sizeHint()`**: 返回推荐的尺寸提示,从而动态调整列表项的大小。 --- #### 结合 QListWidget setItemWidget 方法 除了使用 `QListView` 配合样式表或代理外,还可以考虑采用 `QListWidget` 并利用其内置函数 `setItemWidget(item, widget)` 将任意小部件嵌入到列表项中[^2]。这种方法适用于希望完全掌控单个条目布局的情况。 示例代码如下所示: ```python from PyQt5.QtWidgets import QApplication, QListWidget, QListWidgetItem, QWidget, QHBoxLayout, QLabel, QPushButton app = QApplication([]) list_widget = QListWidget() for i in range(3): custom_item = QListWidgetItem() # 创建一个新的列表项 container_widget = QWidget() # 构造容器窗口组件 layout = QHBoxLayout(container_widget) label = QLabel(f"Label {i}") button = QPushButton("Button") layout.addWidget(label) layout.addWidget(button) list_widget.addItem(custom_item) # 向列表添加空白占位符 list_widget.setItemWidget(custom_item, container_widget) # 替换实际内容 list_widget.show() app.exec_() ``` 此脚本展示了如何向每个列表单元格插入由标签按钮组成的复合界面结构。 --- #### 总结 针对不同的开发目标可以选择合适的方案来自定义 `QListView` 或其他类似视图控件的表现形式。无论是借助简洁明快的 QSS 方案还是深入挖掘基于 C++/Python API 扩展能力的方法都可以达到理想的效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值