콤보 위젯 매퍼 예제

콤보 위젯 매퍼 예제는 사용자 지정 델리게이트를 사용하여 모델의 정보를 양식의 특정 위젯에 매핑하는 방법을 보여줍니다.

각 사람의 나이를 입력할 수 있도록 스핀 박스를 제공하는 대신 주소를 '집', '직장' 또는 '기타'로 분류할 수 있는 콤보 박스를 제공한다는 점을 제외하면 거의 동일한 사용자 인터페이스를 가진 Window 클래스를 만듭니다.

창 클래스 정의

이 클래스는 생성자, 버튼을 최신 상태로 유지하기 위한 슬롯, 모델을 설정하기 위한 비공개 함수를 제공합니다:

class Window : public QWidget
{
    Q_OBJECT

public:
    Window(QWidget *parent = nullptr);

private slots:
    void updateButtons(int row);

private:
    void setupModel();

    QLabel *nameLabel;
    QLabel *addressLabel;
    QLabel *typeLabel;
    QLineEdit *nameEdit;
    QTextEdit *addressEdit;
    QComboBox *typeComboBox;
    QPushButton *nextButton;
    QPushButton *previousButton;

    QStandardItemModel *model;
    QStringListModel *typeModel;
    QDataWidgetMapper *mapper;
};

QDataWidgetMapper 객체와 사용자 인터페이스를 구성하는 데 사용되는 컨트롤 외에도 QStandardItemModel 을 사용하여 데이터를 저장하고 QStringListModel 을 사용하여 각 사람의 데이터에 적용할 수 있는 주소 유형에 대한 정보를 저장합니다.

창 클래스 구현

Window 클래스의 생성자는 세 부분으로 설명할 수 있습니다. 첫 번째 부분에서는 사용자 인터페이스에 사용되는 위젯을 설정합니다:

Window::Window(QWidget *parent)
    : QWidget(parent)
{
    setupModel();

    nameLabel = new QLabel(tr("Na&me:"));
    nameEdit = new QLineEdit();
    addressLabel = new QLabel(tr("&Address:"));
    addressEdit = new QTextEdit();
    typeLabel = new QLabel(tr("&Type:"));
    typeComboBox = new QComboBox();
    nextButton = new QPushButton(tr("&Next"));
    previousButton = new QPushButton(tr("&Previous"));

    nameLabel->setBuddy(nameEdit);
    addressLabel->setBuddy(addressEdit);
    typeLabel->setBuddy(typeComboBox);

    typeComboBox->setModel(typeModel);

다른 위젯과 같은 방식으로 콤보 상자를 매핑하도록 설정했지만, 각 사람에 대한 데이터가 포함된 모델이 아닌 자체 모델인 typeModel 의 데이터를 표시하도록 자체 모델을 적용한다는 점에 유의하세요.

다음으로 위젯 매퍼를 설정하여 각 입력 위젯을 setModel() 호출로 지정된 모델의 열에 연결합니다:

    mapper = new QDataWidgetMapper(this);
    mapper->setModel(model);
    mapper->addMapping(nameEdit, 0);
    mapper->addMapping(addressEdit, 1);
    mapper->addMapping(typeComboBox, 2, "currentIndex");

콤보 상자의 경우 위젯 매퍼에 어떤 속성을 모델의 값과 연관시킬지 알려주는 추가 인수를 전달합니다. 그 결과 사용자는 콤보 상자에서 항목을 선택할 수 있고 위젯의 currentIndex 속성에 저장된 해당 값이 모델에 저장됩니다.

나머지 생성자는 연결 및 레이아웃을 설정합니다:

    connect(previousButton, &QAbstractButton::clicked,
            mapper, &QDataWidgetMapper::toPrevious);
    connect(nextButton, &QAbstractButton::clicked,
            mapper, &QDataWidgetMapper::toNext);
    connect(mapper, &QDataWidgetMapper::currentIndexChanged,
            this, &Window::updateButtons);

    QGridLayout *layout = new QGridLayout();
    layout->addWidget(nameLabel, 0, 0, 1, 1);
    layout->addWidget(nameEdit, 0, 1, 1, 1);
    layout->addWidget(previousButton, 0, 2, 1, 1);
    layout->addWidget(addressLabel, 1, 0, 1, 1);
    layout->addWidget(addressEdit, 1, 1, 2, 1);
    layout->addWidget(nextButton, 1, 2, 1, 1);
    layout->addWidget(typeLabel, 3, 0, 1, 1);
    layout->addWidget(typeComboBox, 3, 1, 1, 1);
    setLayout(layout);

    setWindowTitle(tr("Delegate Widget Mapper"));
    mapper->toFirst();
}

모델은 창의 setupModel() 함수에서 초기화됩니다. 여기서는 5개의 행과 3개의 열로 구성된 표준 모델을 만듭니다. 각 행에 이름, 주소, 주소 유형을 나타내는 값을 삽입합니다. 주소 유형은 문자열 목록 모델에 저장됩니다.

void Window::setupModel()
{
    QStringList items;
    items << tr("Home") << tr("Work") << tr("Other");
    typeModel = new QStringListModel(items, this);

    model = new QStandardItemModel(5, 3, this);
    QStringList names;
    names << "Alice" << "Bob" << "Carol" << "Donald" << "Emma";
    QStringList addresses;
    addresses << "<qt>123 Main Street<br/>Market Town</qt>"
              << "<qt>PO Box 32<br/>Mail Handling Service"
                 "<br/>Service City</qt>"
              << "<qt>The Lighthouse<br/>Remote Island</qt>"
              << "<qt>47338 Park Avenue<br/>Big City</qt>"
              << "<qt>Research Station<br/>Base Camp<br/>Big Mountain</qt>";

    QStringList types;
    types << "0" << "1" << "2" << "0" << "2";

    for (int row = 0; row < 5; ++row) {
      QStandardItem *item = new QStandardItem(names[row]);
      model->setItem(row, 0, item);
      item = new QStandardItem(addresses[row]);
      model->setItem(row, 1, item);
      item = new QStandardItem(types[row]);
      model->setItem(row, 2, item);
    }
}

데이터베이스의 레코드처럼 모델에 각 행을 삽입할 때 각 사람의 주소 유형에 대해 typeModel 의 항목에 해당하는 값을 저장합니다. 위젯 매퍼가 각 행의 마지막 열에서 이러한 값을 읽을 때 다음 다이어그램에 표시된 것처럼 typeModel 의 값에 대한 참조로 사용해야 합니다. 이것이 바로 델리게이트가 사용되는 곳입니다.

완성도를 위해 updateButtons() 슬롯의 구현을 보여드리겠습니다:

void Window::updateButtons(int row)
{
    previousButton->setEnabled(row > 0);
    nextButton->setEnabled(row < model->rowCount() - 1);
}

요약 및 추가 자료

콤보 상자에 별도의 모델을 사용하면 기본 모델에 저장된 데이터와는 별개의 선택 메뉴를 제공합니다. 콤보 상자의 currentIndex 속성을 모델의 열과 연관시키는 네임드 매핑을 사용하면 모델에 조회 값을 효과적으로 저장할 수 있습니다.

그러나 위젯 매퍼의 컨텍스트 외부에서 모델을 읽을 때는 이러한 조회 값을 이해하려면 typeModel 에 대해 알아야 합니다. typeModel 에 저장된 데이터와 선택 사항을 모두 한 곳에 저장할 수 있으면 유용할 것입니다. 이는 SQL 위젯 매퍼 예제에서 다룹니다.

예제 프로젝트 @ code.qt.io

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.