QT开发中文网

我在mainwindow里有一个QTreeView,通过delegate实现了每一行第一个item是一个comboBox。我现在希望第二列最开始是空的, 根据第一列comboBox选的结果在此行第二列添加新的comboBox。如何用C++实现?

您可以通过继承QStyledItemDelegate来实现这个功能。以下是一个简单的例子:

  1. 创建一个自定义的delegate类,继承QStyledItemDelegate,并实现必要的函数。

  2. 重载createEditor函数,在第一列comboBox选中项发生改变时添加新的comboBox到第二列。

  3. 重载setModelData函数,将第二列comboBox选中项的值保存到model中。

  4. 在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存储下来,以便在选中项发生改变时更新第二列数据。

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://qt.0voice.com/?id=3015

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?