Auf dieser Seite

Beispiel: Taschenrechner

Das Beispiel zeigt, wie man mithilfe von Signalen und Slots die Funktionalität eines Taschenrechner-Widgets implementiert und wie man mit „ QGridLayout “ untergeordnete Widgets in einem Raster anordnet.

Einfache Taschenrechner-Anwendung

Screenshot des Taschenrechner-Beispiels

Das Beispiel besteht aus zwei Klassen:

  • Calculator ist das Rechner-Widget mit der gesamten Rechnerfunktionalität.
  • Button ist das Widget, das für jede der Rechner-Schaltflächen verwendet wird. Es leitet sich von ` QToolButton` ab.

Wir beginnen mit einer Wiederholung von „ Calculator “ und werfen anschließend einen Blick auf „ Button “.

Definition der Klasse „Calculator“

class Calculator : public QWidget
{
    Q_OBJECT

public:
    Calculator(QWidget *parent = nullptr);

private slots:
    void digitClicked();
    void unaryOperatorClicked();
    void additiveOperatorClicked();
    void multiplicativeOperatorClicked();
    void equalClicked();
    void pointClicked();
    void changeSignClicked();
    void backspaceClicked();
    void clear();
    void clearAll();
    void clearMemory();
    void readMemory();
    void setMemory();
    void addToMemory();

Die Klasse „ Calculator “ stellt ein einfaches Taschenrechner-Widget bereit. Sie erbt von „ QDialog “ und verfügt über mehrere private Slots, die den Tasten des Taschenrechners zugeordnet sind. „ QObject::eventFilter()“ wird neu implementiert, um Mausereignisse auf dem Display des Taschenrechners zu verarbeiten.

Die Tasten sind entsprechend ihres Verhaltens in Kategorien gruppiert. Beispielsweise fügen alle Zifferntasten (mit den Bezeichnungen „ 0 “ bis „ 9 “) eine Ziffer an den aktuellen Operanden an. Für diese verbinden wir mehrere Tasten mit demselben Slot (z. B. „ digitClicked() “). Die Kategorien sind Ziffern, unäre Operatoren (Sqrt, x², 1/x), additive Operatoren (+, -) und multiplikative Operatoren (×, ÷). Die übrigen Schaltflächen verfügen über eigene Slots.

private:
    template<typename PointerToMemberFunction>
    Button *createButton(const QString &text, const PointerToMemberFunction &member);
    void abortOperation();
    bool calculate(double rightOperand, const QString &pendingOperator);

Die private Funktion „ createButton() “ wird im Rahmen der Widget-Erstellung verwendet. „ abortOperation() “ wird immer dann aufgerufen, wenn eine Division durch Null auftritt oder wenn eine Quadratwurzeloperation auf eine negative Zahl angewendet wird. „ calculate() “ wendet einen binären Operator an (+, -, × oder ÷).

    double sumInMemory;
    double sumSoFar;
    double factorSoFar;
    QString pendingAdditiveOperator;
    QString pendingMultiplicativeOperator;
    bool waitingForOperand;

Diese Variablen kodieren zusammen mit dem Inhalt des Taschenrechner-Displays (ein „ QLineEdit “) den Zustand des Taschenrechners:

  • sumInMemory enthält den im Speicher des Taschenrechners gespeicherten Wert (unter Verwendung von MS, M+ oder MC).
  • sumSoFar speichert den bisher akkumulierten Wert. Wenn der Benutzer auf „ = “ klickt, wird „ sumSoFar “ neu berechnet und auf dem Display angezeigt. „ Clear All “ setzt „ sumSoFar “ auf Null zurück.
  • factorSoFar speichert bei Multiplikationen und Divisionen einen temporären Wert.
  • pendingAdditiveOperator speichert den letzten vom Benutzer angeklickten Additionsoperator.
  • pendingMultiplicativeOperator Speichert das zuletzt vom Benutzer angeklickte Multiplikationszeichen.
  • waitingForOperand ist „ true “, wenn der Taschenrechner erwartet, dass der Benutzer mit der Eingabe eines Operanden beginnt.

Additions- und Multiplikationsoperatoren werden unterschiedlich behandelt, da sie unterschiedliche Prioritäten haben. Beispielsweise wird „ 1 + 2 ÷ 3 “ als „ 1 + (2 ÷ 3) “ interpretiert, da „ ÷ “ eine höhere Priorität hat als „ + “.

Die folgende Tabelle zeigt die Entwicklung des Rechnerzustands, während der Benutzer einen mathematischen Ausdruck eingibt.

BenutzereingabeAnzeigeBisherige SummeAdd. Op.Bisheriger FaktorMultiplikationsoperationWarten auf Operanden?
00true
110false
1 +11+true
1 + 221+false
1 + 2 ÷21+2÷true
1 + 2 ÷ 331+2÷false
1 + 2 ÷ 3 -1,666671,66667-true
1 + 2 ÷ 3 - 441,66667-false
1 + 2 ÷ 3 - 4 =-2,333330true

Unäre Operatoren wie Sqrt erfordern keine besondere Behandlung; sie können sofort angewendet werden, da der Operand bereits bekannt ist, wenn die Operator-Schaltfläche angeklickt wird.

