How to Speed Up JUCE GUI Development


How to Speed Up JUCE GUI Development

May 27th 2025 - Jelle Bakker

When you think about audio software, you might think of the audio processing as the most time-consuming part of development. It's true that DSP algorithms can demand significant time, but the biggest time investments is often the Graphical Audio Interface (GUI) development. Why is that the case, and what can you do about it?

Remind me, why are we using JUCE?

JUCE is an open-source C++ framework designed for developing audio software, with a strong focus on creating audio plug-ins. These plug-ins come in various formats, including VST, VST3, AU, AUv3, AAX, and LV2. JUCE simplifies cross-format development by abstracting them through a unified interface, the juce::AudioProcessor.

JUCE is built in C++ because real-time audio processing demands a high-performance programming language. Meeting strict timing deadlines requires code that is both deterministic and low-latency. C++ is a good choice because it offsers determinstic control and performance.

In general, the GUI of audio software doesn’t face the same strict performance constraints as the audio processing side. The GUI should of course remain smooth and responsive, but this can usually be achieved with a variety of simpler programming languages. However, since JUCE is built in C++ to meet the real-time demands of audio processing, there are not many alternatives for audio software that combine both high-performance audio and GUI in a single framework.

The problem

So what's the issue with writing a GUI in C++?

1. Compile times: Every code change typically requires recompilation, and although modern compilers support incremental builds, recompiling only what they determine is affected, this isn’t always fast in practice. Even a minor change, like tweaking a single number, can sometimes trigger compile times of tens of seconds or even minutes, especially in large or complex projects. This becomes a significant drawback when developing a GUI, where rapid iteration is important and developers often expect to see immediate feedback from their changes.

2. Code complexity: C++ is a complex language, and even simple tasks can sometimes require a significant amount of code. When working at a low level, lots of boilerplate code is often necessary. In JUCE, for example, customizing the appearance of components can involve extensive changes. While JUCE provides helpful abstractions, such as the ability to override colours, fonts, or entire paint routines, these features can still lead to complex and verbose code. As a result, development can become time-consuming, especially when making frequent UI adjustments.

3. Code difficulty: Finally, C++ is a difficult language to work with. Its primary goal is performance, often at the cost of code simplicity and safety. While it gives the programmer full control over low-level details, that same control makes it easy to introduce subtle and hard-to-find bugs. This lack of safety features, compared to higher-level languages, can lead to increased complexity and a greater likelihood of errors. As a result, developers may end up spending a significant amount of time debugging, which slows down the overall development process.

Because of these challenges, C++ is typically used for performance-critical software, such as games, video processing tools, embedded systems, and audio software. Although for audio only the audio-processing components truly require the low-level performance that C++ offers. Ideally, software could be modularized in a way that allows different parts, like the GUI and the audio engine, to be written in different languages. This would allow developers to use a more suitable, higher-level language for the GUI development.

Existing solutions

Many JUCE developers experience these challenges and have responded by creating various tools and solutions to make GUI development more efficient. Here are a few solutions:

HISE: An open-source framework for creating sample-based instruments. Built on top of JUCE, it provides users with a graphical editor that allows them to design instruments without writing any code.

Foleys GUI Magic: A drag-and-drop editor that lets you design the GUI for your audio plugin and easily link it to the parameters of your AudioProcessor.

JIVE: A bundle of JUCE modules focused on bringing a more modern approach to UI development. Inspired by web front-end frameworks, it embraces the idea of defining interfaces declaratively, similar to how HTML outlines components, and styling them with style sheets like CSS. JIVE is also built on top of JUCE.

JUCE_LIVE_CONSTANT: A handy feature built into JUCE that lets you control “magic numbers” in your code through an on-screen slider. For example, if you write x = JUCE_LIVE_CONSTANT(100), a slider will appear, allowing you to adjust that value in real time. It’s especially useful for quickly experimenting with coordinates, sizes, or other parameters of components during development.

Melatonin Component Inspector: A JUCE module that gives you the ability to inspect and visually edit (non-destructively) components in your UI.

Projucer GUI Editor: A feature in JUCE’s Projucer that provided a visual GUI editor with hot-reloading capabilities, letting you see updates to your interface instantly as you made changes. Unfortunately, this editor has since been removed from JUCE.

iZotope Glass Properties: A project, announced during a talk “A Case-study in Rewriting a Legacy GUI Library for Real-time Audio Software in Modern C++” at CppCon. While it’s not yet publicly available, the concept involves customizing properties of GUI classes through a special GUI debugging view, offering real-time adjustments to JUCE components during development.

juce_gui_stylesheet: A lightweight stylesheet-based solution I developed myself. I’ll share more details about it later on.

Although many of the tools mentioned above are helpful and can speed up GUI development, each comes with its own limitations. Also, lot of these solutions try to eliminate the need for scripting by offering GUI editors, but if you look at web development, people have no issue writing code directly. The real problem isn’t coding itself, but it’s writing specifically in C++. What if we could actually write the GUI in a different programming language altogether?

WebView

Say hello to web programming in JUCE. Since JUCE 8, full web view support is available, allowing you to build your GUI using any web language and framework you prefer. You can now bring in your JavaScript friends to help out. Plus, with built-in hot-reloading, any changes you make to the web code update the GUI instantly.

This is a major milestone.

I believe this is where most JUCE GUIs will head in the future. While there’s a learning curve and some overhead, like the boilerplate needed to setup communication between JUCE and the web code, JUCE handles much of this for you.

A Gem to End On

I want to conclude with sharing a repository I put together recently. It shows how to use an XML file as a hot-reloadable stylesheet for a JUCE GUI. 

My motivation came from wanting to tweak UI variables at runtime, without switching to a new framework or using a no-code tool. JUCE offers JUCE_LIVE_CONSTANT, which helps a bit by allowing real-time adjustments, but it doesn’t scale well.

I extended that JUCE_LIVE_CONSTANT concept and built a StyleSheet.xml where I can define things like colours, fonts, and labels. Any changes to the XML file during runtime are automatically applied to the running GUI, making iteration seamless.

It’s a small repo with minimal code, I hope it’s useful or inspiring to others facing the same problem. Link below:

https://github.com/JelleBakker/juce_gui_stylesheet/tree/main