IT Notes

Добавление виджетов в QListWidget

Основы работы с QListWidget мы уже рассматривали. Эту заметку можно считать продолжением. Разберемся с добавлением произвольных виджетов в QListWidget.

Для класса главного окна определим следующую функцию:

void MainWidget::makeItem( QListWidget* lstWgt ) {
    QWidget* wgt = new QWidget;
    QLayout* l = new QHBoxLayout;
    l->addWidget( new QLineEdit );
    QPushButton* btn = new QPushButton( "Click me" );
    connect( btn, SIGNAL( clicked() ), SLOT( onBtnClicked() ) );
    l->addWidget( btn );
    wgt->setLayout( l );

    QListWidgetItem* item = new QListWidgetItem( lstWgt );
    item->setSizeHint( wgt->sizeHint() );
    lstWgt->setItemWidget( item, wgt );
}

Входным аргументом makeItem() служит указатель на виджет списка lstWgt. В этот список и будет добавлен тестовый виджет.

Виджет wgt содержит QLineEdit и QPushButton. Эти элементы выбраны совершенно произвольным образом. Вы можете использовать любой другой виджет, который хотите добавить в QListWidget.

Обратите внимание на соединение сигнала кнопки clicked() и слота onBtnClicked(). Реализацию этого слота мы обсудим чуть ниже.

Главная часть сосредоточена в конце функции. Именно там мы создаем QListWidgetItem. А затем связываем этот item с созданным ранее wgt вызовом setItemWidget().

Чтобы размер элемента соответствовал содержимому виджета, мы устанавливаем для него sizeHint, полученный от wgt.

А вот реализация слота onBtnClicked():

void MainWidget::onBtnClicked() {
    if( QPushButton* btn = qobject_cast< QPushButton* >( sender() ) ) {
        if( QLineEdit* e = btn->parent()->findChild< QLineEdit* >() ) {
            QMessageBox::information( this, "Button was clicked!", e->text() );
            return;
        }
    }
}

Наибольший интерес здесь представляет использование функций sender() и findChild(). Наличие этих функций в Qt позволяет нам не хранить указатели на содержимое каждого виджета в списке.

Функция sender() возвращает указатель на QObject, для которого сработал сигнал. В нашем случае - сигнал clicked() для QPushButton.

С помощью findChild() мы находим объект текстового поля. Заметим, что вызов этой функции происходит для родителя кнопки: btn->parent().

Таким образом, в результате щелчка на кнопке содержимое соседнего QLineEdit будет отображено в информационном диалоговом окне.

А теперь определим конструктор MainWidget, в котором заполним список содержимым:

MainWidget::MainWidget( QWidget* parent )
    : QWidget( parent ) {

    QListWidget* lstWgt = new QListWidget;
    QLayout* l = new QVBoxLayout;
    l->addWidget( lstWgt );
    setLayout( l );

    // Добавим в список 10 элементов
    for( int i = 0; i < 10; ++i ) {
        makeItem( lstWgt );
    }

    resize( 500, 500 );
}

Вот что у нас получилось:

widgets-in-qlistwidget-demo

Похожие публикации

Комментарии

Как поделиться

Anonymous:

Как поделиться

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

btn->parent()->findChild< QLineEdit* >()

Какой указатель мы получим если parent содержит несколько QlineEdit?

Андрей:

btn->parent()->findChild< QLineEdit* >()

Какой указатель мы получим если parent содержит несколько QlineEdit?

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

А возможно ли сделать компонент чтобы можно было делать вертикальный ресайз элемента внутри QListWidget при помощи мышки?

Anonymous:

А возможно ли сделать компонент чтобы можно было делать вертикальный ресайз элемента внутри QListWidget при помощи мышки?

Здравствуйте. Да, варианты есть. Запланировал выход статьи на эту тему.