    QLineEdit *display;

    enum { NumDigitButtons = 10 };
    Button *digitButtons[NumDigitButtons];
};

Abschließend deklarieren wir die Variablen, die mit der Anzeige und den Schaltflächen zur Darstellung von Zahlen in Verbindung stehen.

Implementierung der Klasse „Calculator“

Calculator::Calculator(QWidget *parent)
    : QWidget(parent), sumInMemory(0.0), sumSoFar(0.0)
    , factorSoFar(0.0), waitingForOperand(true)
{

Im Konstruktor initialisieren wir den Zustand des Rechners. Die Variablen ` pendingAdditiveOperator ` und ` pendingMultiplicativeOperator ` müssen nicht explizit initialisiert werden, da der Konstruktor von ` QString ` sie auf leere Zeichenketten setzt. Es ist auch möglich, diese Variablen direkt im Header zu initialisieren. Dies wird als „ member-initializaton “ bezeichnet und vermeidet eine lange Initialisierungsliste.

    display = new QLineEdit("0");
    display->setReadOnly(true);
    display->setAlignment(Qt::AlignRight);
    display->setMaxLength(15);

    QFont font = display->font();
    font.setPointSize(font.pointSize() + 8);
    display->setFont(font);

Wir erstellen das ` QLineEdit `, das das Display des Taschenrechners darstellt, und legen einige seiner Eigenschaften fest. Insbesondere legen wir fest, dass es schreibgeschützt ist.

Außerdem vergrößern wir die Schriftart von „ display “ um 8 Punkte.

    for (int i = 0; i < NumDigitButtons; ++i)
        digitButtons[i] = createButton(QString::number(i), &Calculator::digitClicked);

    Button *pointButton = createButton(tr("."), &Calculator::pointClicked);
    Button *changeSignButton = createButton(tr("\302\261"), &Calculator::changeSignClicked);

    Button *backspaceButton = createButton(tr("Backspace"), &Calculator::backspaceClicked);
    Button *clearButton = createButton(tr("Clear"), &Calculator::clear);
    Button *clearAllButton = createButton(tr("Clear All"), &Calculator::clearAll);

    Button *clearMemoryButton = createButton(tr("MC"), &Calculator::clearMemory);
    Button *readMemoryButton = createButton(tr("MR"), &Calculator::readMemory);
    Button *setMemoryButton = createButton(tr("MS"), &Calculator::setMemory);
    Button *addToMemoryButton = createButton(tr("M+"), &Calculator::addToMemory);

    Button *divisionButton = createButton(tr("\303\267"), &Calculator::multiplicativeOperatorClicked);
    Button *timesButton = createButton(tr("\303\227"), &Calculator::multiplicativeOperatorClicked);
    Button *minusButton = createButton(tr("-"), &Calculator::additiveOperatorClicked);
    Button *plusButton = createButton(tr("+"), &Calculator::additiveOperatorClicked);

    Button *squareRootButton = createButton(tr("Sqrt"), &Calculator::unaryOperatorClicked);
    Button *powerButton = createButton(tr("x\302\262"), &Calculator::unaryOperatorClicked);
    Button *reciprocalButton = createButton(tr("1/x"), &Calculator::unaryOperatorClicked);
    Button *equalButton = createButton(tr("="), &Calculator::equalClicked);

Für jede Schaltfläche rufen wir die private Funktion ` createButton() ` mit der entsprechenden Textbeschriftung und einem Slot auf, um die Verbindung zur Schaltfläche herzustellen.

    QGridLayout *mainLayout = new QGridLayout;
    mainLayout->setSizeConstraint(QLayout::SetFixedSize);
    mainLayout->addWidget(display, 0, 0, 1, 6);
    mainLayout->addWidget(backspaceButton, 1, 0, 1, 2);
    mainLayout->addWidget(clearButton, 1, 2, 1, 2);
    mainLayout->addWidget(clearAllButton, 1, 4, 1, 2);

    mainLayout->addWidget(clearMemoryButton, 2, 0);
    mainLayout->addWidget(readMemoryButton, 3, 0);
    mainLayout->addWidget(setMemoryButton, 4, 0);
    mainLayout->addWidget(addToMemoryButton, 5, 0);

    for (int i = 1; i < NumDigitButtons; ++i) {
        int row = ((9 - i) / 3) + 2;
        int column = ((i - 1) % 3) + 1;
        mainLayout->addWidget(digitButtons[i], row, column);
    }

    mainLayout->addWidget(digitButtons[0], 5, 1);
    mainLayout->addWidget(pointButton, 5, 2);
    mainLayout->addWidget(changeSignButton, 5, 3);

    mainLayout->addWidget(divisionButton, 2, 4);
    mainLayout->addWidget(timesButton, 3, 4);
    mainLayout->addWidget(minusButton, 4, 4);
    mainLayout->addWidget(plusButton, 5, 4);

    mainLayout->addWidget(squareRootButton, 2, 5);
    mainLayout->addWidget(powerButton, 3, 5);
    mainLayout->addWidget(reciprocalButton, 4, 5);
    mainLayout->addWidget(equalButton, 5, 5);
    setLayout(mainLayout);

    setWindowTitle(tr("Calculator"));
}

