【问题标题】:How to specify different strings for a QComboBox's popup menu than are displayed in the box itself?如何为 QComboBox 的弹出菜单指定与框本身显示的不同的字符串?
【发布时间】:2016-06-09 18:00:17
【问题描述】:

我有一个 Qt/C++ 应用程序,它在拥挤的窗口中包含许多(不可编辑的)QComboBox 小部件。用户可以单击这些组合框以从各种类型的单元中进行选择。为了使窗口宽度易于管理,QComboBoxes 需要尽可能的窄。

从概念上讲,组合框中的可用单位类型如下:

feet
meters
milliseconds
[etc]

...但是为了让 QComboBoxes 尽可能的瘦,它们在屏幕上用缩写表示,例如:

f
m
mS
[etc]

...到目前为止,一切都很好,但管理层现在希望在出现的弹出菜单中显示非缩写字符串(“feet”、“meters”、“milliseconds”等)当用户单击 QComboBox... 时,将缩写形式保留在框本身中。这在逻辑上似乎是可行的(因为弹出菜单只是短暂地出现在 GUI 的其余部分之前,因此没有根本原因不能使其更宽),但我不清楚如何使用 QComboBox 来实现这一点。

有没有“正确的方法”来做到这一点(没有破解 Qt 组合框代码)?

【问题讨论】:

  • 可能是stackoverflow.com/questions/16080431/… 的副本,我认为您也需要覆盖完成者。
  • 我没有测试它,只是一个想法:也许你可以在你的QComboBox 上设置一个自定义QStyledItemDelegate,在那里你重新实现displayText() 方法来显示你想要的文本。它可能比您当前的答案更简单...

标签: c++ qt qcombobox


【解决方案1】:

委托会更简单:

class Delegate : public QStyledItemDelegate {
public:
    QString displayText(const QVariant & value, const QLocale & locale) const override {
        // value contains one of your short labels {"mS", "f", "m"}
        return /* Just return the corresponding long label */;
    }
};

yourComboBox->setItemDelegate(new Delegate);

【讨论】:

    【解决方案2】:

    由于缺乏一个好的方法来做到这一点,我发现了一个丑陋的方法......至少在 MacOS/X 和 Windows 下,以下代码似乎对我来说足够好。 (我还没有在其他操作系统下尝试过,但我希望它也可以在其他地方工作):

    #include <QComboBox>
    #include <QIdentityProxyModel>
    #include <QStandardItemModel>
    #include <QProxyStyle>
    
    static const char * shortLabels[] = {"mS",           "f",    "m",      [... and so on...] };
    static const char * longLabels[]  = {"milliseconds", "feet", "meters", [... and so on...] };
    
    // A wrapper-facade data-model object that will provide the long label strings, but only when appropriate
    class LongLabelsProxyModel : public QIdentityProxyModel
    {
    public:
        LongLabelsProxyModel(QAbstractItemModel * source, QObject * parent = 0) : QIdentityProxyModel(parent), forceShortLabelsCounter(0)
        {
           setSourceModel(source);
        }
    
        virtual QVariant data(const QModelIndex &index, int role) const
        {
            return ((forceShortLabelsCounter == 0)&&((role == Qt::DisplayRole)||(role == Qt::EditRole)))
                   ? QVariant(QString(longLabels[index.row()])) :  
                     QIdentityProxyModel::data(index, role);
        }
    
        void BeginForceShortNames() {forceShortLabelsCounter++;}
        void EndForceShortNames()   {forceShortLabelsCounter--;}
    
    private:
        int forceShortLabelsCounter;
    };
    
    #ifndef __APPLE__
    // Under MacOS/X, this class isn't necessary, because OS/X uses a native/non-Qt popup widget.
    // For other OS's, however, we need to make the Qt popup widget wider so the long labels can be fully visible
    class WiderPopupProxyStyle : public QProxyStyle
    {
    public:
        WiderPopupProxyStyle(QStyle * baseStyle) : QProxyStyle(baseStyle) {/* empty */}
    
        virtual QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *option, SubControl sc, const QWidget *widget) const
        {
            QRect r = QProxyStyle::subControlRect(cc, option, sc, widget);
            if ((cc == QStyle::CC_ComboBox)&&(sc == QStyle::SC_ComboBoxListBoxPopup)) r.setWidth(r.width()*2);
            return r;
        }
    };
    #endif
    
    // My customized combo-box class that will show long strings in the popup menu
    class DelayUnitsComboBox : public EnumComboBoxComponent
    {
    public:
        DelayUnitsComboBox(QWidget * parent = NULL ) : QComboBox(parent)
        {
    #ifndef __APPLE__
           // otherwise the popup list is the same width as the combo box
           // itself, which isn't wide enough to see the long strings
           setStyle(new WiderPopupProxyStyle(style()));
    #endif
    
           setModel(new LongLabelsProxyModel(new QStandardItemModel(0, 1, this), this));
    
           // Officially populate the QComboBox with the short labels
           for (int i=0; i<((sizeof(shortLabels)/sizeof(shortLabels[0])); i++) addItem(shortLabels[i]);
        }
    
        // overridden so that when drawing the actual QComboBox, we still use the shorter names
        virtual void paintEvent(QPaintEvent * p)
        {
            LongLabelsProxyModel * llpm = static_cast<LongLabelsProxyModel*>(model());
    
            llpm->BeginForceShortNames();
            EnumComboBoxComponent::paintEvent(p);
            llpm->EndForceShortNames();
        }
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-29
      • 2020-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多