【问题标题】:How to make QComboBox that has only one field editable?如何使只有一个字段的 QComboBox 可编辑?
【发布时间】:2016-05-19 08:04:24
【问题描述】:

我想创建一个QComboBox,允许您选择值或输入您自己的值。它应该可以工作,如果您选择可编辑选项并输入文本,那将是该选项的文本。如果您选择其他,然后返回到可编辑的,您输入的文本应该会保留。

我已经取得了一些进展。它看起来像这样:

组合框菜单

已选择可编辑项

选择了普通项目

我使用事件过滤器实现了这一点:

class MagicComboBoxEventFilter : public QObject {
public:
    explicit MagicComboBoxEventFilter(QObject* parent=0) : 
          QObject(parent),
          parentBox(nullptr),
          lastValue(""),
          editableIndex(-1)
    {
        parentBox = dynamic_cast<QComboBox*>(parent);
        if(parentBox) {
            connect(parentBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
                this, &MagicComboBoxEventFilter::currentIndexChanged);
    }
public slots:
        void currentIndexChanged(int index) {
            // Item data entry is unused, so I used it to determine
            // the editable field from others
            bool editable = parentBox->itemData(index).toInt()==666;
            parentBox->setEditable(editable);
        }
private:
    QComboBox* parentBox;
};

这适用于新的组合框:

QComboBox* comboBox = new QComboBox(this);
comboBox->setEditable(false);
new MagicComboBoxEventFilter(comboBox);

我面临的问题是即使用户选择了其他项目,如何保持可编辑值。我试图连接可编辑的文本更改事件,这是我增强的事件过滤器。我不会重复整个类代码,唯一的另一件事是现在构造函数中有额外的connect调用:

public slots:
        void currentIndexChanged(int index) {
            bool editable = parentBox->itemData(index).toInt()==666;
            parentBox->setEditable(editable);

            // If editable field selected, restore the last value entered
            if(editable) {
                parentBox->setItemText(index, lastValue);
            }
        }
        // slot connected in constructor
        void editTextChanged(const QString& text) {
            lastValue = text;
        }
private:
    QComboBox* parentBox;
    // Last string value the editable field had
    // qt doesn't remember that
    QString lastValue;

问题在于,当用户选择其他项目时 editTextChanged 在 currentIndexChanged 之前触发 并且我最终在lastValue 中拥有所选项目的文本,而不是最后输入的文本。

如何解决这个问题?我真的很努力,我需要一些帮助。

【问题讨论】:

  • 也许通过获取 QComboBox 的孩子,这是一个 QStandardItemModel,并在这个上安装另一个事件过滤器?我没有时间测试你的代码,但这个问题的答案可能会让我感兴趣

标签: qt qcombobox eventfilter


【解决方案1】:

嗯,我也想要同样的东西,但我认为这很容易(抱歉,python 语法):

class EditableComboBox(QComboBox):

    def __init__(self):
        QComboBox.__init__(self)
        self.currentIndexChanged.connect(self.fix)
        self.setInsertPolicy(QComboBox.InsertAtCurrent)

    def fix(self, index):
        if (self.currentData() == '----'):
            self.setEditable(True)
        else:
            self.setEditable(False)

基本上,只需将insertPolicy 设置为InsertAtCurrent 并通过设置editable 属性对每个currentIndexChanged 做出反应。我使用----作为可编辑字段的标记,并设置项目:

cb = EditableComboBox()
cb.addItem('', '----')
cb.addItem('One', '1')
cb.addItem('Two', '2')
cb.addItem('Three', '3')

PS。更改文本时,必须按回车键才能粘贴,否则如果选择其他项目,文本将丢失。

【讨论】:

    【解决方案2】:

    这对我有用。我的场景是选择文件扩展名。

    void VideoFormatWidget::on_comboBox_FileExtension_currentIndexChanged(int index)
    {
        ui->comboBox_FileExtension->setEditable(index==1);
    }
    

    我有进入

    0 "Select File Extension"
    

    进入

    1 "---"
    

    设置 Qt Creator

    还有一些软件也添加了项目。

    ui->comboBox_FileExtension->addItem("avi");
    ui->comboBox_FileExtension->addItem("mjpg");
    ui->comboBox_FileExtension->addItem("mpg");
    ui->comboBox_FileExtension->addItem("m2v");
    ui->comboBox_FileExtension->addItem("m4v");
    ui->comboBox_FileExtension->addItem("wmv");
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-20
      • 2019-11-26
      • 1970-01-01
      • 2014-01-21
      相关资源
      最近更新 更多