Das Layout wird von einem einzigen ` QGridLayout` verwaltet. Der Aufruf von ` QLayout::setSizeConstraint()` stellt sicher, dass das Widget ` Calculator ` stets in seiner optimalen Größe (seiner ` size hint`) angezeigt wird, wodurch verhindert wird, dass der Benutzer die Größe des Rechners ändern kann. Der Größenhinweis wird durch die Größe und die ` size policy ` der untergeordneten Widgets bestimmt.

Die meisten untergeordneten Widgets belegen nur eine Zelle im Rasterlayout. Für diese müssen wir lediglich eine Zeile und eine Spalte an ` QGridLayout::addWidget()` übergeben. Die Widgets ` display`, ` backspaceButton`, ` clearButton` und ` clearAllButton ` belegen mehr als eine Spalte; für diese müssen wir zusätzlich eine Zeilen- und eine Spaltenausdehnung angeben.

void Calculator::digitClicked()
{
    Button *clickedButton = qobject_cast<Button *>(sender());
    int digitValue = clickedButton->text().toInt();
    if (display->text() == "0" && digitValue == 0.0)
        return;

    if (waitingForOperand) {
        display->clear();
        waitingForOperand = false;
    }
    display->setText(display->text() + QString::number(digitValue));
}

Das Drücken einer der Zifferntasten des Taschenrechners löst das Signal „ clicked()“ der Taste aus, wodurch der Slot „ digitClicked() “ ausgelöst wird.

Zunächst ermitteln wir mithilfe von ` QObject::sender()` (), welche Taste das Signal gesendet hat. Diese Funktion gibt den Absender als ` QObject `-Zeiger zurück. Da wir wissen, dass der Absender ein ` Button `-Objekt ist, können wir den ` QObject` sicher umwandeln. Wir hätten einen Cast im C-Stil oder einen C++- static_cast<>() verwenden können, aber als defensive Programmiertechnik nutzen wir einen ` qobject_cast()`. Der Vorteil besteht darin, dass bei einem Objekt mit falschem Typ ein Nullzeiger zurückgegeben wird. Abstürze aufgrund von Nullzeigern lassen sich viel einfacher diagnostizieren als Abstürze aufgrund unsicherer Typumwandlungen. Sobald wir die Schaltfläche haben, extrahieren wir den Operator mithilfe von ` QToolButton::text()`.

Der Slot muss insbesondere zwei Situationen berücksichtigen. Wenn „ display “ den Wert „0“ enthält und der Benutzer auf die Schaltfläche „ 0 “ klickt, wäre es unsinnig, „00“ anzuzeigen. Und wenn sich der Taschenrechner in einem Zustand befindet, in dem er auf einen neuen Operanden wartet, ist die neue Ziffer die erste Ziffer dieses neuen Operanden; in diesem Fall muss zunächst das Ergebnis einer vorherigen Berechnung gelöscht werden.

Am Ende fügen wir die neue Ziffer an den Wert in der Anzeige an.

