Extending QAction by emitting additional Signals/de: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
 
(One intermediate revision by the same user not shown)
Line 1: Line 1:
[[Category:HowTo]]
[[Category:HowTo]]
[[Category:snippets]]
{{DISPLAYTITLE:Erweitern von QAction durch zusätzliche Signale}}
[[Category:German]]
== Einführung ==
 
QAction kann so konfiguriert werden, dass es ''checkable'' ist. Dies bedeutet, es kann einen binären Zustand, nämlich ''angewählt'' (''checked'') und ''nicht angewählt'' annehmen. Dies wird bspw. bei einem Pushbutton angezeigt, der runtergedrückt bleibt, nachdem man ihn einmal geklickt hat und erst wieder in den Ausgangszustand zurückkehrt, nachdem man ihn noch ein weiteres mal anklickt.
'''Deutsch''' | [[ActionEmittingCheckedUncheckedSignals|English]]
 
= Wie man eine Klasse von QAction ableitet, sodass sie Checked/Unchecked-Signale sendet =
 
QAction kann so konfiguriert werden, dass es ''checkable'' ist. Dies bedeutet, es kann einen binären Zustand, nämlich ''angewählt'' (''checked'') und ''nicht_angewählt'' annehmen. Dies wird bspw. bei einem Pushbutton angezeigt, der runtergedrückt bleibt, nachdem man ihn einmal geklickt hat und erst wieder in den Ausgangszustand zurückkehrt, nachdem man ihn noch ein weiteres mal angeklickt hat.


Das Problem mit QAction ist, dass es nur ein Signal sendet, wenn sich sein ''checked''-Zustand geändert hat und in diesem Signal mit einem boolschen Attribut mitteilt, ob der Zustand nun ''checked'' ist oder nicht. Das bedeutet, wenn man eine Slot-Methode schreibt, die auf dieses Signal reagiert, muss man in diesem Slot erst gucken, wie der Zustand der QAction jetzt ist und dann kann man erst, basierend auf dieser Fallentscheidung, die gewünschte Funktion ausführen.
Das Problem mit QAction ist, dass es nur ein Signal sendet, wenn sich sein ''checked''-Zustand geändert hat und in diesem Signal mit einem boolschen Attribut mitteilt, ob der Zustand nun ''checked'' ist oder nicht. Das bedeutet, wenn man eine Slot-Methode schreibt, die auf dieses Signal reagiert, muss man in diesem Slot erst gucken, wie der Zustand der QAction jetzt ist und dann kann man erst, basierend auf dieser Fallentscheidung, die gewünschte Funktion ausführen.
Line 16: Line 11:
Der Quelltext ist wirklich einfach. Dies ist die Header-Datei:
Der Quelltext ist wirklich einfach. Dies ist die Header-Datei:


<code>#ifndef CHECKABLEACTION_H
<code>
#ifndef CHECKABLEACTION_H
#define CHECKABLEACTION_H
#define CHECKABLEACTION_H


