[Qt] TreeWidget 사용하기
Qt를 설치할 때 볼 수 있던 아래와 같은 구조가지는 UI Component를 TreeWidget이라고 합니다. Qt에서 TreeWidget을 사용하는 법에 대해 간단히 소개하려고 합니다.
먼저 UI는 아래와 같이 구성했습니다. 상단에 QTreeWidget 그리고 하단에는 선택한 Item의 Text를 확인할 수 있는 Label과 선택된 Item에 자식 Item을 추가할 수 있는 Insert와 해당 Item을 지울 Delete 버튼입니다.
먼저 간단하게 Header와 몇가지 Item을 추가해보겠습니다.
#include "mainwindow.h"
#include "./ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QTreeWidgetItem* headerItem = new QTreeWidgetItem;
headerItem->setText(0, "Name");
headerItem->setText(1, "Price");
ui->treeWidget->setHeaderItem(headerItem); // header
QTreeWidgetItem* Parent = new QTreeWidgetItem(ui->treeWidget);
Parent->setText(0, "Nintendo");
QTreeWidgetItem* Child = new QTreeWidgetItem(Parent);
Child->setText(0, "Zelda");
Child->setText(1, "70000");
}
MainWindow::~MainWindow()
{
delete ui;
}
Nintendo라는 부모 Item 아래 Zelda 라는 자식 Item을 추가했습니다.
여기에 선택된 Item의 Name을 label에 보여주는 Connect를 추가해보겠습니다.
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QTreeWidgetItem* headerItem = new QTreeWidgetItem;
headerItem->setText(0, "Name");
headerItem->setText(1, "Price");
ui->treeWidget->setHeaderItem(headerItem); // header
QTreeWidgetItem* Parent = new QTreeWidgetItem(ui->treeWidget);
Parent->setText(0, "Nintendo");
QTreeWidgetItem* Child = new QTreeWidgetItem(Parent);
Child->setText(0, "Zelda");
Child->setText(1, "70000");
connect(ui->treeWidget, &QTreeWidget::itemClicked, [&] (QTreeWidgetItem *item, int column) {
QString sName = item->text(0);
ui->lbTreeItemTitle->setText(sName);
});
}
다음으로 Add Child Item, Delete Item 코드입니다.
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QTreeWidgetItem* headerItem = new QTreeWidgetItem;
headerItem->setText(0, "Name");
headerItem->setText(1, "Price");
ui->treeWidget->setHeaderItem(headerItem); // header
QTreeWidgetItem* Parent = new QTreeWidgetItem(ui->treeWidget);
Parent->setText(0, "Nintendo");
QTreeWidgetItem* Child = new QTreeWidgetItem(Parent);
Child->setText(0, "Zelda");
Child->setText(1, "70000");
connect(ui->treeWidget, &QTreeWidget::itemClicked, [&] (QTreeWidgetItem *item, int column) {
QString sName = item->text(0);
ui->lbTreeItemTitle->setText(sName);
}); // Display Current Selected Item Name(Column = 0)
connect(ui->pb_AddChild, &QPushButton::clicked, [&] {
QTreeWidgetItem* pCurrentSelectedItem = ui->treeWidget->currentItem();
if ( pCurrentSelectedItem == nullptr ) { return; }
QTreeWidgetItem* pNewChild = new QTreeWidgetItem;
pNewChild->setText(0, ui->le_ChildTitle->text());
pCurrentSelectedItem->addChild(pNewChild);
}); // Add Child Item
connect(ui->pb_DeleteItem, &QPushButton::clicked, [&] {
QTreeWidgetItem* pCurrentSelectedItem = ui->treeWidget->currentItem();
if ( pCurrentSelectedItem == nullptr ) { return; }
delete pCurrentSelectedItem;
}); // Delete Current Item
}
다음은 Item을 접고 펼칠때마다 Column의 크기를 재 조정할 수 있는 기능입니다.
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QTreeWidgetItem* headerItem = new QTreeWidgetItem;
headerItem->setText(0, "Name");
headerItem->setText(1, "Price");
ui->treeWidget->setHeaderItem(headerItem); // header
QTreeWidgetItem* Parent = new QTreeWidgetItem(ui->treeWidget);
Parent->setText(0, "Nintendo");
QTreeWidgetItem* Child = new QTreeWidgetItem(Parent);
Child->setText(0, "Zelda");
Child->setText(1, "70000");
connect(ui->treeWidget, &QTreeWidget::itemClicked, [&] (QTreeWidgetItem *item, int column) {
QString sName = item->text(0);
ui->lbTreeItemTitle->setText(sName);
}); // Display Current Selected Item Name(Column = 0)
connect(ui->pb_AddChild, &QPushButton::clicked, [&] {
QTreeWidgetItem* pCurrentSelectedItem = ui->treeWidget->currentItem();
if ( pCurrentSelectedItem == nullptr ) { return; }
QTreeWidgetItem* pNewChild = new QTreeWidgetItem;
pNewChild->setText(0, ui->le_ChildTitle->text());
pCurrentSelectedItem->addChild(pNewChild);
}); // Add Child Item
connect(ui->pb_DeleteItem, &QPushButton::clicked, [&] {
QTreeWidgetItem* pCurrentSelectedItem = ui->treeWidget->currentItem();
if ( pCurrentSelectedItem == nullptr ) { return; }
delete pCurrentSelectedItem;
}); // Delete Current Item
connect(ui->treeWidget, &QTreeWidget::itemExpanded, [&] (QTreeWidgetItem *item) {
ui->treeWidget->resizeColumnToContents(0);
ui->treeWidget->resizeColumnToContents(1);
}); // Resize Columns
connect(ui->treeWidget, &QTreeWidget::itemCollapsed, [&] (QTreeWidgetItem *item) {
ui->treeWidget->resizeColumnToContents(0);
ui->treeWidget->resizeColumnToContents(1);
}); // Resize Columns
}
마지막으로 TreeWidgetItem에 체크박스를 추가하고 체크 상태에 따라 부모와 자식의 상태도 자동으로 변하는 기능입니다.
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QTreeWidgetItem* headerItem = new QTreeWidgetItem;
headerItem->setText(0, "Name");
headerItem->setText(1, "Price");
ui->treeWidget->setHeaderItem(headerItem); // header
QTreeWidgetItem* Parent = new QTreeWidgetItem(ui->treeWidget);
Parent->setCheckState(0, Qt::Unchecked);
Parent->setFlags(Parent->flags() | Qt::ItemIsAutoTristate | Qt::ItemIsUserCheckable );
Parent->setText(0, "Nintendo");
QTreeWidgetItem* Child = new QTreeWidgetItem(Parent);
Child->setFlags(Child->flags() | Qt::ItemIsUserCheckable );
Child->setCheckState(0, Qt::Unchecked);
Child->setText(0, "Zelda");
Child->setText(1, "70000");
Child = new QTreeWidgetItem(Parent);
Child->setFlags(Child->flags() | Qt::ItemIsUserCheckable );
Child->setCheckState(0, Qt::Unchecked);
Child->setText(0, "Mario");
Child->setText(1, "75000");
Child = new QTreeWidgetItem(Parent);
Child->setFlags(Child->flags() | Qt::ItemIsUserCheckable );
Child->setCheckState(0, Qt::Unchecked);
Child->setText(0, "Pockemon");
Child->setText(1, "60000");
connect(ui->treeWidget, &QTreeWidget::itemClicked, [&] (QTreeWidgetItem *item, int column) {
QString sName = item->text(0);
ui->lbTreeItemTitle->setText(sName);
}); // Display Current Selected Item Name(Column = 0)
connect(ui->pb_AddChild, &QPushButton::clicked, [&] {
QTreeWidgetItem* pCurrentSelectedItem = ui->treeWidget->currentItem();
if ( pCurrentSelectedItem == nullptr ) { return; }
QTreeWidgetItem* pNewChild = new QTreeWidgetItem;
pNewChild->setText(0, ui->le_ChildTitle->text());
pCurrentSelectedItem->addChild(pNewChild);
}); // Add Child Item
connect(ui->pb_DeleteItem, &QPushButton::clicked, [&] {
QTreeWidgetItem* pCurrentSelectedItem = ui->treeWidget->currentItem();
if ( pCurrentSelectedItem == nullptr ) { return; }
delete pCurrentSelectedItem;
}); // Delete Current Item
connect(ui->treeWidget, &QTreeWidget::itemExpanded, [&] (QTreeWidgetItem *item) {
ui->treeWidget->resizeColumnToContents(0);
ui->treeWidget->resizeColumnToContents(1);
}); // Resize Columns
connect(ui->treeWidget, &QTreeWidget::itemCollapsed, [&] (QTreeWidgetItem *item) {
ui->treeWidget->resizeColumnToContents(0);
ui->treeWidget->resizeColumnToContents(1);
}); // Resize Columns
}
자식 Item에 Check 시에는 자식이 다수일 경우에는 Qt::PartiallyChecked이고 다 선택되면 Qt::Checked 상태 그리고 부모에서 Check 시에는 자식 Item이 모두 Qt::Checked 상태로 변하게 됩니다.
만약에 자식 item에는 checkbox를 두지 않고 싶으면 부모에 Qt::ItemIsAutoTristate는 제거하면 됩니다.