void Calculator::unaryOperatorClicked()
{
    Button *clickedButton = qobject_cast<Button *>(sender());
    QString clickedOperator = clickedButton->text();
    double operand = display->text().toDouble();
    double result = 0.0;

    if (clickedOperator == tr("Sqrt")) {
        if (operand < 0.0) {
            abortOperation();
            return;
        }
        result = std::sqrt(operand);
    } else if (clickedOperator == tr("x\302\262")) {
        result = std::pow(operand, 2.0);
    } else if (clickedOperator == tr("1/x")) {
        if (operand == 0.0) {
            abortOperation();
            return;
        }
        result = 1.0 / operand;
    }
    display->setText(QString::number(result));
    waitingForOperand = true;
}

Der Slot „ unaryOperatorClicked() “ wird immer dann aufgerufen, wenn eine der Schaltflächen für unäre Operatoren angeklickt wird. Auch hier wird mithilfe von „ QObject::sender()“ ein Zeiger auf die angeklickte Schaltfläche abgerufen. Der Operator wird aus dem Text der Schaltfläche extrahiert und in „ clickedOperator “ gespeichert. Der Operand wird aus „ display “ abgerufen.

Anschließend führen wir die Operation durch. Wird „ Sqrt “ auf eine negative Zahl oder „ 1/x “ auf Null angewendet, rufen wir „ abortOperation() “ auf. Verläuft alles reibungslos, zeigen wir das Ergebnis der Operation im Zeilenbearbeitungsfeld an und setzen „ waitingForOperand “ auf „ true “. Dadurch wird sichergestellt, dass eine vom Benutzer eingegebene neue Ziffer als neuer Operand betrachtet wird, anstatt an den aktuellen Wert angehängt zu werden.

void Calculator::additiveOperatorClicked()
{
    Button *clickedButton = qobject_cast<Button *>(sender());
    if (!clickedButton)
      return;
    QString clickedOperator = clickedButton->text();
    double operand = display->text().toDouble();

Der Slot „ additiveOperatorClicked() “ wird aufgerufen, wenn der Benutzer auf die Schaltfläche „ + “ oder „ - “ klickt.

Bevor wir tatsächlich etwas mit dem angeklickten Operator tun können, müssen wir alle noch ausstehenden Operationen abwickeln. Wir beginnen mit den multiplikativen Operatoren, da diese eine höhere Priorität haben als additive Operatoren:

    if (!pendingMultiplicativeOperator.isEmpty()) {
        if (!calculate(operand, pendingMultiplicativeOperator)) {
            abortOperation();
            return;
        }
        display->setText(QString::number(factorSoFar));
        operand = factorSoFar;
        factorSoFar = 0.0;
        pendingMultiplicativeOperator.clear();
    }

Wenn zuvor auf „ × “ oder „ ÷ “ geklickt wurde, ohne anschließend auf „ = “ zu klicken, ist der aktuelle Wert in der Anzeige der rechte Operand des Operators „ × “ oder „ ÷ “, und wir können die Operation schließlich ausführen und die Anzeige aktualisieren.

    if (!pendingAdditiveOperator.isEmpty()) {
        if (!calculate(operand, pendingAdditiveOperator)) {
            abortOperation();
            return;
        }
        display->setText(QString::number(sumSoFar));
    } else {
        sumSoFar = operand;
    }

Wurde zuvor auf „ + “ oder „ - “ geklickt, ist „ sumSoFar “ der linke Operand und der aktuelle Wert in der Anzeige der rechte Operand des Operators. Ist kein additiver Operator in der Warteschlange, wird „ sumSoFar “ einfach auf den Text in der Anzeige gesetzt.

    pendingAdditiveOperator = clickedOperator;
    waitingForOperand = true;
}

Schließlich können wir uns um den gerade angeklickten Operator kümmern. Da wir noch keinen rechten Operanden haben, speichern wir den angeklickten Operator in der Variablen „ pendingAdditiveOperator “. Wir werden die Operation später anwenden, sobald wir einen rechten Operanden haben, wobei „ sumSoFar “ als linker Operand dient.

void Calculator::multiplicativeOperatorClicked()
{
    Button *clickedButton = qobject_cast<Button *>(sender());
    if (!clickedButton)
      return;
    QString clickedOperator = clickedButton->text();
    double operand = display->text().toDouble();

    if (!pendingMultiplicativeOperator.isEmpty()) {
        if (!calculate(operand, pendingMultiplicativeOperator)) {
            abortOperation();
            return;
        }
        display->setText(QString::number(factorSoFar));
    } else {
        factorSoFar = operand;
    }

    pendingMultiplicativeOperator = clickedOperator;
    waitingForOperand = true;
}

