QT开发中文网

我想在mainwindow里写一个QTreeView,每一行第一个item是一个comboBox。第二列最开始是空的, 根据comboBox选的结果更新这一行第二个item(也是一个comboBox)。如何用C++实现?

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

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

  2. 在构造函数中初始化数据结构。

  3. 重载rowCount、columnCount和data函数,用于设置树形控件的行数、列数和数据显示。

  4. 重载setData函数,在comboBox的选项发生改变时更新对应行的第二个comboBox。

  5. 在MainWindow中创建QTreeView控件并设置model为自定义model类。

下面是代码示例:

#include <QtWidgets>

class MyModel : public QAbstractItemModel
{
    Q_OBJECT

public:
    explicit MyModel(QObject *parent = nullptr);

    QModelIndex index(int row, int column, const QModelIndex &parent) const override;
    QModelIndex parent(const QModelIndex &index) const override;

    int rowCount(const QModelIndex &parent) const override;
    int columnCount(const QModelIndex &parent) const override;

    QVariant data(const QModelIndex &index, int role) const override;
    bool setData(const QModelIndex &index, const QVariant &value, int role) override;

private:
    QList<QStringList> m_data; // 存储数据
};

MyModel::MyModel(QObject *parent)
    : QAbstractItemModel(parent)
{
    // 初始化数据
    QStringList headers = {"Header1", "Header2"};
    m_data << headers;
    for (int i = 0; i < 5; ++i) {
        QStringList row = {"ComboBox1", ""};
        m_data << row;
     }
}

QModelIndex MyModel::index(int row, int column, const QModelIndex &parent) const
{
    if (!hasIndex(row, column, parent))
        return QModelIndex();

    return createIndex(row, column);
}

QModelIndex MyModel::parent(const QModelIndex &index) const
{
    Q_UNUSED(index)
    return QModelIndex();
}

int MyModel::rowCount(const QModelIndex &parent) const
{
    if (parent.column() > 0)
        return 0;

    if (!parent.isValid())
        return m_data.size();

    return 0;
}

int MyModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return m_data.first().size();
}

QVariant MyModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    switch (role) {
    case Qt::DisplayRole:
        return m_data.at(index.row()).at(index.column());
    case Qt::EditRole:
        // 返回ComboBox选中的值或者空字符串
        if (index.column() == 1 && !m_data.at(index.row()).at(0).isEmpty()) {
            QComboBox *comboBox = qobject_cast<QComboBox*>(qvariant_cast<QWidget*>(m_data.at(index.row()).at(1)));
            if (comboBox != nullptr)
                return comboBox->currentText();
            else
                return "";
        }
        break;
    case Qt::DecorationRole:
        break;
   }

   return QVariant();
}

bool MyModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
   if (role != Qt::EditRole || !index.isValid())
       return false;

   // 更新第二列数据
   if (index.column() == 0) {
       m_data[index.row()][0] = value.toString(); // 更新第一列数据

       emit dataChanged(createIndex(index.row(), 1), createIndex(index.row(), 1));
       return true;
   } else if (index.column() == 1) {
       m_data[index.row()][1] = value.toString();

       emit dataChanged(index, index);
       return true;
   }

   return false;
}

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);
    MyModel *model = new MyModel(this);
    m_treeView->setModel(model);

    setCentralWidget(m_treeView);
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    MainWindow w;
    w.show();
    
    return a.exec();
}

#include "main.moc"

需要注意的是,在setData函数中更新第二列数据时,要同时发出dataChanged信号,以便让树形控件显示最新的数据。此外,在data函数中返回第二列的数据时,如果当前行没有选中任何项,则应该返回空字符串。

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

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

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

联系我们

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

微信号:3007537140

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

关注我们
x

注册

已经有帐号?