如何使QComboBox向上弹出?

13

我的QComboBox派生类包含在一个QGraphicsScene中,位于(可见的)屏幕底部 - 但它向下弹出,因此看不见。

如何将弹出窗口强制向上打开而不是向下?

我尝试像这样重新实现showPopup

void MyComboBox::showPopup()
{
     QAbstractItemView *popupView = view();
     popupView->move(0,-100);
     //popupView->window->move(0,-100);
     QComboBox::showPopup();
}

结果是,内容似乎被移动了,但基础的弹出对象并没有。

4个回答

14

根据这里的信息,我成功地以以下方式完成了它:

void SteuerQComboBox::showPopup() {
    QComboBox::showPopup();
    QWidget *popup = this->findChild<QFrame*>(); 
    popup->move(popup->x(),popup->y()-this->height()-popup->height());
}

请注意,首先调用基类的 "showPopup" 非常重要

感谢所有阅读和思考我的问题的人!


不是一个坏的解决方案,但它向下动画,然后向上移动。 - Len

2

user1319422的解决方案还不错,但它有两个问题。

  1. 如果您的平台具有GUI动画,则列表框将向下动画打开,然后移动到文本框上方。
  2. 如果您禁用组合框动画(或者您没有它),调用QComboBox :: showPopup()仍会使GUI元素开始出现在屏幕上。因此,将其移动到那里会导致它闪烁,因为它首先出现并移动到下一个位置。

因此,为了解决第一个问题,我只关闭了动画:

void MyComboBox::showPopup()
{
  bool oldAnimationEffects = qApp->isEffectEnabled(Qt::UI_AnimateCombo);
  qApp->setEffectEnabled(Qt::UI_AnimateCombo, false);

  QComboBox::showPopup();
  qApp->setEffectEnabled(Qt::UI_AnimateCombo, oldAnimationEffects);
}

然后,对于第二个问题,在Show事件中移动了框架:

bool MyComboBox::eventFilter(QObject *o, QEvent *e)
{
  bool handled = false;
  if (e->type() == QEvent::Show)
  {
    if (o == view())
    {
      QWidget *frame = findChild<QFrame*>(); 

      //For some reason, the frame's geometry is GLOBAL, not relative to the QComboBox!
      frame->move(frame->x(),
                  mapToGlobal(lineEdit()->geometry().topLeft()).y() - frame->height());
    }
  }
  /*else if other filters here*/

  if (!handled)
    handled = QComboBox::eventFilter(o, e);

  return handled;
}

它可以工作,但是(当然)只有在view()上安装事件过滤器之后才能工作(在MyComboBox::setView中使用view()->installEventFilter(this),或者如果仅使用默认视图,则在MyComboBox构造函数中)。如果MyComboBox不可编辑,则lineEdit()将返回nullptr。请改用this - pasbi

1

如果您想在弹出窗口不可见时强制将其打开在视图之上,可以这样做:

void SteuerQComboBox::showPopup() {
    QComboBox::showPopup();
    QWidget *popup = this->findChild<QFrame*>(); 

    if((popup->y() + popup->height()) > this->window()->height())
        popup->move(popup->x(),popup->y()-this->height()-popup->height());
}

0
以下是一种不需要从 QComboBox 派生的解决方案,使用事件过滤器:
  • QComboBoxview 上安装 eventFilter
  • 通过从其 y 坐标中减去 view 的高度来向上移动其父级。

事件过滤器:

#ifndef MYEVENTFILTER_H
#define MYEVENTFILTER_H

#include <QObject>
#include <QEvent>
#include <QAbstractItemView>

class myEventFilter : public QObject
{
    Q_OBJECT

public:
    myEventFilter (QObject *parent = nullptr) {}

protected:
    bool eventFilter(QObject * obj, QEvent * event) override
    {
        if (event->type() == QEvent::Show)
        {
            QAbstractItemView *v = static_cast<QAbstractItemView*>(obj);

            v->parentWidget()->move(v->parentWidget()->x(), v->parentWidget()->pos().y()-v->height());
        }

        return QObject::eventFilter(obj, event);
    }
};

#endif // MYEVENTFILTER_H

实现:

QComboBox *b = new QComboBox();

QStringList s = QStringList()<<"a"<<"b"<<"c";
b->insertItems(0,s);

b->setMinimumSize(200,40);
b->show();

myEventFilter *filter = new myEventFilter();
b->view()->installEventFilter(filter);

这是结果:

pop up


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接