Der Slot „ multiplicativeOperatorClicked() “ ähnelt dem von „ additiveOperatorClicked() “. Wir müssen uns hier keine Gedanken über ausstehende Additionsoperatoren machen, da Multiplikationsoperatoren Vorrang vor Additionsoperatoren haben.

void Calculator::equalClicked()
{
    double operand = display->text().toDouble();

    if (!pendingMultiplicativeOperator.isEmpty()) {
        if (!calculate(operand, pendingMultiplicativeOperator)) {
            abortOperation();
            return;
        }
        operand = factorSoFar;
        factorSoFar = 0.0;
        pendingMultiplicativeOperator.clear();
    }
    if (!pendingAdditiveOperator.isEmpty()) {
        if (!calculate(operand, pendingAdditiveOperator)) {
            abortOperation();
            return;
        }
        pendingAdditiveOperator.clear();
    } else {
        sumSoFar = operand;
    }

    display->setText(QString::number(sumSoFar));
    sumSoFar = 0.0;
    waitingForOperand = true;
}

Wie bei „ additiveOperatorClicked() “ beginnen wir damit, alle ausstehenden multiplikativen und additiven Operatoren zu verarbeiten. Anschließend zeigen wir „ sumSoFar “ an und setzen die Variable auf Null zurück. Das Zurücksetzen der Variablen auf Null ist notwendig, um eine doppelte Zählung des Werts zu vermeiden.

void Calculator::pointClicked()
{
    if (waitingForOperand)
        display->setText("0");
    if (!display->text().contains('.'))
        display->setText(display->text() + tr("."));
    waitingForOperand = false;
}

Der Slot „ pointClicked() “ fügt dem Inhalt von „ display “ einen Dezimalpunkt hinzu.

void Calculator::changeSignClicked()
{
    QString text = display->text();
    double value = text.toDouble();

    if (value > 0.0) {
        text.prepend(tr("-"));
    } else if (value < 0.0) {
        text.remove(0, 1);
    }
    display->setText(text);
}

Der Slot „ changeSignClicked() “ ändert das Vorzeichen des Werts in „ display “. Ist der aktuelle Wert positiv, wird ein Minuszeichen vorangestellt; ist der aktuelle Wert negativ, wird das erste Zeichen des Werts (das Minuszeichen) entfernt.

void Calculator::backspaceClicked()
{
    if (waitingForOperand)
        return;

    QString text = display->text();
    text.chop(1);
    if (text.isEmpty()) {
        text = "0";
        waitingForOperand = true;
    }
    display->setText(text);
}

Der Slot „ backspaceClicked() “ entfernt das Zeichen ganz rechts in der Anzeige. Wenn wir eine leere Zeichenkette erhalten, zeigen wir „0“ an und setzen „ waitingForOperand “ auf „ true “.

void Calculator::clear()
{
    if (waitingForOperand)
        return;

    display->setText("0");
    waitingForOperand = true;
}

Der Slot „ clear() “ setzt den aktuellen Operanden auf Null zurück. Dies entspricht dem wiederholten Klicken auf „ Backspace “, bis der gesamte Operand gelöscht ist.

void Calculator::clearAll()
{
    sumSoFar = 0.0;
    factorSoFar = 0.0;
    pendingAdditiveOperator.clear();
    pendingMultiplicativeOperator.clear();
    display->setText("0");
    waitingForOperand = true;
}

Der Slot „ clearAll() “ setzt den Taschenrechner in seinen Ausgangszustand zurück.

void Calculator::clearMemory()
{
    sumInMemory = 0.0;
}

void Calculator::readMemory()
{
    display->setText(QString::number(sumInMemory));
    waitingForOperand = true;
}

void Calculator::setMemory()
{
    equalClicked();
    sumInMemory = display->text().toDouble();
}

void Calculator::addToMemory()
{
    equalClicked();
    sumInMemory += display->text().toDouble();
}

Der Slot „ clearMemory() “ löscht die im Speicher befindliche Summe, „ readMemory() “ zeigt die Summe als Operand an, „ setMemory() “ ersetzt die Summe im Speicher durch die aktuelle Summe und „ addToMemory() “ addiert den aktuellen Wert zum Wert im Speicher. Für „ setMemory() “ und „ addToMemory() “ rufen wir zunächst „ equalClicked() “ auf, um „ sumSoFar “ und den Wert in der Anzeige zu aktualisieren.

