On Qt, how to change the icon of an action in the toolbar at runtime?

Marc SJ picture Marc SJ · Oct 3, 2012 · Viewed 8.4k times · Source

In a program which calculates abritary precision numbers. I have an action on the taskbar.

QAction* button_stop_continue.

I've set the icon green icon in the beginning of the program, when calculations are being executed it should turn red and so on.

I've already tried something like this:

connect(this, SIGNAL(startedComputing()), this, SLOT(turnIconRed()));
connect(this, SIGNAL(finishedComputing()), this, SLOT(turnIconGreen()));

the function turnIconRed is looking similar to this:

void turnIconRed()
{
    button_stop_continue->setIcon(QIcon("images/red-light.png"));
}

I've come up with some incredibly-ugly algorithms :S. Isn't there a straight-forward way to deal with that on Qt? Any ideas?

Thanks.

Answer

tomvodi picture tomvodi · Oct 3, 2012

I would subclass QAction and add some logic for the states in which it can be. It is never a good idea to hardcode the color of something into the name of a method. By subclassing QAction, the look and feel of it is encapsulated.

This could be something like this:

Header file:

class StateAction : public QAction
{
    Q_OBJECT
public:
    explicit StateAction(QObject *parent = 0);

public slots:
    void start();
    void stop();
    void pause();
};

Implementation file:

StateAction::StateAction(QObject *parent) :
    QAction(parent)
{
    this->stop();
}

void StateAction::start()
{
    this->setIcon(QIcon(":/states/start.png"));
}

void StateAction::stop()
{
    this->setIcon(QIcon(":/states/stop.png"));
}

void StateAction::pause()
{
    this->setIcon(QIcon(":/states/pause.png"));
}

Now, in your MainWindow you can use that custom QAction simply by connecting its slots to the right signals:

Header file:

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

signals:
    void startedComputing();
    void finishedComputing();
    void pausedComputing();

private:
    void createActions();
    void createToolbars();
    void createConnections();
    StateAction *m_stateAction;
};

Implementation file:

...

void MainWindow::createConnections()
{
    connect(this, SIGNAL(startedComputing()), m_stateAction, SLOT(start()));
    connect(this, SIGNAL(finishedComputing()), m_stateAction, SLOT(stop()));
    connect(this, SIGNAL(pausedComputing()), m_stateAction, SLOT(pause()));
}