Qt实现从列表中选择项目到其他列表(双列表,累加器,列表构建器,TwoListSelection ......)

Ale*_*han 1 c++ qt qwidget qt5

我想从任意长度的列表中选择任意数量的项目.下拉列表(QComboBox)不允许检查项目.可检查项目列表会因很多项目而变得笨拙.

我在User Experience SE子网站中发现了这个问题,这个答案似乎是最适合我需求的解决方案.它有很多名称,作为回答备注中的评论:双列表,累加器,列表构建器,TwoListSelection ......

上面链接的答案中显示的OpenFaces.org版本:

一个

但是我在Qt中找不到实现.我应该自己实现它还是Qt中有可用的实现?有推荐的方法吗?

eyl*_*esc 6

这个小部件在Qt中没有默认,但是构建它并不复杂,首先应该列出要求:

  • 如果左边的列表不为空,则启用带有文本">>"的按钮,如果按下,则必须移动所有项目.

  • 带有文本"<<"的按钮与前一个类似,但右侧列表

  • 如果选择了左侧列表中的项目,则启用带有文本">"的按钮,如果按下该项,则应将所选项目移动到右侧.

  • 文本"<"的按钮相同,但右侧.

  • 如果选择了某个项目并且这不是列表中的第一项,则启用带有"向上"文本的按钮.按下时,您必须将当前项目移动到更高的位置.

  • 如果选择了一个项目并且这不是列表中的最后一项,则启用带有"向下"文本的按钮.按下时,您必须将当前项目移动到较低位置.

正如我们所看到的,大多数逻辑取决于项目的选择,为此,我们将信号itemSelectionChanged与决定按钮是否启用的插槽连接.

要移动,我们必须使用的物品takeItem()addItem(),第一删除项和第二添加它.

向上或向下移动相当于删除项目然后插入它,为此我们takeItem()再次使用insertItem()

以上所有内容都在以下小部件中实现:

#ifndef TWOLISTSELECTION_H
#define TWOLISTSELECTION_H

#include <QHBoxLayout>
#include <QListWidget>
#include <QPushButton>
#include <QWidget>

class TwoListSelection : public QWidget
{
    Q_OBJECT
public:
    explicit TwoListSelection(QWidget *parent = nullptr):QWidget{parent}{
        init();
        connections();
    }

    void addAvailableItems(const QStringList &items){
        mInput->addItems(items);
    }

    QStringList seletedItems(){
        QStringList selected;
        for(int i=0; i<mOuput->count(); i++)
            selected<< mOuput->item(i)->text();
        return selected;
    }
private:
    void init(){
        QHBoxLayout *layout = new QHBoxLayout(this);
        mInput = new QListWidget;
        mOuput = new QListWidget;

        mButtonToSelected = new QPushButton(">>");
        mBtnMoveToAvailable= new QPushButton(">");
        mBtnMoveToSelected= new QPushButton("<");
        mButtonToAvailable = new QPushButton("<<");

        layout->addWidget(mInput);

        QVBoxLayout *layoutm = new QVBoxLayout;
        layoutm->addItem(new QSpacerItem(10, 20, QSizePolicy::Minimum, QSizePolicy::Expanding));
        layoutm->addWidget(mButtonToSelected);
        layoutm->addWidget(mBtnMoveToAvailable);
        layoutm->addWidget(mBtnMoveToSelected);
        layoutm->addWidget(mButtonToAvailable);
        layoutm->addItem(new QSpacerItem(10, 20, QSizePolicy::Minimum, QSizePolicy::Expanding));

        layout->addLayout(layoutm);
        layout->addWidget(mOuput);

        mBtnUp = new QPushButton("Up");
        mBtnDown = new QPushButton("Down");

        QVBoxLayout *layoutl =  new QVBoxLayout;
        layoutl->addItem(new QSpacerItem(10, 20, QSizePolicy::Minimum, QSizePolicy::Expanding));
        layoutl->addWidget(mBtnUp);
        layoutl->addWidget(mBtnDown);
        layoutl->addItem(new QSpacerItem(10, 20, QSizePolicy::Minimum, QSizePolicy::Expanding));

        layout->addLayout(layoutl);
        setStatusButton();
    }

    void connections(){
        connect(mOuput, &QListWidget::itemSelectionChanged, this, &TwoListSelection::setStatusButton);
        connect(mInput, &QListWidget::itemSelectionChanged, this, &TwoListSelection::setStatusButton);
        connect(mBtnMoveToAvailable, &QPushButton::clicked, [=](){
           mOuput->addItem(mInput->takeItem(mInput->currentRow()));
        });

        connect(mBtnMoveToSelected, &QPushButton::clicked, [=](){
           mInput->addItem(mOuput->takeItem(mOuput->currentRow()));
        });

        connect(mButtonToAvailable, &QPushButton::clicked, [=](){
            while (mOuput->count()>0) {
                 mInput->addItem(mOuput->takeItem(0));
            }
        });

        connect(mButtonToSelected, &QPushButton::clicked, [=](){
            while (mInput->count()>0) {
                 mOuput->addItem(mInput->takeItem(0));
            }
        });

        connect(mBtnUp, &QPushButton::clicked, [=](){
            int row = mOuput->currentRow();
            QListWidgetItem *currentItem = mOuput->takeItem(row);
            mOuput->insertItem(row-1, currentItem);
            mOuput->setCurrentRow(row-1);
        });

        connect(mBtnDown, &QPushButton::clicked, [=](){
            int row = mOuput->currentRow();
            QListWidgetItem *currentItem = mOuput->takeItem(row);
            mOuput->insertItem(row+1, currentItem);
            mOuput->setCurrentRow(row+1);
        });
    }

    void setStatusButton(){
        mBtnUp->setDisabled(mOuput->selectedItems().isEmpty() || mOuput->currentRow() == 0);
        mBtnDown->setDisabled(mOuput->selectedItems().isEmpty() || mOuput->currentRow() == mOuput->count()-1);
        mBtnMoveToAvailable->setDisabled(mInput->selectedItems().isEmpty());
        mBtnMoveToSelected->setDisabled(mOuput->selectedItems().isEmpty());
    }

    QListWidget *mInput;
    QListWidget *mOuput;

    QPushButton *mButtonToAvailable;
    QPushButton *mButtonToSelected;

    QPushButton *mBtnMoveToAvailable;
    QPushButton *mBtnMoveToSelected;

    QPushButton *mBtnUp;
    QPushButton *mBtnDown;
};

#endif // TWOLISTSELECTION_H
Run Code Online (Sandbox Code Playgroud)

在以下链接中,您将找到一个完整的示例

在此输入图像描述

  • 它的 Qt 版本非常旧,从 5.6 或 5.7 开始,Qt 支持 C ++ 11,您可以在其中使用新的连接样式:https://wiki.qt.io/New_Signal_Slot_Syntax,此外还有其他功能。这就是为什么它与其版本不兼容。我已经用 Qt 5.10 对其进行了测试,但我认为它与 Qt 5.7 向前兼容。如果我有时间,我会对以前的版本提供支持。 (2认同)