QListView / QListWidget с настраиваемыми элементами и пользовательскими виджетами элементов

Я пишу приложение PyQt, и у меня возникли проблемы с созданием пользовательского списка. Я хотел бы, чтобы список содержал произвольные виджеты (в частности, один пользовательский виджет). Как я могу это сделать?

Похоже, что альтернативой будет создание таблицы или сетки, завернутых в полосу прокрутки. Тем не менее, я хотел бы иметь возможность использовать подход модели / представления, а также вложение (древовидная) поддержки встроенного дескриптора.

Чтобы уточнить, пользовательские виджеты являются интерактивными (содержат кнопки), поэтому для решения требуется больше, чем рисование виджета.

Я думаю, вам нужно подclassифицировать QItemDelegate .

QItemDelegate может использоваться для предоставления пользовательских функций отображения и виджетов элементов для представления элементов на основе подclassов QAbstractItemView. Использование делегата для этой цели позволяет настраивать и разрабатывать механизмы отображения и редактирования независимо от модели и представления.

Этот код взят из примеров Qt, торрент-приложения.

class TorrentViewDelegate : public QItemDelegate { Q_OBJECT public: inline TorrentViewDelegate(MainWindow *mainWindow) : QItemDelegate(mainWindow) {} inline void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const { if (index.column() != 2) { QItemDelegate::paint(painter, option, index); return; } // Set up a QStyleOptionProgressBar to precisely mimic the // environment of a progress bar. QStyleOptionProgressBar progressBarOption; progressBarOption.state = QStyle::State_Enabled; progressBarOption.direction = QApplication::layoutDirection(); progressBarOption.rect = option.rect; progressBarOption.fontMetrics = QApplication::fontMetrics(); progressBarOption.minimum = 0; progressBarOption.maximum = 100; progressBarOption.textAlignment = Qt::AlignCenter; progressBarOption.textVisible = true; // Set the progress and text values of the style option. int progress = qobject_cast(parent())->clientForRow(index.row())->progress(); progressBarOption.progress = progress < 0 ? 0 : progress; progressBarOption.text = QString().sprintf("%d%%", progressBarOption.progress); // Draw the progress bar onto the view. QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter); } }; 

В основном, как вы можете видеть, он проверяет, является ли столбец для рисования конкретным индексом, если он рисует индикатор выполнения. Я думаю, вы можете немного подкорректировать его, и вместо использования QStyleOption вы можете использовать свой собственный виджет.

edit: не забудьте настроить делегат элемента с помощью QListView с помощью setItemDelegate .

Изучая ваш вопрос, я наткнулся на эту тему, в которой подробно описывается, как рисовать пользовательский виджет с помощью QItemDelegate. Я считаю, что у него есть вся информация, которая вам может понадобиться.

@ Ответ Идана хорошо работает, но я опубликую более простой пример, который я придумал. Этот элемент делегата просто рисует черный прямоугольник для каждого элемента.

 class ItemDelegate : public QItemDelegate { public: explicit ItemDelegate(QObject *parent = 0) : QItemDelegate(parent) {} void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { painter->fillRect(option.rect.adjusted(1, 1, -1, -1), Qt::SolidPattern); } }; 

И тогда вам просто нужно установить его для виджета списка:

 ui->listWidget->setItemDelegate(new ItemDelegate(ui->listWidget)); 

Помощник говорит, что:

 void QTableWidget::setCellWidget (int row, int column, QWidget * widget) 

Устанавливает данный виджет, который будет отображаться в ячейке в данной строке и столбце, передавая право собственности на виджет на таблицу. Если виджет ячейки A заменен виджлетом ячейки B, виджет ячейки A будет удален.

И есть аналоги этого метода у большинства потомков QAbstractItemView.

Вы должны подclassифицировать Q *** делегировать только тогда, когда вы хотите, чтобы виджет редактора появлялся в режиме просмотра только при нажатии EditTrigger, затем исчезает и позволяет делегату каким-либо образом визуализировать элемент вида.

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

Другой способ добавления пользовательских элементов в listWidget. для этого вам нужно добавить новый class. назовите его так, как хотите, я просто дам его «myList». Надеюсь, вы знаете, как добавлять новые элементы в проект. 🙂

то в этом новом фрейме добавьте свой контроль столько, сколько хотите. как QLabels, QlineEdit и т. д.

то в основном classе u вам нужно добавить список имен списков или как вы хотите, и напишите следующий код

 MyList *myList = new MyList(); QListWidgetItem *item = new QListWidgetItem(); ui->list->insertItem(ui->list->size().height(),item); item->setSizeHint(QSize(50,30)); ui->list->setItemWidget(item,myList); 

последний u также может изменять свойства элементов, используя сигналы / слоты.

надеюсь, что это поможет вам ..!

Если я правильно понял ваш вопрос, вам нужно что-то вроде этого:

введите описание изображения здесь

где каждая строка содержит пользовательский набор виджетов.

Для этого выполните два шага.

Внедрить строку с помощью специального виджета

Во-первых, создайте собственный виджет, содержащий все виджеты, необходимые для каждой строки списка.

Здесь я использую метку и две кнопки в строке, с горизонтальной компоновкой.

 class MyCustomWidget(QWidget): def __init__(self, name, parent=None): super(MyCustomWidget, self).__init__(parent) self.row = QHBoxLayout() self.row.addWidget(QLabel(name)) self.row.addWidget(QPushButton("view")) self.row.addWidget(QPushButton("select")) self.setLayout(self.row) 

Добавить строки в список

Приведение в действие нескольких строк – это просто вопрос создания элемента виджета и привязка настраиваемого виджета к строке элемента.

 # Create the list mylist = QListWidget() # Add to list a new item (item is simply an entry in your list) item = QListWidgetItem(mylist) mylist.addItem(item) # Instanciate a custom widget row = MyCustomWidget() item.setSizeHint(row.minimumSizeHint()) # Associate the custom widget to the list entry mylist.setItemWidget(item, row) 
  • Когда следует использовать Q_OBJECT?
  • Что означает команда «lock» в сборке x86?
  • Как создать Qt 4.8 / 5.2 статически в VS2012, используя статическую среду выполнения MSVC, с поддержкой Windows XP?
  • Qt Linker Error: «неопределенная ссылка на vtable»
  • C ++ Qt - Как добавить «-std = c ++ 11» в make-файл, который генерируется qmake?
  • Отображение изображения Qt jpg
  • Что делает макрос Q_OBJECT? Почему все объекты Qt нуждаются в этом макросе?
  • Как сделать текст представления рендеринга богатым (html) текстом в Qt
  • что означает __declspec (dllimport)?
  • Как выполнить функтор или lambda в заданном streamе в Qt, GCD-стиле?
  • Добавление внешней библиотеки в проект Qt Creator
  • Давайте будем гением компьютера.