GetDunne Wiki

Notes from the desk of Shane Dunne, software development consultant

User Tools

Site Tools


juce_gui_basics

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
juce_gui_basics [2021/02/08 18:13]
shane [Layout is basically top-down]
juce_gui_basics [2021/02/08 23:52] (current)
shane [Subclassing JUCE GUI classes]
Line 12: Line 12:
 You might choose to subclass //juce::Button// if you want to create your own type of button widget with unique appearance and behavior. To respond to the button being clicked, you would overload the //clicked()// member function. To change its appearance, you would overload //paint()//, and so on. You might choose to subclass //juce::Button// if you want to create your own type of button widget with unique appearance and behavior. To respond to the button being clicked, you would overload the //clicked()// member function. To change its appearance, you would overload //paint()//, and so on.
  
-Creating a derived class like this allows you to override as much of the standard class's functionality as you like, and inherit the rest.+Creating a derived class like this allows you to override as much of the standard class's functionality as you like, and inherit the rest. It's usually more work than the other two approaches.
  
 ==== Listeners ==== ==== Listeners ====
Line 80: Line 80:
  
 (The truth is, //no part of JUCE is truly well-documented//. There's quite a bit of documentation, but a hell of a lot more code. I would estimate that it is less than 5% adequately documented, perhaps closer to 1%.) (The truth is, //no part of JUCE is truly well-documented//. There's quite a bit of documentation, but a hell of a lot more code. I would estimate that it is less than 5% adequately documented, perhaps closer to 1%.)
 +
 +==== Linking GUI components to variables in your code ====
 +JUCE does not provide simple mechanisms to link, say, a //juce::Slider// control to a C++ //float// in your code. Instead, the Slider has a "current value" which you can get/set using its //getValue()// and //setValue()// methods. You can also inherit from //juce::Slider::Listener//, or set your Slider's //onChange// std::function pointer to a lambda in your code, to receive callbacks when the user changes the value.
 +
 +==== Linking GUI components to plug-in parameters ====
 +JUCE does provide a very high-level system to link GUI controls to //plug-in parameters//, which goes by the ungainly class name //juce::AudioProcessorValueTreeState// (abbreviated AVTS).
 +  * [[https://docs.juce.com/master/classAudioProcessor.html|//juce::AudioProcessor]] is the root class for your plug-in's DSP code
 +  * [[https://docs.juce.com/master/classValueTree.html|juce::ValueTree]] implements a hierarchical structure of "values" which are [[https://docs.juce.com/master/classvar.html|juce::var]] objects.
 +  * [[https://docs.juce.com/master/classAudioProcessorValueTreeState.html|juce::AudioProcessorValueTreeState]] (AVTS) is a special kind of //juce::ValueTree// intended to represent the "state" of all a plug-in's parameters (the same ones it exposes to a host for automation).
 +  * AVTS knows all about //parameters//, which are all expressed as subclasses of [[https://docs.juce.com/master/classAudioProcessorParameter.html|juce::AudioProcessorParameter]]
 +  * AVTS also defines several "attachment" classes e.g. //ButtonAttachment//, //SliderAttachment//, etc. which set up automated, two-way links between a GUI control and its associated parameter. This is by far the best way to do this in a plug-in.
 +  * //juce::AudioProcessorParameter// has an associated //Listener// class, which you can override to receive a callback whenever the parameter value gets changed, either by the user manipulating the GUI, or through host automation, or in a few other cases (like loading presets, adjusting related parameters, etc.)
 +
 +===== JUCE is NOT a Model-View-Controller based framework =====
 +Nearly all GUI frameworks in widespread use are based on the classic [[wp>Model–view–controller|Model-View-Controller]] design pattern, but JUCE is not.
 +
 +As you see from the above sections, GUIs for audio plug-ins are not built according to anything like an MVC pattern. You will, however, find a few spots where MVC-like ideas are applied, the main one being the [[https://docs.juce.com/master/classListBox.html|ListBox]]/[[https://docs.juce.com/master/classListBoxModel.html|ListBoxModel]] pair of classes: to create a scrolling list, you use a //juce::ListBox// component, which is completely generic, and link it to a //juce::ListBoxModel//-derived object which contains the specific data to be listed.
 +
 +==== Plugin Processor and Editor ====
 +JUCE implements a plug-in using a pair of classes:
 +  * The DSP code is called the plug-in //processor// and is derived from [[https://docs.juce.com/master/classAudioProcessor.html|juce::AudioProcessor]]
 +  * The GUI is called the //editor// and is derived from [[https://docs.juce.com/master/classAudioProcessorEditor.html|juce::AudioProcessorEditor]]
 +
 +The //processor// is what is instantiated by a host (e.g. DAW). It has a //createEditor()// method, whose job is to create an instance of the //editor// and return a pointer to it. The editor has a member variable which is a reference to the corresponding processor instance; through this reference, the editor can communicate with the processor, call its methods, get at public member variables, etc. (This is a //convention//, not something which is enforced by the class definitions.)
 +
 +Because the processor can exist alone, i.e., there is no requirement that the host //ever// instantiate the editor, and most hosts actually delete the editor instance each time the user closes the plug-in GUI window, there is no reciprocal arrangement where the processor can get at "the" editor. (There are ways, but they are indirect.) The more common pattern is that the editor (or any of its child components) are set up as //Listeners// of the processor, so they get callbacks when its state changes in a way that requires the GUI to update. The JUCE classes [[https://docs.juce.com/master/classChangeBroadcaster.html|ChangeBroadcaster]] and [[https://docs.juce.com/master/classChangeListener.html|ChangeListener]] are most often used for this.
 +
 +As mentioned above, JUCE's "attachments" mechanism allows GUI controls to be connected directly to the corresponding plug-in parameters (which themselves are embedded in a //juce::AudioProcessorValueTreeState// member variable of the processor). These connections are two-way and work basically automatically.
  
juce_gui_basics.1612807991.txt.gz · Last modified: 2021/02/08 18:13 by shane