[Interest] Can't get menu with QWidgetAction to close after click! (Mac OS 10.6.8, Qt 4.8.3)

Jim Prouty jim at wavemetrics.com
Tue Oct 9 20:29:08 CEST 2012


In this test program (Qt 4.8.3 on Mac OS X 10.6.8), I've got one QMenu added to the menubar, and the menu has several QWidgetActions, including one that has a Done QPushButton and a QSpinBox.

Having connected the QPushButton to a slot, I'm trying to get the menu to close up after the button has been clicked(), but the menu resolutely stays visible:

-------------- next part --------------
A non-text attachment was scrubbed...
Name: PastedGraphic-1.png
Type: image/png
Size: 26927 bytes
Desc: not available
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20121009/75fc4c39/attachment.png>
-------------- next part --------------


Based on Google search results, I've programmed my _onPushButton() slot to call QMenu::close() on the added menu.

I've tried using a queued connection hoping to do an end run around the event handling, but neither direct nor queued connections succeed in closing the menu.

I've checked that the slot is getting called (qDebug() is printing).

What am I doing wrong here?

(And yes, I see that there are other menu issues with the program; Qt for Mac seems a bit neglected.)

main.cpp:

#include <QApplication>
#include <QLabel>
#include <QMainWindow>
#include <QMenu>
#include <QMenuBar>
#include <QDebug>
#include <QWidgetAction>
#include <QPushButton>
#include <QSpinBox>
#include <QLayout>
#include <QLabel>

class SpinBoxAction : public QWidgetAction
{
    Q_OBJECT
public:
    explicit SpinBoxAction(const QString& title, QWidget *parent = 0);

    virtual QSize minimumSizeHint () const { return QSize(300,35); }

protected:
    virtual QWidget * createWidget ( QWidget * parent );
    virtual void deleteWidget ( QWidget * widget );
private:
    QString pStr;
    QWidget * pWidget;
};

SpinBoxAction::SpinBoxAction(const QString& title, QWidget *parent)
     : QWidgetAction(parent),
       pStr(title), pWidget(NULL)
{

}

QWidget* SpinBoxAction::createWidget(QWidget *parent)
{
    if( pWidget == NULL ) {
        QWidget * widget = new QWidget (parent);
        widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
        widget->setObjectName(QLatin1String("parentOfButtonAndSpinBox"));

        QSpinBox * spinBox = new QSpinBox(NULL);
        spinBox->setObjectName(QLatin1String("spinbox"));
        spinBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);

        spinBox->setMinimumSize(200,20);

        QPushButton * button = new QPushButton(pStr);
        button->setObjectName(QLatin1String("button"));

        QHBoxLayout * layout = new QHBoxLayout();
        layout->setObjectName(QLatin1String("horizontal layout"));

        layout->addWidget (button);
        layout->addWidget (spinBox);

        widget->setLayout (layout);
        pWidget= widget;
    }
    return pWidget;
}

void SpinBoxAction::deleteWidget(QWidget *widget)
{
    if( widget == pWidget )
        pWidget= NULL;
    QWidgetAction::deleteWidget(widget);
}

//#include "main.h"

class SpinApplication : public QApplication
{
    Q_OBJECT
public:
    explicit SpinApplication ( int & argc, char ** argv );
    QMenu * _menu;

public slots:
    void _onPushButton(bool b);
};

// main.cpp
SpinApplication::SpinApplication ( int & argc, char ** argv ) : QApplication(argc, argv), _menu(NULL)
{

}

 void SpinApplication::_onPushButton(bool b)
 {
     Q_UNUSED(b);
     if(_menu) {
         //_menu->hide(); // doesn't help
         bool closed= _menu->close();	// doesn't close the menu.
         qDebug() << "Closed:" << closed;
      }
 }

int main( int argc, char* argv[])
{
    SpinApplication app(argc, argv);

    QMenu * menu= new QMenu("TEST");
    app._menu = menu;

    // Widget Action 1
    QLabel* lbl = new QLabel( "-----------TEST LABEL------------" );
    lbl->setObjectName(QLatin1String("test label"));

    QWidgetAction* wAction = new QWidgetAction( menu );
    wAction->setDefaultWidget( lbl );
    wAction->setObjectName(QLatin1String("test label widget action"));

    menu->addAction( wAction );

    // Widget Action 2
    QLabel* lbl2 = new QLabel( "TEST LABEL 2" );
    lbl2->setObjectName(QLatin1String("test label 2"));

    QWidgetAction* wAction2 = new QWidgetAction( menu );
    wAction2->setDefaultWidget( lbl2 );
    wAction2->setObjectName(QLatin1String("test label 2 widget action"));

    menu->addAction( wAction2 );

    // Widget Action 3
    SpinBoxAction * spinBoxAction = new SpinBoxAction(QLatin1String("Done"),menu);
    menu->addAction( spinBoxAction );

    if( QWidget *widget= spinBoxAction->requestWidget(menu) ) {
        if( QPushButton *button = widget->findChild<QPushButton *>() ) {
            QObject::connect(button, SIGNAL(clicked(bool)), &app, SLOT(_onPushButton(bool)), Qt::QueuedConnection);
        }
    }

    // normal action
    QAction *naction= new QAction(QLatin1String("Normal menu item"), menu);
    naction->setObjectName(QLatin1String("naction"));
    menu->addAction( naction );

    QMainWindow* w = new QMainWindow();
    w->menuBar()->addMenu( menu );
    w->show();

    app.exec();
}

#include "main.moc"


========================================================================

Jim "How does it work?" Prouty

Voice: (503) 620-3001, FAX: (503) 620-6754
Makers of IGOR Pro, scientific data analysis and graphing for Mac and PC
http://www.wavemetrics.com



More information about the Interest mailing list