This page is for developers who are familiar with web technologies like HTML, CSS and JavaScript. It shows a collection of examples, implemented both in web technologies and Felgo for comparison. Felgo is based on Qt and uses QML as the main language.
QML stands for "Qt Markup Language" and is a declarative language designed to describe the user interface of a program: both what it looks like, and how it behaves. In QML, a user interface is specified as a tree of objects with properties. This tree is also often referred to as Scene Graph, because when the parent item moves all children will follow. JavaScript is used as a scripting language in QML. In this section we will cover the basics of QML and its advantages by an example.
As code speaks more than 1000 words, here is a QML example implementing the following:
How many lines of code would it take you to develop this application with the same functionality in another programming language? With QML, it is just about 30 lines of code:
import Felgo import QtQuick App { id: app property int clickCount: 0 // a property of type integer, to count our button clicks NavigationStack { // the NavigationStack displays the navigation bar and lets you push and pop pages AppPage { title: "QML Introduction" // the title of the active page is displayed in the navigation bar Rectangle { color: "#e0e2eb" width: parent.width // make this rectangle the same width as its parent, which is the page height: parent.height * slider.value // this property binding is automatically updated when the slider value changes } Column { anchors.centerIn: parent // center the column in its parent, which is the page AppButton { id: button text: "Click Me! " + app.clickCount // this property binding is automatically updated when the click count changes flat: false anchors.horizontalCenter: parent.horizontalCenter onClicked: { app.clickCount++ // increase the click count by 1 on every button click } } AppSlider { id: slider value: 0.2 } } //Column } //Page } //NavigationStack } //App
While the HTML examples will use px
values, Felgo offers dp()
and sp()
functions to get density independent pixel values. This guarantees that the components have the same physical size
on any screen. You can also use normal pixel values, but it is best practice to design your apps density and resolution independent. You can find more about this topic here: Create Layouts and Position Components in Your App.
The following examples show how to perform the most common UI layout tasks.
Font style, size, and other text attributes that CSS handles with the font and color properties are individual properties of the AppText component.
In both HTML and Felgo, by default child elements or widgets are anchored at the top left.
<div class="box"> Lorem ipsum </div> .box { background-color: #e0e0e0; width: 320px; height: 240px; font: bold 24px Helvetica; }
Rectangle { color: "#e0e0e0" width: dp(320) height: dp(240) AppText { text: "Lorem ipsum" font.weight: Font.Bold font.pixelSize: sp(24) font.family: "Helvetica" } }
Setting a background color with Felgo is as straightforward as with CSS.
<div class="box"> </div> .box { background-color: #e0e0e0; width: 320px; height: 240px; }
Rectangle { color: "#e0e0e0" width: dp(320) height: dp(240) }
You can use anchors to center any component in its parent. You can read more about the powerful options of anchoring here: Positioning with Anchoring
To accomplish a similar effect in CSS, the parent element uses either a flex or table-cell display behavior. The examples on this page show the flex behavior.
<div class="box"> Lorem ipsum </div> .box { background-color: #e0e0e0; width: 320px; height: 240px; display: flex; align-items: center; justify-content: center; }
Rectangle { color: "#e0e0e0" width: dp(320) height: dp(240) AppText { text: "Lorem ipsum" anchors.centerIn: parent } }
The following examples show how to perform more complex operations on component position, size, and background.
Components are always positioned relative to their parent. To specify an absolute position for a component, just use its x
and y
properties.
<div class="box"> <div class="inner"> </div> </div> .box { background-color: #e0e0e0; width: 320px; height: 240px; position: relative; } .inner { background-color: #ef5350; width: 100px; height: 100px; position: absolute; top: 24px; left: 24px; }
Rectangle { color: "#e0e0e0" width: dp(320) height: dp(240) Rectangle { color: "#ef5350" width: dp(100) height: dp(100) x: dp(24) y: dp(24) } }
To rotate a comonent, just change its rotation
property. You can also apply more complex transformations using the Item::transform
property. The default transform origin is the center, you can change it with the Item::transformOrigin property.
<div class="box"> <div class="inner"> </div> </div> .box { background-color: #e0e0e0; width: 320px; height: 240px; display: flex; align-items: center; justify-content: center; } .inner { background-color: #ef5350; width: 100px; height: 100px; transform: rotate(15deg); }
Rectangle { color: "#e0e0e0" width: dp(320) height: dp(240) Rectangle { color: "#ef5350" width: dp(100) height: dp(100) rotation: 15 } }
When you scale a parent component, all its child component are scaled accordingly.
<div class="box"> <div class="inner"> </div> </div> .box { background-color: #e0e0e0; width: 320px; height: 240px; display: flex; align-items: center; justify-content: center; } .inner { background-color: #ef5350; width: 100px; height: 100px; transform: scale(1.5); }
Rectangle { color: "#e0e0e0" width: dp(320) height: dp(240) Rectangle { color: "#ef5350" width: dp(100) height: dp(100) scale: 1.5 } }
You can either apply a gradient to a Rectangle directly, or use the LinearGradient component for even more options. This component is available with import Qt5Compat.GraphicalEffects
.
The default gradient is drawn as vertical gradient. You can use as many colors as you want, with a position between 0.0 and 1.0.
<div class="box"> </div> .box { width: 320px; height: 240px; background: linear-gradient(180deg, #ffffff, #000000); }
LinearGradient { width: dp(320) height: dp(240) gradient: Gradient { GradientStop { position: 0.0; color: "#ffffff" } GradientStop { position: 1.0; color: "#000000" } } }
For a horizontal gradient, you need to set the start point to the very left, and the end point to the very right of the component. This way, you can also create gradients at any desired rotation.
<div class="box"> </div> .box { width: 320px; height: 240px; background: linear-gradient(0deg, #ffffff, #000000); }
LinearGradient { width: dp(320) height: dp(240) start: Qt.point(0,0) // Qt.point(<x>,<y>) end: Qt.point(width, 0) gradient: Gradient { GradientStop { position: 0.0; color: "#ffffff" } GradientStop { position: 1.0; color: "#000000" } } }
The following examples show how to make and customize shapes.
Use the radius
property to get rounded corners.
<div class="box"> </div> .box { background-color: #e0e0e0; width: 320px; height: 240px; border-radius: 8px; }
Rectangle { color: "#e0e0e0" width: dp(320) height: dp(240) radius: dp(8) }
To add a box shadow, you can add a layer effect to your component. The DropShadow type requires an import
Qt5Compat.GraphicalEffects
.
<div class="box"> </div> .box { background-color: #e0e0e0; width: 320px; height: 240px; box-shadow: 0 5px 5px rgba(0, 0, 0, 0.8); }
Rectangle { color: "#e0e0e0" width: dp(320) height: dp(240) layer.enabled: true layer.effect: DropShadow { radius: 0 horizontalOffset: dp(5) verticalOffset: dp(5) color: "#80000000" } }
Like with CSS, you can create circles by defining a border radius of 50% width to all edges. Additionally you can use the Canvas type to draw shapes using JavaScript.
<div class="box"> </div> .box { background-color: #e0e0e0; width: 240px; height: 240px; border-radius: 50%; }
Rectangle { color: "#e0e0e0" width: dp(240) height: dp(240) radius: width/2 }
The following examples show how to specify fonts and other text attributes. They also show how to transform text strings, customize spacing, and create excerpts.
In CSS you specify the amount of white space between each letter or word by giving a length value for the letter-spacing and word-spacing properties, respectively. The amount of space can be in px, pt, cm, em, etc.
With Felgo you can also set those values in pixels, or the recommended density independent pixels of dp()
and sp()
. You can find all the available properties in the documentation of AppText and the inherited Text type.
<div class="box"> Lorem ipsum </div> .box { background-color: #e0e0e0; width: 320px; height: 240px; display: flex; align-items: center; justify-content: center; letter-spacing: 4px; }
Rectangle { color: "#e0e0e0" width: dp(320) height: dp(240) AppText { text: "Lorem ipsum" anchors.centerIn: parent font.letterSpacing: sp(4) } }
In HTML/CSS, you perform simple case transformations using the text-transform property.
You can apply the same transformations with the font.capitalization property.
<div class="box"> Lorem ipsum </div> .box { background-color: #e0e0e0; width: 320px; height: 240px; display: flex; align-items: center; justify-content: center; text-transform: uppercase; }
Rectangle { color: "#e0e0e0" width: dp(320) height: dp(240) AppText { text: "Lorem ipsum" anchors.centerIn: parent font.capitalization: Font.AllUppercase } }
You can use the RichText textFormat to add inline text formatting using HTML markup. You can find the supported HTML markup here: Supported HTML Subset.
<div class="box"> Lorem <em>ipsum</em> </div> .box { background-color: #e0e0e0; width: 320px; height: 240px; display: flex; align-items: center; justify-content: center; } .box em { font-weight: bold; }
Rectangle { color: "#e0e0e0" width: dp(320) height: dp(240) AppText { // you can use < instead of < // the < is a little hack to copy this web example text: "Lorem <em style=\"font-weight: bold;\">ipsum </em>" anchors.centerIn: parent textFormat: Text.RichText } }
An excerpt displays the initial line(s) of text in a paragraph, and handles the overflow text, often using an ellipsis. In HTML/CSS an excerpt can be no longer than one line. Truncating after multiple lines requires some JavaScript code.
With Felgo, you have full control how you want to wrap your text, the maximum number of lines or the maximum maximum height of your excerpt.
<div class="box"> Lorem ipsum dolor sit amet, consectetur adipiscing. </div> .box { background-color: #e0e0e0; width: 320px; height: 240px; display: flex; align-items: center; justify-content: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
Rectangle { color: "#e0e0e0" width: dp(320) height: dp(240) AppText { text: "Lorem ipsum dolor sit amet, consectetur adipiscing." width: parent.width wrapMode: Text.WordWrap maximumLineCount: 1 elide: Text.ElideRight } }
More examples for common use cases of app development can be found in the Felgo Apps Documentation. The navigation on the left contains the most important components and challenges for developing cross-platform apps.
Felgo Apps run in a browser by using WebAssembly. You can deploy a Felgo app as a standalone app or integrate it into an already existing website. One such example is the Felgo WebEditor that allows you to run a code editor and a live preview side by side.
Felgo also provides a seamless integration between a browser and the QML app. See Sharing data with the Browser to learn more.