Qt实战:自定义二级选项框 | 附完整源码

发布于:2025-06-22 ⋅ 阅读:(14) ⋅ 点赞:(0)
1、目的

实现自定义二级选项框,一级选项有子项就没有选项功能,没有子项就有功能。

2、效果

在这里插入图片描述

3、方法

可以通过QToolButton和QMenu结合来实现这个功能。

4、源码
a、头文件
#ifndef SECONDARYCOMBOBOX_H
#define SECONDARYCOMBOBOX_H

#include <QMenu>
#include <QToolButton>
#include <QWidget>

struct UserData {
  QString textStr;
  QString dataStr;
  QAction *act = nullptr;
};
Q_DECLARE_METATYPE(UserData)

/** 需求:二级选项框,一级选项有子项就没有选项功能,没有子项就有功能;
 *
 */
class SecondaryComboBox : public QWidget {
  Q_OBJECT
 public:
  explicit SecondaryComboBox(QWidget *parent = 0);
  ~SecondaryComboBox();

  QString currentData() const;
  QString currentText() const;

  void setCurrentData(const QString &data);

  // 一次加入全部数据
  void addLists(const QList<QPair<QString, QString>> &firstList,
                const QList<QList<QPair<QString, QString>>> &secondList);

 signals:
  void currentDataChange();

 private:
  QToolButton *toolBtn = nullptr;
  QMenu *toolMenu = nullptr;
  QList<UserData> userDataList;
};

#endif  // SECONDARYCOMBOBOX_H

b、源文件
#include "secondarycombobox.h"

#include <QVBoxLayout>

const char propertyStr[5] = "data";

SecondaryComboBox::SecondaryComboBox(QWidget *parent) : QWidget(parent) {
  QVBoxLayout *lay = new QVBoxLayout(this);
  lay->setMargin(0);
  toolBtn = new QToolButton(this);
  toolMenu = new QMenu(this);
  toolBtn->setMinimumSize(100, 30);
  toolBtn->setPopupMode(QToolButton::MenuButtonPopup);
  toolBtn->setMenu(toolMenu);
  lay->addWidget(toolBtn);
}

SecondaryComboBox::~SecondaryComboBox() {}

QString SecondaryComboBox::currentData() const {
  QString retStr;
  QVariant var = toolBtn->property(propertyStr);
  if (var.canConvert<UserData>()) {
    UserData uData = var.value<UserData>();
    retStr = uData.dataStr;
  }
  return retStr;
}

QString SecondaryComboBox::currentText() const { return toolBtn->text(); }

void SecondaryComboBox::setCurrentData(const QString &data) {
  bool isFind = false;
  UserData newData;
  for (int i = 0; i < userDataList.size(); i++) {
    UserData uData = userDataList.at(i);
    if (uData.dataStr == data) {
      isFind = true;
      newData = uData;
      break;
    }
  }
  QVariant var = toolBtn->property(propertyStr);
  if (!isFind) {
    if (userDataList.size() == 0) return;
    newData = userDataList.at(0);
  }
  if (var.canConvert<UserData>()) {
    UserData curData = var.value<UserData>();
    if (curData.dataStr != newData.dataStr) {
      toolBtn->setText(newData.textStr);
      QVariant var = QVariant::fromValue(newData);
      toolBtn->setProperty(propertyStr, var);
      emit currentDataChange();
    }
  } else {
    toolBtn->setText(newData.textStr);
    QVariant var = QVariant::fromValue(newData);
    toolBtn->setProperty(propertyStr, var);
    emit currentDataChange();
  }
}

void SecondaryComboBox::addLists(
    const QList<QPair<QString, QString>> &firstList,
    const QList<QList<QPair<QString, QString>>> &secondList) {
  if (firstList.size() != secondList.size()) return;
  QString firstText;
  UserData firstUseData;
  bool isFirst = true;
  for (int i = 0; i < firstList.size(); i++) {
    const QPair<QString, QString> &pair = firstList.at(i);
    const QList<QPair<QString, QString>> &list = secondList.at(i);
    if (list.size() == 0) {
      QAction *act = new QAction(pair.first, this);
      UserData uData;
      uData.textStr = pair.first;
      uData.dataStr = pair.second;
      uData.act = act;
      QVariant var = QVariant::fromValue(uData);
      act->setProperty(propertyStr, var);
      userDataList.push_back(uData);
      toolMenu->addAction(act);
      if (isFirst) {
        firstText = pair.first;
        firstUseData = uData;
        isFirst = false;
      }
      connect(act, &QAction::triggered, [=]() {
        bool isChange = true;
        QVariant var = toolBtn->property(propertyStr);
        if (var.canConvert<UserData>()) {
          UserData uData = var.value<UserData>();
          if (uData.act == act) {
            isChange = false;
          }
        }
        if (isChange) {
          toolBtn->setText(act->text());
          toolBtn->setProperty(propertyStr, act->property(propertyStr));
          emit currentDataChange();
        }
      });
    } else {
      QMenu *menu = new QMenu(pair.first, this);
      for (int j = 0; j < list.size(); j++) {
        QPair<QString, QString> pair = list.at(j);
        QAction *act = new QAction(pair.first, this);
        UserData uData;
        uData.textStr = pair.first;
        uData.dataStr = pair.second;
        uData.act = act;
        QVariant var = QVariant::fromValue(uData);
        act->setProperty(propertyStr, var);
        userDataList.push_back(uData);
        menu->addAction(act);
        if (isFirst) {
          firstText = pair.first;
          firstUseData = uData;
          isFirst = false;
        }
        connect(act, &QAction::triggered, [=]() {
          bool isChange = true;
          QVariant var = toolBtn->property(propertyStr);
          if (var.canConvert<UserData>()) {
            UserData uData = var.value<UserData>();
            if (uData.act == act) {
              isChange = false;
            }
          }
          if (isChange) {
            toolBtn->setText(act->text());
            toolBtn->setProperty(propertyStr, act->property(propertyStr));
            emit currentDataChange();
          }
        });
      }
      toolMenu->addMenu(menu);
    }
  }
}

点击下载完整代码

对你有用就点个赞👍,以后需要用到就收藏⭐


网站公告

今日签到

点亮在社区的每一天
去签到