首页 > 解决方案 > 是否可以将自定义小部件添加到 QListView 中?

问题描述

我有一个大的日志数据(100、1000、100000,...记录),我想以下列方式对其进行可视化:

在此处输入图像描述 在此处输入图像描述 在此处输入图像描述

为了避免性能和内存问题,我应该使用哪个小部件(例如QListView, )以及如何使用?QListWidget

标签: c++qtqlistview

解决方案


是否可以将自定义小部件添加到 QListView 中?

请阅读:

如何在 Qt C++ 应用程序中显示具有大量小部件的可滚动列表作为项目?


我想以上述格式显示每条日志消息

解决方案

为了达到预期的结果并远离性能问题,即使数据日志很长,也可以使用QListView带有自定义委托的 a:

  1. 创建一个子类QStyledItemDelegate,比如说Delegate

  2. 重新实现QStyledItemDelegate::paint自定义绘图的方法

  3. 重新实现QStyledItemDelegate::sizeHint以报告列表中项目的正确大小

  4. 通过调用在视图中使用自定义委托QAbstractItemView::setItemDelegate

例子

我为您准备了一个工作示例,以演示如何在应用程序中实施和使用建议的解决方案。

该示例的基本部分是委托在列表视图中绘制项目的方式:

void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
                     const QModelIndex &index) const
{
    QStyleOptionViewItem opt(option);
    initStyleOption(&opt, index);

    const QPalette &palette(opt.palette);
    const QRect &rect(opt.rect);
    const QRect &contentRect(rect.adjusted(m_ptr->margins.left(),
                                               m_ptr->margins.top(),
                                               -m_ptr->margins.right(),
                                               -m_ptr->margins.bottom()));
    const bool lastIndex = (index.model()->rowCount() - 1) == index.row();
    const bool hasIcon = !opt.icon.isNull();
    const int bottomEdge = rect.bottom();
    QFont f(opt.font);

    f.setPointSize(m_ptr->timestampFontPointSize(opt.font));

    painter->save();
    painter->setClipping(true);
    painter->setClipRect(rect);
    painter->setFont(opt.font);

    // Draw background
    painter->fillRect(rect, opt.state & QStyle::State_Selected ?
                          palette.highlight().color() :
                          palette.light().color());

    // Draw bottom line
    painter->setPen(lastIndex ? palette.dark().color()
                              : palette.mid().color());
    painter->drawLine(lastIndex ? rect.left() : m_ptr->margins.left(),
                      bottomEdge, rect.right(), bottomEdge);

    // Draw message icon
    if (hasIcon)
        painter->drawPixmap(contentRect.left(), contentRect.top(),
                            opt.icon.pixmap(m_ptr->iconSize));

    // Draw timestamp
    QRect timeStampRect(m_ptr->timestampBox(opt, index));

    timeStampRect.moveTo(m_ptr->margins.left() + m_ptr->iconSize.width()
                         + m_ptr->spacingHorizontal, contentRect.top());

    painter->setFont(f);
    painter->setPen(palette.text().color());
    painter->drawText(timeStampRect, Qt::TextSingleLine,
                      index.data(Qt::UserRole).toString());

    // Draw message text
    QRect messageRect(m_ptr->messageBox(opt));

    messageRect.moveTo(timeStampRect.left(), timeStampRect.bottom()
                       + m_ptr->spacingVertical);

    painter->setFont(opt.font);
    painter->setPen(palette.windowText().color());
    painter->drawText(messageRect, Qt::TextSingleLine, opt.text);

    painter->restore();
}

该示例的完整代码可在GitHub上找到。

结果

如所写,给定的示例产生以下结果:

带有消息记录器的窗口


推荐阅读