Beginner's help with a GUI window

Hi!

Let me start with a brief introduction:

Limited c++ knowledge, limited programming experience/knowledge… but do please try and help anyways!

Just successfully installed Juce + Visual Studio 2019 and compiled the basic GUI window.

I’m add two functions to the basic GUI project (which is literally just a window) ATM:

-repeating timed function
-read .txt document (inside timed function)

I’ve spent an embarrassing amount of time on the interweb trying scavenge pre-written code, but to no avail. I realize that I should “go learn c++ you newb,” but I would very much appreciate a little “booster” help with this particular function.

Really, if someone would provide me with a resource that they feel combined with Juce documentation would help me to create an interval timer function myself that would be fantastic.

One such instance of a thread I’ve read would be this one:

I tried strategically placing the code into my project, but it does not work. I’m sure there are multiple reasons why, and I’m trying to get to the bottom of this.

This is a very broad description, if you supply more information on what exactly you want to achieve and especially what you already tried / how your current (non-working) approach looks like, you’ll likely get some better help :slight_smile: Useful information to help you could be:

  • What should happen with the content you read from your text file (print to the console, display in your GUI, process and write back to another file…)
  • How should your app know about the location of your file? Some file opening dialogue, some resource folder or a file inside your app bundle. Spoiler: A hard coded file path should be avoided…
  • At what update rate should your repeated function be called? Do you expect the file content to be changed in between or what’s the motivation of doing it repeated?

First steps should always be to look for a suitable JUCE tutorial. Does the File reading tutorial contain useful information for you?

Then if you want to try something yourself, useful JUCE classes for you might be:

  • Timer (Execute a function repeated on the message thread)
  • HighResolutionTimer (Execute an exactly timed repeated function on its own thread)
  • The File class to handle all kinds of file paths
  • The FilenameComponent or FileChooser to open a file via a gui dialogue
  • The FileInputStream as a possibility to read from an opened file
1 Like

Thank you for your response!

One thing I tried to make clear (and obviously failed lol) is that I’m trying to focus on the timed interval function first, before I worry about file/.txt reading.

To further explain myself about the timer function, All I’m trying to wrap my head around and create is very similar to the gentleman in the thread I linked…

I’d like a function that simply repeats itself over a given interval of time. Preferably, just for fun, it would popup a message every few seconds, so that I can see and know it is working as desired…

Alright. Above you said

And that is 100% right – if you understand the language it will become obvious how you should handle most JUCE classes. However, why not starting to learn C++ by this? I’ll try to mention the topics you need to know to come up with that solution by yourself and I’d advise you to look them up step by step to understand each line of code you write instead of copy & pasting. Here we go.

For most applications, the Timer class is what you need, so we will use it here. It is called from the message thread. The message thread is the thread, that keeps any GUI application up and running and is the only thread that should handle GUI actions. So first thing to put on your list for further research (not really C++ related but for GUI apps in general):

  • Message thread

If we have a look at the Timer documentation we see that it is a class with one pure virtual function void timerCallback() (you see that it is pure virtual by the = 0). A pure virtual function is a function, that the implementation has to supply by inheriting from the base class that defines it. A base Timer object on it’s own can’t be created, because the virtual function is not defined, so we need to define our own class, that inherits from timer. So the next thing you should look up is

  • Inheritance in C++

Create an empty GUI application with the Projucer. For now, let’s put our custom class implementation in a new header file, which you should add to the project via the Projucer. In this example I named it MyTimer.h and it has the following content:

#pragma once
#include <JuceHeader.h>

class MyTimer : public Timer
{
public:

    void timerCallback() override
    {
        constexpr bool shouldShowOkCancelButtons = false;

        AlertWindow::showNativeDialogBox ("Timer callback",
                                          "This dialogue has been created on the timer callback",
                                          shouldShowOkCancelButtons);

    }
};

So what is happening here? We declare a new class with the name MyTimer. We say that it should inherit Timer, this means that our class will be a variation of the base class Timer. By declaring the inheritance public, each class outside can see that it inherits Timer and call every member function the Timer base class has.
To make the most interesting part work, the periodically called piece of code, we override the pure virtual function void timerCallback(). This function will be called over and over once the timer is running. In the function body, I simply placed a call to the JUCE AlertWindow class that creates a dialog box window with a given text. The third argument makes sure that it only has an ok button, which you can click to make it disappear. By the way, the syntax AlertWindow::showNativeDialogBox with the two :: shows you that showNativeDialogBox is a static function of the AlertWindow class, this means you don’t need to create some AlertWindow object to call it. So for your list of topics to learn add

  • static vs. non-static member functions and member variables

Now after the class has been declared, the application actually needs an instance of it – because the timer callback is no static member :wink: The easiest way is to add it as a private member to your Projucer-generated MainComponent class:

#pragma once

#include <JuceHeader.h>
#include "MyTimer.h"

class MainComponent   : public Component
{
public:
    //==============================================================================
    MainComponent();
    ~MainComponent();

    //==============================================================================
    void paint (Graphics&) override;
    void resized() override;

private:
    //==============================================================================
    MyTimer timer1;


    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)
};

I basically added two lines: #include "MyTimer.h", which makes sure that the declaration created above is “known” as we want to use it here. The second line is the private member MyTimer timer1; so the Main component now has an instance of the timer class declared above we can now use. If we now add something like
timer1.startTimer (5000); to the main components constructor and timer1.stopTimer(); to the destructor, you’ll start the timer when starting the application and stopping it when the app is closed.

Hope that helped you a bit to get started with all!

2 Likes

You, Sir, are incredible. Thank you.

You broke this down to the perfect level for me, and have given me a running start and an inspirational boost to learn more c++, is it is most definitely daunting to a beginner.

Thank you!

2 Likes