Line 30: Line 26:
{
{
  Q_OBJECT
  Q_OBJECT
public:
public:
explicit CheckableAction(QObject '''parent = 0);
  explicit CheckableAction(QObject *parent = 0);
 
signals:
 
/*!
* This signal is emitted each time the action is
* checked.
*/
void actionChecked();
 
/*!
* This signal is emitted each time the action is
* unchecked.
*/
void actionUnchecked();
 
 


public slots:
signals:
  /*!
  * This signal is emitted each time the action is
  * checked.
  */
  void actionChecked();


  /*!
  * This signal is emitted each time the action is
  * unchecked.
  */
  void actionUnchecked();


private slots:
public slots:
 
/*!
* This slot is used to forward (i.e., emit) a triggered
* event depending on the status of the action (i.e., if it
* has been checked or not).
* checked true if the action has been checked, false
* otherwise
*/
void slotForwardCheckSignal( bool checked );


private slots:
  /*!
  * This slot is used to forward (i.e., emit) a triggered
  * event depending on the status of the action (i.e., if it
  * has been checked or not).
  * checked true if the action has been checked, false
  * otherwise
  */
  void slotForwardCheckSignal( bool checked );
};
};


Line 68: Line 58:
</code>
</code>


Implementierung:


Und hier folgt nun die Implementierung der Klasse:
<code>
#include "checkableaction.h"


<code>#include "checkableaction.h"
CheckableAction::CheckableAction(QObject *parent) :
QAction(parent)
{


CheckableAction::CheckableAction(QObject '''parent) :
  // auto connect the triggered event to the slot for
QAction(parent)
  // forwarding the check status
{
  connect( this, SIGNAL(triggered(bool)),
// auto connect the triggered event to the slot for
          this, SLOT(slotForwardCheckSignal(bool))
// forwarding the check status
  );
connect( this,
SIGNAL (triggered(bool)),
this,
SLOT (slotForwardCheckSignal(bool)) );
}
}


Line 87: Line 77:
{
{
  qDebug() << "Action checked status " << checked;
  qDebug() << "Action checked status " << checked;
  // check the status of the action
  // check the status of the action
  if( ! isCheckable() )
  if( ! isCheckable() ) {
// the action cannot be checked, simply emit
  // the action cannot be checked, simply emit
// a triggered event
  // a triggered event
triggered();
  triggered();
  else
  } else
  if( isChecked() )
  if( isChecked() ) {
// the action is checked
  // the action is checked
emit actionChecked();
  emit actionChecked();
  else
}
// the action is unchecked
  else {
emit actionUnchecked();
  // the action is unchecked
 
  emit actionUnchecked();
}
}
}
</code>
</code>


== Beispiel zur Verwendung ==
== Beispiel zur Verwendung ==
The action can be used in the way a QAction is, for instance:
Die neue Klasse wird genauso benutzt, wie eine QAction, bloß dass uns jetzt die 2 neuen Signale <tt>actionChecked()</tt> und <tt>actionUnchecked()</tt> zur Verfügung stehen.
Die neue Klasse wird genauso benutzt, wie eine QAction, bloß dass uns jetzt die 2 neuen Signale <code>actionChecked()</code> und <code>actionUnchecked()</code> zur Verfügung stehen.


<code>
<code>
CheckableAction''' myAction = new CheckableAction( this );
CheckableAction *myAction = new CheckableAction( this );
myAction->setText( tr("Action TEXT") );
myAction->setText( tr("Action TEXT") );
myAction->setIcon( QIcon(":/actions/img/myaction.png") );
myAction->setIcon( QIcon(":/actions/img/myaction.png") );
myAction->setStatusTip( tr("Check/Uncheck the action") );
myAction->setStatusTip( tr("Check/Uncheck the action") );
myAction->setCheckable( true );
myAction->setCheckable( true );
connect( myAction,
 
SIGNAL (actionChecked()),
connect( myAction, SIGNAL(actionChecked()),
this,
            this, SLOT(slotActionUncheked())
SLOT( slotActionUncheked()) );
      );
connect( myAction,
SIGNAL (actionUnchecked()),
this,
SLOT (slotActionCheked()) );


connect( myAction, SIGNAL(actionUnchecked()),
            this, SLOT(slotActionCheked())
      );
</code>
</code>

Latest revision as of 23:37, 11 March 2015


Einführung

QAction kann so konfiguriert werden, dass es checkable ist. Dies bedeutet, es kann einen binären Zustand, nämlich angewählt (checked) und nicht angewählt annehmen. Dies wird bspw. bei einem Pushbutton angezeigt, der runtergedrückt bleibt, nachdem man ihn einmal geklickt hat und erst wieder in den Ausgangszustand zurückkehrt, nachdem man ihn noch ein weiteres mal anklickt.

Das Problem mit QAction ist, dass es nur ein Signal sendet, wenn sich sein checked-Zustand geändert hat und in diesem Signal mit einem boolschen Attribut mitteilt, ob der Zustand nun checked ist oder nicht. Das bedeutet, wenn man eine Slot-Methode schreibt, die auf dieses Signal reagiert, muss man in diesem Slot erst gucken, wie der Zustand der QAction jetzt ist und dann kann man erst, basierend auf dieser Fallentscheidung, die gewünschte Funktion ausführen.

Es oft praktischer, wenn man 2 getrennte Signale hätte: Eins für "der Zustand ist jetzt checked" und eins für "er ist jetzt nicht checked". Weil QAction solche Signale nicht hat, bauen wir uns hier eine von QAction abgeleitete Klasse, die QAction um eben diese Signale erweitert.

Quelltext

Der Quelltext ist wirklich einfach. Dies ist die Header-Datei:

#ifndef CHECKABLEACTION_H
#define CHECKABLEACTION_H

#include <QAction>
#include <QDebug>

/*!
 * This class represents an action that will emit
 * distinct signals depending on the check of the
 * action itself.
 */
class CheckableAction : public QAction
{
 Q_OBJECT
 public:
  explicit CheckableAction(QObject *parent = 0);

 signals:
  /*!
   * This signal is emitted each time the action is
   * checked.
   */
  void actionChecked();

  /*!
   * This signal is emitted each time the action is
   * unchecked.
   */
  void actionUnchecked();

 public slots:

 private slots:
  /*!
   * This slot is used to forward (i.e., emit) a triggered
   * event depending on the status of the action (i.e., if it
   * has been checked or not).
   * checked true if the action has been checked, false
   * otherwise
   */
  void slotForwardCheckSignal( bool checked );
};

#endif // CHECKABLEACTION_H

Implementierung:

#include "checkableaction.h"

CheckableAction::CheckableAction(QObject *parent) :
 QAction(parent)
 {

  // auto connect the triggered event to the slot for
  // forwarding the check status
  connect( this, SIGNAL(triggered(bool)),
           this, SLOT(slotForwardCheckSignal(bool))
  );
}

void CheckableAction::slotForwardCheckSignal(bool checked)
{
 qDebug() << "Action checked status " << checked;

 // check the status of the action
 if( ! isCheckable() ) {
  // the action cannot be checked, simply emit
  // a triggered event
  triggered();
 } else
 if( isChecked() ) {
  // the action is checked
  emit actionChecked();
 }
 else {
  // the action is unchecked
  emit actionUnchecked();
 }
}

Beispiel zur Verwendung

Die neue Klasse wird genauso benutzt, wie eine QAction, bloß dass uns jetzt die 2 neuen Signale actionChecked() und actionUnchecked() zur Verfügung stehen.

CheckableAction *myAction = new CheckableAction( this );
myAction->setText( tr("Action TEXT") );
myAction->setIcon( QIcon(":/actions/img/myaction.png") );
myAction->setStatusTip( tr("Check/Uncheck the action") );
myAction->setCheckable( true );

connect( myAction, SIGNAL(actionChecked()),
             this, SLOT(slotActionUncheked())
       );

connect( myAction, SIGNAL(actionUnchecked()),
             this, SLOT(slotActionCheked())
       );