Qt QListWidgetItem Несколько строк

У меня есть очень простой объект QListWidget, и я хочу создать список папок. Когда я добавляю элемент в свой список, я делаю следующее:

void LessCC::on_addFolderButton_clicked()
{
    QString dirName = QFileDialog::getExistingDirectory(this, tr("Choose Directory"), QDir::homePath(), QFileDialog::ShowDirsOnly);
    QListWidgetItem* newItem = new QListWidgetItem(QIcon(":/resources/icons/folder.png"), dirName, 0, 0);
    this->ui->folderListWidget->addItem(newItem);
}

Это работает, но я хочу, чтобы мои элементы имели несколько строк или столбцов информации (с другим стилем).

Я слышал о QStyledItemDelegate, но я не очень понимаю, как это работает, потому что все другие решения, которые я нашел, кажутся очень сложными для таких простых(?)< /em> вещь.

Это единственное решение или, может быть, есть что-то более простое, чего я не видел?

Надеюсь, кто-нибудь может мне помочь.


person wnkz    schedule 01.08.2011    source источник


Ответы (1)


Немного сложно предложить «лучшее» решение, не видя, как именно вы хотите, чтобы ваш элемент списка выглядел, но мы попробуем.

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

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

Создание пользовательского делегата звучит пугающе, но по сути это просто предоставление пользовательского виджета для списка. Он работает по существу как шаблон. Вы определяете, как должен выглядеть элемент списка, и рисуете его, используя данные из списка. Вы просто можете наследовать от QAbstractItemDelegate.

#include <QPainter>
#include <QAbstractItemDelegate>

class ListDelegate : public QAbstractItemDelegate
{
    public:
       ListDelegate(QObject *parent = 0);

       void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
       QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const;

       virtual ~ListDelegate();
};

Самая большая работа — написать код функции рисования. Здесь я покажу только основы, но вы можете перейти по ссылке выше, чтобы посмотреть более длинный пример.

ListDelegate::ListDelegate(QObject *parent)
: QAbstractItemDelegate(parent)
{

}

void ListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
        QRect r = option.rect;

        QPen fontPen(QColor::fromRgb(51,51,51), 1, Qt::SolidLine);

        if(option.state & QStyle::State_Selected)
            {
            painter->setBrush(Qt::cyan);
            painter->drawRect(r);

        } 
            else 
            {
            //BACKGROUND ALTERNATING COLORS
            painter->setBrush( (index.row() % 2) ? Qt::white : QColor(252,252,252) );
            painter->drawRect(r);
        }

            painter->setPen(fontPen);

        //GET TITLE, DESCRIPTION AND ICON
        QIcon ic = QIcon(qvariant_cast<QPixmap>(index.data(Qt::DecorationRole)));
        QString title = index.data(Qt::DisplayRole).toString();
        QString description = index.data(Qt::UserRole).toString();

        int imageSpace = 10;
        if (!ic.isNull()) 
            {
            //ICON
            r = option.rect.adjusted(5, 10, -10, -10);
            ic.paint(painter, r, Qt::AlignVCenter|Qt::AlignLeft);
            imageSpace = 55;
        }

        //TITLE
        r = option.rect.adjusted(imageSpace, 0, -10, -30);
        painter->setFont( QFont( "Lucida Grande", 6, QFont::Normal ) );
        painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignBottom|Qt::AlignLeft, title, &r);

        //DESCRIPTION
        r = option.rect.adjusted(imageSpace, 30, -10, 0);
        painter->setFont( QFont( "Lucida Grande", 5, QFont::Normal ) );
        painter->drawText(r.left(), r.top(), r.width(), r.height(), Qt::AlignLeft, description, &r);

}

QSize ListDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
   return QSize(200, 60); // very dumb value
}

ListDelegate::~ListDelegate()
{

}

Итак, вы можете видеть, что в этом коде мы получаем три бита данных из списка. Значок, заголовок и описание. Затем мы отображаем рисунок значка и рисуем две текстовые строки так, как нам нравится. Но важной частью является получение самих данных. По сути, мы просим список предоставить нам данные, используя переданный нам «индекс».

QIcon ic = QIcon(qvariant_cast<QPixmap>(index.data(Qt::DecorationRole)));
QString title = index.data(Qt::DisplayRole).toString();
QString description = index.data(Qt::UserRole + 1).toString();

Вы заметите, что каждый бит информации был получен с использованием другой «роли». Обычно список отображает только одну вещь, доступ к которой осуществляется через DisplayRole. Значки хранятся в DecorationRole. Но если вы хотите хранить больше вещей, вы начинаете использовать UserRole. Вы можете хранить множество вещей, используя UserRole, UserRole +1, UserRole +2 и т. д....

Итак, как вы храните всю эту информацию в каждом элементе. Легкий...

QListWidgetItem *item = new QListWidgetItem();
item->setData(Qt::DisplayRole, "Title");
item->setData(Qt::UserRole, "Description");
myListWidget->addItem(item);

И, наконец, как заставить список отображать элемент с помощью нового модного делегата?

myListWidget->setItemDelegate(new ListDelegate(myListWidget));

Надеюсь, это немного прояснило ситуацию.

person Liz    schedule 01.08.2011