Calqlatr
Eine Qt Quick App, die für Geräte im Hoch- und Querformat entwickelt wurde und benutzerdefinierte Komponenten, responsive Layouts und JavaScript für die Anwendungslogik verwendet.
Calqlatr demonstriert verschiedene QML- und Qt Quick Funktionen, wie z. B. die Anzeige von benutzerdefinierten Komponenten und die Verwendung von responsiven Layouts. Die Anwendungslogik ist in JavaScript und die Benutzeroberfläche in QML implementiert.
Ausführen des Beispiels
Zum Ausführen des Beispiels von Qt Creatorzu starten, öffnen Sie den Modus Welcome und wählen Sie das Beispiel unter Examples aus. Weitere Informationen finden Sie unter Erstellen und Ausführen eines Beispiels.
Anzeigen von benutzerdefinierten Komponenten
In der Calqlatr-Anwendung werden benutzerdefinierte Typen verwendet. Diese werden in einer separaten .qml-Datei definiert:
- BackspaceButton.qml
- RechnerSchaltfläche.qml
- Anzeige.qml
- NumberPad.qml
Um diese benutzerdefinierten Typen in Main.qml
zu verwenden, fügen Sie eine Importanweisung für den Ordner content
hinzu, in dem sich die Typen befinden:
import "content"
Der Typ NumberPad
wird zum Beispiel in Main.qml
verwendet, um den Nummernblock des Taschenrechners zu erstellen. Dieser ist in einem Item Typ verschachtelt, dem Basistyp für alle visuellen Elemente in Qt Quick:
NumberPad { id: numberPad; Layout.margins: root.margin }
Benutzerdefinierte Komponenten sind QML-Typen, die in jeder QML-Datei definiert werden können. Sie verhalten sich genauso wie die Komponenten, die in einer eigenen .qml-Datei definiert sind, wie NumberPad.qml
. In NumberPad.qml
sind die Komponente DigitButton
und die Komponente OperatorButton
definiert. In diesen Komponenten können neue Eigenschaften hinzugefügt oder bestehende Eigenschaften geändert werden. Hier wird der onReleased
Handler für die beiden benutzerdefinierten Komponenten überschrieben.
component DigitButton: CalculatorButton { onReleased: { root.digitPressed(text) updateDimmed() } } component OperatorButton: CalculatorButton { onReleased: { root.operatorPressed(text) updateDimmed() } textColor: controller.qtGreenColor implicitWidth: 48 dimmable: true }
Verwenden Sie außerdem den Typ CalculatorButton
für die verschiedenen Schaltflächen auf NumberPad
. CalculatorButton.qml
definiert grundlegende Eigenschaften einer Schaltfläche, die Sie für jede Instanz in NumberPad.qml
ändern. Für die Ziffern- und Operator-Schaltflächen werden einige zusätzliche Eigenschaften hinzugefügt, z. B. die Eigenschaften text
, width
und dimmable
. Verwenden Sie dimmable
, um Schaltflächen visuell zu deaktivieren (abgeblendet), wenn der Taschenrechner keine Eingaben von dieser Schaltfläche akzeptiert.
DigitButton { text: "e" dimmable: true implicitWidth: 48 }
Es gibt eine weitere Datei im Verzeichnis content
mit dem Namen BackSpaceButton.qml
. Dies ist ein Sonderfall von CalculatorButton
, bei dem wir ein Bild auf die Schaltfläche rendern möchten, anstatt Text zu verwenden. Diese Schaltfläche ist die gleiche wie eine OperatorButton
, enthält aber eine icon
anstelle von text
:
icon.source: getIcon() icon.width: 38 icon.height: 38 icon.color: getIconColor() // include this text property as the calculator engine // differentiates buttons through text. The text is never drawn. text: "bs" property bool dimmable: true property bool dimmed: false readonly property color backgroundColor: "#222222" readonly property color borderColor: "#A9A9A9" readonly property color backspaceRedColor: "#DE2C2C" readonly property int buttonRadius: 8 function getBackgroundColor() { if (button.dimmable && button.dimmed) return backgroundColor if (button.pressed) return backspaceRedColor return backgroundColor
Reaktionsfähige Layouts
In diesem Beispiel ordnen responsive Layouts die verschiedenen UI-Komponenten sowohl im Hoch- als auch im Querformat an. Sie können auch zwischen diesen beiden Modi hin- und herschalten. Sie können dies an Main.qml
erkennen, das ein ColumnLayout
für das Hochformat und ein RowLayout
für das Querformat definiert.
ColumnLayout { id: portraitMode anchors.fill: parent visible: true LayoutItemProxy { target: display Layout.minimumHeight: display.minHeight } LayoutItemProxy { target: numberPad Layout.alignment: Qt.AlignHCenter } } RowLayout { id: landscapeMode anchors.fill: parent visible: false LayoutItemProxy { target: display } LayoutItemProxy { target: numberPad Layout.alignment: Qt.AlignVCenter } }
ColumnLayout
steht für das Hochformat-Layout der Anwendung, RowLayout
für das Querformat-Layout. Die Eigenschaft visible
steuert, welches Layout zu einem bestimmten Zeitpunkt verwendet wird. Die Eigenschaft id
der Komponenten NumberPad
und Display
wird verwendet, um die Eigenschaft target
der Typen LayoutItemProxy
zu setzen. Auf diese Weise können beide Layouts die gleichen Inhaltselemente verwenden. Darüber hinaus können die Eigenschaften innerhalb des Elements LayoutItemProxy
an das Element target
selbst weitergeleitet werden. Wenn zum Beispiel NumberPad
instanziiert wird, benötigen beide Layouts ein anderes Layout.alignment
.
Das Umschalten zwischen den beiden Layouts erfolgt im Signalhandler für die Eigenschaft isPortraitMode
, indem ihre Sichtbarkeit eingestellt wird:
onIsPortraitModeChanged: { if (isPortraitMode) { portraitMode.visible = true landscapeMode.visible = false } else { portraitMode.visible = false landscapeMode.visible = true } }
Dies ist möglich, weil QML Signalhandler für alle selbst deklarierten Eigenschaften erstellt, in diesem Fall den on<Property>Changed
handler, wobei <property> die Eigenschaft isPortraitMode
ist.
Ein responsives Layout wird auch in NumberPad.qml
verwendet, wenn das Hoch- und Querformat für die NumberPad
selbst definiert wird.
RowLayout { spacing: controller.spacing GridLayout { id: scientificGrid columns: 3 columnSpacing: controller.spacing rowSpacing: controller.spacing visible: !isPortraitMode OperatorButton { text: "x²" } OperatorButton { text: "⅟x" } OperatorButton { text: "√" } OperatorButton { text: "x³" } OperatorButton { text: "sin" } OperatorButton { text: "|x|" } OperatorButton { text: "log" } OperatorButton { text: "cos" } DigitButton { text: "e" dimmable: true implicitWidth: 48 } OperatorButton { text: "ln" } OperatorButton { text: "tan" } DigitButton { text: "π" dimmable: true implicitWidth: 48 } } GridLayout { id: mainGrid columns: 5 columnSpacing: controller.spacing rowSpacing: controller.spacing BackspaceButton {} DigitButton { text: "7" } DigitButton { text: "8" } DigitButton { text: "9" } OperatorButton { text: "÷" implicitWidth: 38 } OperatorButton { text: "AC" textColor: controller.backspaceRedColor accentColor: controller.backspaceRedColor } DigitButton { text: "4" } DigitButton { text: "5" } DigitButton { text: "6" } OperatorButton { text: "×" implicitWidth: 38 } OperatorButton { text: "=" implicitHeight: 81 Layout.rowSpan: 2 } DigitButton { text: "1" } DigitButton { text: "2" } DigitButton { text: "3" } OperatorButton { text: "−" implicitWidth: 38 } OperatorButton { text: "±" implicitWidth: 38 } DigitButton { text: "0" } DigitButton { text: "." dimmable: true } OperatorButton { text: "+" implicitWidth: 38 } } } // RowLayout
In diesem Fall werden zwei LayoutItemProxy
Elemente erstellt. Ihre target
Eigenschaften sind auf scientificGrid
, einen Typ Grid
, der alle wissenschaftlichen Schaltflächen enthält, und mainGrid
, einen anderen Typ Grid
, der alle Standardschaltflächen enthält, eingestellt.
In CalculatorButton.qml
werden auch die Textfarben der Schaltflächen des Nummernblocks animiert.
... color: getBackgroundColor() border.color: getBorderColor() } contentItem: Text { text: button.text font.pixelSize: button.fontSize horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter color: getTextColor() Behavior on color { ColorAnimation { duration: 120 easing.type: Easing.OutElastic }
Die Farbänderungen werden animiert, indem ein Behavior
für die Eigenschaft color
definiert wird. Wenn eine Schaltfläche auf dimmed = true
gesetzt ist, erscheint die Schaltfläche dunkler. Wenn eine Schaltfläche gedrückt wird, leuchtet sie grün. Um die Eigenschaft dimmed
für alle Schaltflächen auf NumberPad
dynamisch zu ändern, ruft das Signal buttonPressed
die Funktion updateDimmed()
von NumberPad
auf.
function updateDimmed(){ for (let i = 0; i < mainGrid.children.length; i++){ mainGrid.children[i].dimmed = root.isButtonDisabled(mainGrid.children[i].text) } for (let j = 0; j < scientificGrid.children.length; j++){ scientificGrid.children[j].dimmed = root.isButtonDisabled(scientificGrid.children[j].text) } }
Ausführen von Berechnungen
Die Datei calculator.js definiert die Engine des Taschenrechners. Sie enthält Variablen, um den Zustand des Rechners zu speichern, und Funktionen, die aufgerufen werden, wenn der Benutzer die Ziffern- und Operatortasten drückt. Um die Engine zu verwenden, importieren Sie calculator.js in die Datei Main.qml
unter Verwendung des Alias CalcEngine
:
import "content/calculator.js" as CalcEngine
Standardmäßig wird beim Importieren einer JavaScript-Datei aus QML eine neue Instanz der Datei erstellt, und jeder darin enthaltene Status ist nur für diese Instanz gültig. Durch die Verwendung von .pragma library
kann der Status von allen Benutzern des Skripts gemeinsam genutzt werden.
.pragma library
Wenn der Benutzer eine Ziffer drückt, wird der Text der Ziffer auf dem Display angezeigt. Wenn sie einen Operator drücken, wird die entsprechende Berechnung durchgeführt, und das Ergebnis kann mit dem Gleichheitsoperator (=) angezeigt werden. Der Alles-Löschen-Operator (AC) setzt den Taschenrechner zurück.
Liste der Dateien
Siehe auch QML-Anwendungen.
© 2025 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.