
SBOM Best Practices for Embedded and Medical Software
Modern software is built on layers of open-source and third-party components—bringing both innovation and risk. In regulated industries, especially those […]
Join us at Qt C++ Warsaw Meetup - 21.08.2025
Sign up for free!Have you ever noticed that most professional software and games are available for all the most popular platforms? This is normal, because when creating an application you want it to be available to as many customers as possible. A wider audience means more interest in your product, but also more potential profits you can get from it. So it is worth releasing your app on several, different platforms, but how to do it? Whether you’re a startup or an established business, cross platform development gives you a strategic advantage by reaching more users with fewer resources.
As a team specializing in cross-platform Qt development – from desktop software to embedded systems – we help companies create apps that run efficiently on all major platforms. If you’re planning a multi-platform release and need expert support or just want to validate your idea, feel free to contact us for a free consultation.
When developing an application, one of the key decisions you need to make is choosing the right platform approach. There are two main options: native development and cross-platform development. So, how do they differ?
The first one is based on native development languages. In short, it involves the use of language and toolkits that are dedicated to a specific platform – for example, for Android it’s Java using Android Studio, and for iOS it’s Swift along with XCode IDE. The native approach has its advantages, but also disadvantages. The most important advantage is undoubtedly the possible achievable performance-optimized code in a native language will run the fastest, giving access to the built-in platform specific features of the system.
The disadvantage is of course the difficulty, time-consumption, and price of implementation – if you want to release an application for three different systems, you need to hire three independent teams of programmers. Managing codebases for multiple operating systems separately often leads to higher cost and longer delivery times. Such teams would work separately, which would have a significant impact on the application release date.
In addition, that application must also be maintained, which is associated with the constant payment of these teams. If you are wondering how to reduce project costs or want to learn what a technology stack is, take a look at our article: Low technology stack with Qt: Saved money.
So how to avoid high costs with little loss of performance? The answer lies in cross platform app frameworks which allows teams to write app code once and deploy it across many environments. Use a cross-platform framework. These types of frameworks allow you to develop software for multiple, different platforms using the same source code – no need to rewrite your application when you need to add new functionality or support for a new target platform. Of course, creating cross platform applications does not offer that easy access to all native components, but they offer instead faster, cheaper, and more efficient software production.
So which platform app development framework is best? Well, it depends on what type of target platforms you’re interested in – there are many different frameworks, and it’s impossible to list all of them in one post. So we will focus today on 6 of the best desktop cross-platform frameworks.
Let’s start our review with JavaFX, a cross-platform framework based on pure Java. Initially, this framework was included with JDK versions 8-10 and was the main GUI environment for Java, replacing the previously used Swing. Starting with JDK 11, however, it was only available as an external tool included in OpenJDK as part of the OpenJFX project.
JavaFX allows software development for platforms such as Windows, macOS and Linux or Android, iOS (mobile development), and web browsers. Initially, embedded systems were also supported, but this support was withdrawn with JDK 8u33 for ARM. JavaFX applications can be developed using pure Java as well as available libraries – we are also talking about the popular Maven package manager, which can be integrated with JavaFX. JavaFX, of course, comes with a set of ready-made libraries, and developers can also enhance their applications using various third party libraries available in the Java ecosystem.
JavaFX uses FXML (language based on XML) files to create the appearance of windows. Each tag represents a separate object in the application to which we can give appropriate properties, position, and nest other components. The base component is a single container into which we put other objects. Such a component then only needs to be loaded in the Java code. Remember that the type used should be consistent with that declared in the file. We can also use a CSS file to style selected components.
To make working with FXML files easier, there’s a tool called Scene Builder. It is an editor that allows you to create the appearance of your application easily. To add a component, simply drag and drop it on the workspace and then adjust its properties in the side window. If we have chosen AnchorPane as the base component, positioning components is even easier because they “stick” to an invisible grid that divides our application into equal parts.
Scene Builder in action
Unfortunately, JavaFX is not without its drawbacks. As most of you probably know, programs created in Java run in a virtual machine, which results in higher RAM consumption and significant CPU usage. The result is that programs created in JavaFX can run noticeably slow on some, weaker devices. Additionally, both JavaFX and JavaSwing are used less and less – these solutions are gradually being replaced by technologies such as Qt, JSF, Flutter, or Electron. Moreover custom drawing, and animations are not so simple to do – at least not as simple as in QML.
Below is a sample application design that we generated using Scene Builder (screen above):
<? xml version="1.0" encoding="UTF-8"?> <? import javafx.scene.control.Label?> <? import javafx.scene.image.Image?> <? import javafx.scene.image.ImageView?> <? import javafx.scene.layout.AnchorPane?> <? import javafx.scene.layout.Pane?> < AnchorPane accessibleText="″ xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/17"> < children> < Pane layoutX="-7.0" prefHeight="768.0" prefWidth="660.0"> < children> < Label layoutX="300.0" layoutY="283.0" text="Hello world" textAlignment="CENTER" /> < ImageView fitHeight="150.0" fitWidth="200.0" layoutX="255.0" layoutY="309.0" pickOnBounds="true" preserveRatio="true"> < image>. < Image url="@ss.png" /> </image>. </ImageView>. </children>. </Pane>. </children>. </AnchorPane>.
So this is what the program looks like after launch:
Qt is a framework that we specialize in, but also a framework trusted by many global companies. This framework had its beginnings back in 1995, and since then it has been constantly developing. Qt has its heart created in pure C++ language, thanks to that it offers native-like performance and enables creation of a responsive user interface even for complex business applications. Initially, Qt was a framework fully dedicated to desktop platforms, which resulted in such deep development of the dedicated desktop module Qt Widgets. With the release of the 5th version of Qt, support for most mobile platforms as well as embedded systems was introduced.
Developing desktop applications in Qt requires knowledge of C++ (or Python, if you’re using PyQt) – in fact, basic knowledge of this programming language is enough here, because Qt comes with many, easy-to-use modules, which are additionally described in detail and understandable way in the documentation. A noteworthy module is Qt Quick, which allows you to create applications using the QML declarative language. It is a simple tool that looks like a combination of JSON, CSS, and JavaScript. The last of mentioned languages is part of QML, so we can directly use previously prepared js scripts. However, it is commonly accepted that the application logic is fully implemented in C++ and QML handles its appearance. That separation of logic and appearance allows us to achieve native-like performance, in a non-native way and cleaner software architecture.
Qt, as a technology, has been chosen by many, global brands. AMD, Intel, Mercedes-Benz, Bosh, LG, Panasonic, Ubuntu – we could list without end. There is nothing surprising about it because Qt is a stable, mature solution. The attention of these corporations is certainly attracted by the mentioned above Qt Widgets, which is one of the most developed and advanced modules that allows you to create an efficient desktop application with little effort, making Qt one of the best cross-platform desktop frameworks. It’s also worth mentioning that the Qt framework, besides the previously mentioned Qt Widgets and Qt Quick modules, also comes with many other modules, thanks to which you can easily call native functionalities, using 100% of the potential of the target device. Additionally, the Qt framework includes the Qt Designer tool, which allows you to easily create the appearance of your application without knowing any programming language – similar to the previously mentioned Scene Builder.
Of course, like any other framework, Qt is not a silver bullet for every project. Qt isn’t such a widespread framework, which can make it difficult to find a specialist in this technology. Additionally, its low popularity is also reflected in the framework’s less extensive developer community.
Below you will find the code of a simple program, created in QML:
importing QtQuick 2.12 import QtQuick.Window 2.0 Window { id: root width: 640 height: 640 visible: true title: "Example window" Text { id: text anchors { bottom: image.top bottomMargin: 25 horizontalCenter: image.horizontalCenter } text: "Hello world!" } Image { id: image width: 150 height: 150 anchors.centerIn: parent fillMode: Image.PreserveAspectFit source: "qrc:/assets/image.png" } }
This is what our sample program looks like after running:
The next cross-platform desktop framework we will discuss today is Electron. Electron is an open-source framework created and developed by GitHub. It was first released in 2013, so it is a fairly young framework. Electron is available as a Node.js package and can be easily downloaded using the npm manager.
Electron allows you to create fully-functional desktop applications using modern web technologies such as HTML, JavaScript, and CSS, making it ideal for web developers entering the desktop space. It uses a combination of the Chromium rendering engine and the Node.js environment to visualize the appearance of the application. It is worth mentioning here that Electron itself was created in C++ and Objective-C, and all its built-in methods and functionalities are available from JavaScript in the application we are creating.
Visual Studio Code as web app vs Visual Studio Code as Electron desktop app
Desktop apps created in Electron contains 3 main elements: index.html, main.js, and package.json. The first file contains the implementation of the application appearance, which we create using HTML. Here, we define and position the application elements, giving them the appropriate properties – similar to FXML in JavaFX. The main.js file contains the implementation of the application logic – this is where the more complicated scripts of our program should be placed. The last of these three files contains metadata about our application that is used as package information by Node.js. In this file, we need to include information about our application, such as the title, version, as well as a path to the file containing the logic implementation (by default main.js).
Many, well-known applications that are available on multiple platforms are based on Electron, such as Discord, Skype, Visual Studio Code, WordPress Desktop, Github Desktop, Microsoft Teams and many others. You will notice that each of them has its counterpart on the web platform. Having a ready-made web design, you can quite easily port it to a desktop application using Electron. Of course, it also works the other way round – by creating a basic application in Electron we can later use its source code to create a web application.
However, Electron has its own disadvantages. First of all, like JavaFX, it uses a very large amount of system resources while offering much worse performance than native apps. Electron is also aimed directly at desktop platforms – it is impossible to build an application directly for Android, iOS, or embedded systems. Additionally, it lacks a dedicated designer for the apps you create. You can, of course, use solutions such as WYSIWYG, but such solutions won’t use the built-in features Electron provides.
Below is the HTML code of a sample application created in Electron. The main.js file has remained unchanged:
<! DOCTYPE html> < html>. < head> < meta charset="UTF-8"> <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --> < meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"> < link href="./styles.css" rel="stylesheet"> < title> Example App</title>. </head> < body> < div style="text-align: center; margin-top: 25%;"> < h1> Hello World! </h1> < br> < img src="ss.png" alt="electron"> </div>. <!-- You can also require other files to run in this process --> < script src="./renderer.js"></script> </body> </html>.
This is what our application looks like after launch:
Flutter is another cross-platform desktop framework for software development. It is an open-sourced project created by Google in May 2017. Flutter was initially targeted exclusively at mobile platforms. Support for desktop platforms was introduced only in 2020.
Programming applications in Flutter requires knowledge of Dart, Google’s proprietary programming language. Originally designed for mobile app development, Flutter now supports multiple form factors, including desktop and web.. It is a universal, strongly-typed object-oriented language. It can seem a bit difficult to the novice programmer, so it’s important to learn it before you start developing applications in Flutter. Flutter programming is primarily based on using components called widgets. Widgets can be either stateless, meaning that they cannot be changed at runtime, or they can be stateful, meaning that we can change their appearance at runtime. However, it is important to keep in mind, that such a change renders the element completely from scratch – this can have an impact on performance.
Similar to Qt, Flutter allows us to integrate our code with the native functionality of the target system, like Bluetooth, GPS, etc.but unlike in Qt, however, you have to use special libraries created by the community to do so – in the Qt framework, most of them are already built-in.
To create a project in Flutter, run the file flutter_console.bat. The program will then guide you through the process of creating the project. The implementation of the appearance and logic is contained in the main.dart file. After creating the application, we can build it for both web and mobile platforms. In the case of desktop platforms, the matter is a bit more complicated, because here we have to download the appropriate packages first, and also properly configure the project to be ready for release to desktops.
One of the biggest drawbacks of Flutter is the quite large size of the final package. An application created in Flutter, for example, which takes up 2MB, would take up 200-400KB of disk space in other technologies. Another problem is the youth of this framework, and the small number of built-in libraries. Also, since Flutter is a framework from Google, they pay more attention to improvements targeting Android than iOS.
Below you will find sample code for an application created in Flutter:
import' package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { Map< int, Color> color = { 50 :Color. fromRGBO(29,202 , 155, . 1), 100 :Color. fromRGBO(29,202 , 155, . 2), 200 :Color. fromRGBO(29,202 , 155, . 3), 300 :Color. fromRGBO(29,202 , 155, . 4), 400 :Color. fromRGBO(29,202 , 155, . 5), 500 :Color. fromRGBO(29,202 , 155, . 6), 600 :Color. fromRGBO(29,202 , 155, . 7), 700 :Color. fromRGBO(29,202 , 155, . 8), 800 :Color. fromRGBO(29,202 , 155, . 9), 900 :Color. fromRGBO(29,202 , 155, 1), }; return MaterialApp( title: 'Scythe Demo', debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: MaterialColor(0xff1dca9b, color) ), home: const HomePageClass(displayText: 'Hello world'), ); } } class HomePageClass extends StatefulWidget { const HomePageClass({Key? key, required this.displayText}) : super(key: key); final String displayText; @override State< HomePageClass> createState() => _HomePageClassState(); } class _HomePageClassState extends State< HomePageClass> { @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: < Widget>[ Text(widget.displayText), Image. asset('assets/images/ss.png'), ], ), ) ); } }
This is how it looks like after launch:
Another noteworthy cross-platform framework worth mentioning is .NET MAUI – short for Multi-platform App UI. It’s Microsoft’s modern successor to Xamarin.Forms, officially released in 2022 as part of the .NET 6 ecosystem. MAUI enables developers to build native applications for Windows, macOS, Android, and iOS using a shared C# and XAML codebase, making it a solid choice for those already familiar with Microsoft technologies.
Unlike older Microsoft technologies like WPF or UWP, MAUI is fully integrated into the .NET ecosystem and uses .NET 6+ SDK. What makes it especially interesting for desktop development is that MAUI applications are compiled into native code, and thanks to the underlying use of platform-specific renderers (known as handlers), they offer near-native performance and full access to native APIs.
Creating an application in .NET MAUI requires Visual Studio 2022 or newer with the MAUI workload installed. MAUI uses XAML for designing the UI and C# for the logic – very similar to WPF or Xamarin.Forms, so developers with Microsoft stack experience will feel right at home.
MAUI comes with a wide range of built-in controls and layouts, and it supports MVU (Model-View-Update) architecture, as well as MVVM (Model-View-ViewModel). It also provides development tools such as Live Reload and Hot Restart, which significantly speed up development process and debugging. MAUI’s project structure also allows you to share code across multiple platforms, while still enabling platform-specific customization through conditional compilation or platform folders.
That said, the framework is still relatively young and has some growing pains. There are fewer open-source UI libraries compared to more mature frameworks like Qt or Flutter, and the tooling can sometimes feel unstable. Also, despite Microsoft’s efforts, the macOS support is less mature than Windows, and there are no plans to support Linux.
Below is an example of a simple desktop app created in .NET MAUI using XAML:
And its appearance after running:
The last cross-platform framework in today’s review is React Native for Windows + macOS – an official Microsoft-supported extension of React Native, originally developed by Meta. While React Native was initially designed for mobile platforms (Android and iOS), thanks to this extension it’s now possible to build native desktop applications for Windows and macOS using JavaScript and React.
The architecture of React Native remains unchanged – the application UI is built using React components, and logic is implemented in JavaScript (or TypeScript). Under the hood, React Native uses native modules and views, so despite writing your code in JavaScript, the final result is still a native application, not a web wrapper. This allows React Native to achieve significantly better performance than solutions like Electron.
To create a React Native desktop application, you need to install additional packages: react-native-windows or react-native-macos, depending on the target platform. Development is usually done using Visual Studio Code and Node.js tooling such as Metro bundler, npm, and react-native CLI. Thanks to the React ecosystem, you also get access to a vast range of open-source libraries, UI components, and an active community that continuously improves the tooling.
React Native for Windows + macOS is a great choice if you’re already familiar with React or if your application needs to share code with a mobile version. However, desktop support is still under active development – Linux is not supported, and even on Windows/macOS, you may encounter missing components, bugs, or limited documentation. Also, while the app’s UI is native, integrating with low-level system APIs (like Bluetooth or camera) may require writing native C++ or Objective-C modules manually.
Below you’ll find the simplified JSX code of a small desktop app created with React Native for Windows:
import React from 'react'; import { SafeAreaView, StatusBar, StyleSheet, Text, Image, View } from 'react-native'; function App(): React.JSX.Element { return (); } const styles = StyleSheet.create({ container: { flex: 1, // This will make the SafeAreaView take up the full height of the screen justifyContent: 'center', // Vertically center the content in SafeAreaView alignItems: 'center' // Horizontally center the content in SafeAreaView }, columnContainer: { flexDirection: 'column', // Stack children vertically justifyContent: 'center', // Center the content vertically in the column alignItems: 'center', // Center the content horizontally in the column paddingVertical: 20, // Add some padding around the column to ensure it stays in the middle }, helloText: { fontSize: 24, fontWeight: 'bold', marginBottom: 20, // Adds space between "Hello World!" and the image }, image: { width: 200, height: 200, resizeMode: 'contain', }, }); export default App; Hello World!
And here is what it looks like when launched:
Feature | Qt | Electron | Flutter | JavaFX | .NET MAUI | React Native for Windows/macOS |
---|---|---|---|---|---|---|
First release | 1995 | 2013 | 2017 | 2008 | 2022 | 2020 (Windows), 2021 (macOS) |
Rapid development | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ |
High performance | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ |
Dedicated UI designer | ✅ | ❌ | ❌ | ✅ | ✅ (XAML + Live Preview) | ❌ |
Large number of built-in functionalities | ✅ | ❌ | ❌ | ✅ | ❌ (many via NuGet) | ❌ (community-based) |
Large community | ❌ | ✅ | ✅ | ❌ | ❌ (growing) | ✅ (React ecosystem) |
Desktops | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Mobiles | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ |
Web | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ |
Embedded | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
If you want your application to be accessible simultaneously on web browsers and desktop systems, then Electron is still one of the best options. It allows you to build your app using pure HTML, CSS, and JavaScript, making it easy to reuse existing web code or port your desktop app back to the browser. It’s ideal for teams with a strong web development background, although you should keep in mind the relatively high resource usage and lack of native performance.
If you’re planning to release an application targeting both desktop and mobile platforms, Flutter is a very capable option. Thanks to Google’s backing, it has a fast-growing ecosystem and good community support. However, it requires familiarity with Dart and currently produces relatively large binaries. Desktop support is also still maturing.
An alternative to Flutter is .NET MAUI, especially if you’re already in the Microsoft ecosystem. With MAUI, you can build native applications for Windows, macOS, Android, and iOS using C# and XAML. It’s particularly attractive to developers familiar with WPF or Xamarin. While its tooling and macOS support still need refinement, MAUI is quickly becoming a powerful and future-proof solution for cross-platform business applications.
If you’re coming from a React or web frontend background, then React Native for Windows + macOS is a strong contender. You can reuse large parts of your existing React codebase and achieve near-native performance thanks to the use of native components under the hood. Keep in mind that desktop support is newer than mobile, and you may encounter missing components or need to write native modules for advanced integrations.
If you prefer to prioritize maximum performance and mature desktop tools, your best bet is still Qt. It offers native speed, excellent platform support (including embedded systems), and a modular architecture that gives you full access to device capabilities. Qt is ideal for complex cross platform desktop applications that require high efficiency, custom native integration, or broad platform coverage – even in industrial and automotive environments.
And finally, while JavaFX still allows you to create desktop apps quickly using Java and tools like Scene Builder, it is gradually fading in popularity and lacks the performance or flexibility of newer solutions. For most new projects, it is no longer a recommended choice.
That would be it. If you are interested in a cross-platform desktop application development service, check out what we can do for you or book a free consultation right away.
Also, if you’re looking for a more detailed comparison, be sure to read our post “The Current State of Flutter vs React Native vs Qt vs Lynx JS”, which thoroughly compares these frameworks for desktop, mobile, web, and embedded devices.
Let's face it? It is a challenge to get top Qt QML developers on board. Help yourself and start the collaboration with Scythe Studio - real experts in Qt C++ framework.
Discover our capabilitiesModern software is built on layers of open-source and third-party components—bringing both innovation and risk. In regulated industries, especially those […]
If we think about it for a minute, it is impossible to imagine an app without a UI. We need buttons, checkboxes, dropdown menus and much more. Almost all of these controls are created using 2D elements. However, sometimes we need to put some depth into the UI.
I’m not going to lie, a lot of the projects we do at Scythe Studio are related to the medical […]