您可以通过继承QStyledItemDelegate来实现这个功能。以下是一个简单的例子:
创建一个自定义的delegate类,继承QStyledItemDelegate,并实现必要的函数。
重载createEditor函数,在第一列comboBox选中项发生改变时添加新的comboBox到第二列。
重载setModelData函数,将第二列comboBox选中项的值保存到model中。
在MainWindow中创建QTreeView控件并设置delegate为自定义delegate类。
下面是代码示例:
#include <QtWidgets>
class MyDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit MyDelegate(QObject *parent = nullptr);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const override;
private slots:
void onCurrentIndexChanged(int index);
private:
mutable QMap<int, QStringList> m_comboBoxItems; // 存储每行第一列ComboBox的items
};
MyDelegate::MyDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
QWidget* MyDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
if (index.column() == 0) { // 第一列用ComboBox编辑器
QComboBox* comboBox = new QComboBox(parent);
QStringList items = {"item1", "item2", "item3"};
comboBox->addItems(items);
connect(comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onCurrentIndexChanged(int)));
m_comboBoxItems.insert(index.row(), items);
return comboBox;
} else if (index.column() == 1) { // 第二列用空白编辑器
return new QWidget(parent);
}
return QStyledItemDelegate::createEditor(parent, option, index);
}
void MyDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
if (QComboBox* comboBox = qobject_cast<QComboBox*>(editor)) {
comboBox->setCurrentText(index.data(Qt::EditRole).toString());
}
}
void MyDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
if (QComboBox* comboBox = qobject_cast<QComboBox*>(editor)) {
model->setData(index, comboBox->currentText(), Qt::EditRole);
// 在第一列选中项改变时更新第二列的ComboBox
int row = index.row();
int column = index.column();
QStringList items = m_comboBoxItems.value(row);
QString selectedItem = comboBox->currentText();
if (!selectedItem.isEmpty()) {
// 如果此行第二列为空,添加一个新的comboBox
if (model->data(model->index(row, column+1)).toString().isEmpty()) {
QComboBox* newComboBox = new QComboBox(qobject_cast<QWidget*>(editor));
newComboBox->addItems(items);
connect(newComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onCurrentIndexChanged(int)));
model->setData(model->index(row, column+1), QVariant::fromValue<QWidget*>(newComboBox));
}
// 更新已有的comboBox的items
else {
QComboBox* existingBox = qvariant_cast<QWidget*>(model->data(model->index(row, column+1), Qt::EditRole));
if (existingBox != nullptr) {
existingBox->clear();
existingBox->addItems(items);
}
}
} else {
// 如果第一列选中项为空,将此行的第二列清空
model->setData(model->index(row, column+1), QVariant());
}
}
}
void MyDelegate::onCurrentIndexChanged(int index)
{
Q_UNUSED(index)
emit commitData(qobject_cast<QWidget*>(sender()));
emit closeEditor(qobject_cast<QWidget*>(sender()));
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
private:
QTreeView *m_treeView;
};
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
m_treeView = new QTreeView(this);
QStandardItemModel *model = new QStandardItemModel(0, 2, this);
m_treeView->setModel(model);
MyDelegate *delegate = new MyDelegate(this);
m_treeView->setItemDelegate(delegate);
setCentralWidget(m_treeView);
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
#include "main.moc"
需要注意的是,在setModelData函数中更新第二列数据时,要同时保存对应的comboBox控件指针。在重载createEditor函数时,也需要将每个ComboBox的items存储下来,以便在选中项发生改变时更新第二列数据。