이번 포스팅에서는 Tableview 위에 ComboBox를 추가한 후 각 Cell 별로 다른 데이터를 추가하는 방법을 알려드리겠습니다.
이전에 "QTableView에 CheckBox 및 ComboBox 삽입하기" 주제에서 ComboBox와 ComboBoxDelegate 클래스를 다룬적이 있지만,
추가로 ComboBox 부분을 더욱 자세하게 다뤄보겠습니다.
QComboboxdelegate 클래스를 이용하면 QTableview에 ComboBox를 생성할 수 있습니다.
단순히 QComboboxdelegate 클래스로 생성만 하는 경우 해당 Cell을 클릭해야만 ComboBox가 생성되고 선택 후에는 다시 선택했던 값만을 저장한 후 ComboBox가 사라지는 문제가 발생합니다.
프로그램이 종료될 때 까지 생성한 ComboBox를 Tableview에 고정하기 위해서는 openPersistentEditor() 함수를 사용하여야 합니다.
1. 우선, ComboBox를 생성할 Tableview와 각 데이터의 항목을 표시할 Header를 만들어보도록 하겠습니다.
Tableview의 Geometry는 임의로 정한 값이므로 UI에 맞게 setGeometry() 함수로 수정하시면 됩니다.
// QStandardItemModel & QTableView Init gridmodel = new QStandardItemModel(ROW_MAX, COL_MAX, this); tableview = new QTableView(this); tableview->setGeometry(10, 25, 591, 481); tableview->setModel(gridmodel); // Gridmodel Header Init gridmodel->setHorizontalHeaderItem(0, new QStandardItem(QString("Data"))); gridmodel->setHorizontalHeaderItem(1, new QStandardItem(QString("ComboBox"))); gridmodel->setHorizontalHeaderItem(2, new QStandardItem(QString("ComboBox"))); gridmodel->setHorizontalHeaderItem(3, new QStandardItem(QString("Data"))); gridmodel->setHorizontalHeaderItem(4, new QStandardItem(QString("Data"))); // Grid Row & Column for (int row = 0; row < ROW_MAX; row++) { for (int col = 0; col < COL_MAX; col++) { index = gridmodel->index(row, col, QModelIndex()); gridmodel->setData(index,""); tableview->setColumnWidth(col, WIDTH); } tableview->setRowHeight(row, HEIGHT); } |
2. 아래와 같이 ComboBoxDelegate를 통해 ComboBox을 Cell에 삽입할 경우는 해당 Cell을 마우스로 클릭하면,
그 순간 ComboBox가 나타나는 형태로 처음부터 ComboBox의 모양을 띄고 있지 않습니다.
또한, ComboBox를 만들 경우 Default로 선택하고 싶은 데이터가 있더라도 표시할 방법이 없는 Model입니다.
// ComboBoxDelegate Init ComboBoxDelegate *f_combodelegate = new ComboBoxDelegate(tableview, gridmodel); tableview->setItemDelegateForColumn(1, f_combodelegate); ComboBoxDelegate *s_combodelegate = new ComboBoxDelegate(tableview, gridmodel); tableview->setItemDelegateForColumn(2, s_combodelegate); for(int nrow = 0; nrow < ROW_MAX; nrow++) { // First Column ComboBox Section QString str = ""; str.sprintf("ComboBox%d", nrow); index = gridmodel->index(nrow, 1, QModelIndex()); gridmodel->setData(index, str); // Second Column ComboBox Section str.sprintf("ComboBox%d", nrow + ROW_MAX); index = gridmodel->index(nrow, 2, QModelIndex()); gridmodel->setData(index, str); } |
3. ComboBox를 Tableview에 계속 유지하고 싶을 경우, openPersistentEditor(const QModelIndex &index)라는 함수를 사용할 수 있습니다. 특정 Cell의 Index를 매개변수로 전달하면 해당 Cell의 Combox는 프로그램이 종료되기 전까지 유지됩니다.
// ComboBoxDelegate Init ComboBoxDelegate *f_combodelegate = new ComboBoxDelegate(tableview, gridmodel); tableview->setItemDelegateForColumn(1, f_combodelegate); ComboBoxDelegate *s_combodelegate = new ComboBoxDelegate(tableview, gridmodel); tableview->setItemDelegateForColumn(2, s_combodelegate); for(int nrow = 0; nrow < ROW_MAX; nrow++) { // First Column ComboBox Section QString str = ""; str.sprintf("ComboBox%d", nrow); index = gridmodel->index(nrow, 1, QModelIndex()); gridmodel->setData(index, str); tableview->openPersistentEditor(gridmodel->index(nrow, 1)); // 추가 // Second Column ComboBox Section str.sprintf("ComboBox%d", nrow + ROW_MAX); index = gridmodel->index(nrow, 2, QModelIndex()); gridmodel->setData(index, str); tableview->openPersistentEditor(gridmodel->index(nrow, 2)); // 추가 } |
4. 이제 ComboBox가 마우스 선택시에만 생성되는 문제는 해결하였지만, 모든 Cell의 ComboBox 값이 첫번째 값으로 시작되는 문제가 발생합니다. 이를 해결하지 위해서는 comboboxdelegate.cpp 파일 내에서 원하는 값을 구현해주어야 합니다.
각 Cell의 Index만을 가져와 해당하는 Row, Column에 ComboxBox를 생성하는 방식이기 때문에,
추가로 QStandardItemModel의 주소 값을 매개변수로 넘겨주도록 합니다.
* mainwindow.cpp 부
... ComboBoxDelegate *s_combodelegate = new ComboBoxDelegate(tableview, gridmodel); ... |
* comboboxdelegate.cpp 생성자
ComboBoxDelegate::ComboBoxDelegate(QObject* parent, QStandardItemModel *gridmodel) : QStyledItemDelegate(parent) { parentGridModel = gridmodel; } |
* comboboxdelegate.cpp 부 createEditor 함수
... QString strpindata = parentGridModel[0].index(index.row(), index.column()).data().toString(); cb->setCurrentText(strpindata); ... |
생성자에서 받은 parentGridModel 변수를 통해 현재 mainwindow의 gridmodel에 설정되어 있는 값을 알 수 있기 때문에,
ComboBox 생성 후 단순히 첫번째 값을 반환하지 않고 현재 설정된 값을 반환할 수 있습니다.
* mainwindow.h 및 mainwindow.cpp 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
// mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QStandardItemModel>
#include <QTableView>
#define ROW_MAX 15
#define COL_MAX 5
#define WIDTH 120
#define HEIGHT 30
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
void GridTableView();
~MainWindow();
private:
Ui::MainWindow *ui;
QStandardItemModel *gridmodel;
QTableView *tableview;
QModelIndex index;
};
#endif // MAINWINDOW_H
// mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "comboboxdelegate.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
GridTableView();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::GridTableView()
{
// QStandardItemModel & QTableView Init
gridmodel = new QStandardItemModel(ROW_MAX, COL_MAX, this);
tableview = new QTableView(this);
tableview->setGeometry(10, 25, 591, 481);
tableview->setModel(gridmodel);
// Gridmodel Header Init
gridmodel->setHorizontalHeaderItem(0, new QStandardItem(QString("Data")));
gridmodel->setHorizontalHeaderItem(1, new QStandardItem(QString("ComboBox")));
gridmodel->setHorizontalHeaderItem(2, new QStandardItem(QString("ComboBox")));
gridmodel->setHorizontalHeaderItem(3, new QStandardItem(QString("Data")));
gridmodel->setHorizontalHeaderItem(4, new QStandardItem(QString("Data")));
// Grid Row & Column
for (int row = 0; row < ROW_MAX; row++)
{
for (int col = 0; col < COL_MAX; col++)
{
index = gridmodel->index(row, col, QModelIndex());
gridmodel->setData(index,"");
tableview->setColumnWidth(col, WIDTH);
}
tableview->setRowHeight(row, HEIGHT);
}
// ComboBoxDelegate Init
ComboBoxDelegate *f_combodelegate = new ComboBoxDelegate(tableview, gridmodel);
tableview->setItemDelegateForColumn(1, f_combodelegate);
ComboBoxDelegate *s_combodelegate = new ComboBoxDelegate(tableview, gridmodel);
tableview->setItemDelegateForColumn(2, s_combodelegate);
for(int nrow = 0; nrow < ROW_MAX; nrow++)
{
// First Column ComboBox Section
QString str = "";
str.sprintf("ComboBox%d", nrow);
index = gridmodel->index(nrow, 1, QModelIndex());
gridmodel->setData(index, str);
tableview->openPersistentEditor(gridmodel->index(nrow, 1));
// Second Column ComboBox Section
str.sprintf("ComboBox%d", nrow + ROW_MAX);
index = gridmodel->index(nrow, 2, QModelIndex());
gridmodel->setData(index, str);
tableview->openPersistentEditor(gridmodel->index(nrow, 2));
}
}
|
* comboboxdelegate.h 및 comboboxdelegate.cpp 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125 126
|
// comboboxdelegate.h #ifndef COMBOBOXDELEGATE_H
#define COMBOBOXDELEGATE_H
#include <QStyledItemDelegate>
#include <QComboBox>
#include <QStandardItemModel>
class ComboBoxDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
ComboBoxDelegate(QObject* parent=0, QStandardItemModel *gridmodel=0);
~ComboBoxDelegate();
QWidget *createEditor( QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const;
void setEditorData( QWidget *editor,
const QModelIndex &index ) const;
void setModelData( QWidget *editor,
QAbstractItemModel *model,
const QModelIndex &index ) const;
void updateEditorGeometry( QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &index ) const;
QStringList comboItems;
mutable QComboBox *combo;
private:
QStandardItemModel *parentGridModel;
};
#endif // COMBOBOXDELEGATE_H
// comboboxdelegate.cpp
#include "comboboxdelegate.h"
#include <QComboBox>
ComboBoxDelegate::ComboBoxDelegate(QObject* parent, QStandardItemModel *gridmodel)
: QStyledItemDelegate(parent)
{
parentGridModel = gridmodel;
}
ComboBoxDelegate::~ComboBoxDelegate()
{
}
QWidget* ComboBoxDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
// ComboBox ony in column 2
if ((index.column() != 1) && (index.column() != 2))
return QStyledItemDelegate::createEditor(parent, option, index);
// Create the combobox and populate it
QComboBox* cb = new QComboBox(parent);
if(index.column() == 1)
{
cb->addItem(QString("ComboBox0"));
cb->addItem(QString("ComboBox1"));
cb->addItem(QString("ComboBox2"));
cb->addItem(QString("ComboBox3"));
cb->addItem(QString("ComboBox4"));
cb->addItem(QString("ComboBox5"));
cb->addItem(QString("ComboBox6"));
cb->addItem(QString("ComboBox7"));
cb->addItem(QString("ComboBox8"));
cb->addItem(QString("ComboBox9"));
cb->addItem(QString("ComboBox10"));
cb->addItem(QString("ComboBox11"));
cb->addItem(QString("ComboBox12"));
cb->addItem(QString("ComboBox13"));
cb->addItem(QString("ComboBox14"));
}
else if(index.column() == 2)
{
cb->addItem(QString("ComboBox15"));
cb->addItem(QString("ComboBox16"));
cb->addItem(QString("ComboBox17"));
cb->addItem(QString("ComboBox18"));
cb->addItem(QString("ComboBox19"));
cb->addItem(QString("ComboBox20"));
cb->addItem(QString("ComboBox21"));
cb->addItem(QString("ComboBox22"));
cb->addItem(QString("ComboBox23"));
cb->addItem(QString("ComboBox24"));
cb->addItem(QString("ComboBox25"));
cb->addItem(QString("ComboBox26"));
cb->addItem(QString("ComboBox27"));
cb->addItem(QString("ComboBox28"));
cb->addItem(QString("ComboBox29"));
}
QString strpindata = parentGridModel[0].index(index.row(), index.column()).data().toString();
cb->setCurrentText(strpindata);
return cb;
}
void ComboBoxDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
QString text = index.model()->data( index, Qt::DisplayRole ).toString();
int comboIndex = comboItems.indexOf(QRegExp(text));
if(comboIndex>=0)
(static_cast<QComboBox*>( editor ))->setCurrentIndex(comboIndex);
}
void ComboBoxDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{
model->setData( index, static_cast<QComboBox*>( editor )->currentText() );
}
void ComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
editor->setGeometry( option.rect );
}
|
'Qt' 카테고리의 다른 글
QSplitter 클래스로 Widget 크기 조절하기 (0) | 2020.11.04 |
---|---|
Qt Designer 에서 styleSheet 사용하기 (0) | 2020.10.23 |
Qt Remote Debugging (0) | 2020.06.12 |
Qt 컨테이너 클래스 정리 (0) | 2020.04.16 |
fork() 함수 및 exec() 계열 함수로 Child Process 실행하기 (0) | 2020.04.01 |