Qt QListWidgetItem Multiple Lines - PullRequest
       33

Qt QListWidgetItem Multiple Lines

3 голосов
/ 02 августа 2011

У меня действительно простой 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 , но Я не совсем понимаю, как это работает, потому что все другие решения , которые я нашел, кажутся действительно сложными для таких простых (?) вещь.

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

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

1 Ответ

10 голосов
/ 02 августа 2011

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

На самом деле в ветке 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. Иконки хранятся в DecoRole. Но если вы хотите хранить больше вещей, тогда вы начинаете использовать 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));

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

...