template<typename PointerToMemberFunction>
Button *Calculator::createButton(const QString &text, const PointerToMemberFunction &member)
{
    Button *button = new Button(text);
    connect(button, &Button::clicked, this, member);
    return button;
}

Die private Funktion „ createButton() “ wird vom Konstruktor aus aufgerufen, um die Tasten des Taschenrechners zu erstellen.

void Calculator::abortOperation()
{
    clearAll();
    display->setText(tr("####"));
}

Die private Funktion ` abortOperation() ` wird immer dann aufgerufen, wenn eine Berechnung fehlschlägt. Sie setzt den Zustand des Taschenrechners zurück und zeigt „####“ an.

bool Calculator::calculate(double rightOperand, const QString &pendingOperator)
{
    if (pendingOperator == tr("+")) {
        sumSoFar += rightOperand;
    } else if (pendingOperator == tr("-")) {
        sumSoFar -= rightOperand;
    } else if (pendingOperator == tr("\303\227")) {
        factorSoFar *= rightOperand;
    } else if (pendingOperator == tr("\303\267")) {
        if (rightOperand == 0.0)
            return false;
        factorSoFar /= rightOperand;
    }
    return true;
}

Die private Funktion ` calculate() ` führt eine binäre Operation durch. Der rechte Operand wird durch ` rightOperand` angegeben. Bei additiven Operatoren ist der linke Operand ` sumSoFar`; bei multiplikativen Operatoren ist der linke Operand ` factorSoFar`. Die Funktion gibt ` false ` zurück, wenn eine Division durch Null auftritt.

Definition der Klasse „Button“

Werfen wir nun einen Blick auf die Klasse „ Button “:

class Button : public QToolButton
{
    Q_OBJECT

public:
    explicit Button(const QString &text, QWidget *parent = nullptr);

    QSize sizeHint() const override;
};

Die Klasse „ Button “ verfügt über einen Komfortkonstruktor, der eine Textbeschriftung und ein übergeordnetes Widget entgegennimmt, und sie implementiert die Methode „ QWidget::sizeHint()“ neu, um mehr Platz um den Text herum bereitzustellen, als die Methode „ QToolButton “ normalerweise vorsieht.

Implementierung der Button-Klasse

Button::Button(const QString &text, QWidget *parent)
    : QToolButton(parent)
{
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
    setText(text);
}

Das Erscheinungsbild der Schaltflächen wird durch das Layout des Taschenrechner-Widgets über die Größe und die ` size policy ` der untergeordneten Widgets des Layouts bestimmt. Der Aufruf der Funktion ` setSizePolicy()` im Konstruktor stellt sicher, dass sich die Schaltfläche horizontal ausdehnt, um den gesamten verfügbaren Platz auszufüllen; standardmäßig dehnen sich ` QToolButton` nicht aus, um den verfügbaren Platz auszufüllen. Ohne diesen Aufruf hätten die verschiedenen Schaltflächen in derselben Spalte unterschiedliche Breiten.

QSize Button::sizeHint() const
{
    QSize size = QToolButton::sizeHint();
    size.rheight() += 20;
    size.rwidth() = qMax(size.width(), size.height());
    return size;
}

In ` sizeHint()` versuchen wir, eine Größe zurückzugeben, die für die meisten Schaltflächen gut aussieht. Wir verwenden den Größenhinweis der Basisklasse (`QToolButton`) wieder, passen ihn jedoch wie folgt an:

  • Wir addieren 20 zur „ height “-Komponente des Größenhinweises.
  • Wir stellen sicher, dass die „ width “-Komponente des Größenhinweises mindestens so groß ist wie die „ height “-Komponente.

Dadurch wird sichergestellt, dass bei den meisten Schriftarten die Ziffern- und Operator-Schaltflächen quadratisch sind, ohne dass der Text auf den Schaltflächen „ Backspace “, „ Clear “ und „ Clear All “ abgeschnitten wird.

Der folgende Screenshot zeigt, wie das Widget „ Calculator “ aussehen würde, wenn wir die horizontale Größenrichtlinie im Konstruktor nicht auf „ QSizePolicy::Expanding “ setzen und die Methode „ QWidget::sizeHint()“ nicht neu implementieren würden.

Taschenrechner mit falsch angeordneten Tasten

Das „Calculator“-Beispiel mit Standard-Größenrichtlinien und Größenhinweisen

Beispielprojekt @ code.qt.io

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.