Adding Background Image - October 2019! [SOLVED] by cpr

Hi,

I’m new to JUCE and have been reading a lot the API and Threads on how to add a background image, I see no clear definitive answer to this question.

I have tried a few things that have been ‘SOLVED’ related to adding background image,
nothing works …judging by the screenshoots provided, seems the persons answering are using the old version/API.

Please can someone kindly tell me step by step how to add background image to my window.
using the latest JUCE 2019 API.

Many thanks,
Bubs

Here is the most straight forward method, which uses an ImageComponent. The other method is to draw it directly in the paint() method.
Add the image to the Projucer project, and use code similar to this:

class ExampleComponent : public Component
{
public:
    ExampleComponent ()
    {
        backgroundImage.setImage (ImageCache::getFromMemory (BinaryData::temp_song_image_1_png, BinaryData::temp_song_image_1_pngSize));
        // apply placement flags if needed (https://docs.juce.com/master/classRectanglePlacement.html)
        backgroundImage.setImagePlacement (RectanglePlacement (RectanglePlacement::stretchToFit));
        // add this first so it is furthest back in z order
        addAndMakeVisible (backgroundImage);

        // add other components
    }
private:
    ImageComponent backgroundImage;

    void resized () override
    {
        backgroundImage.setBounds (getLocalBounds ());

        // positioning and size your other components
    }
};

For completeness, here is the paint() version:

class ExampleComponent : public Component
{
public:
    ExampleComponent ()
    {
        backgroundImage = ImageCache::getFromMemory (BinaryData::temp_song_image_1_png, BinaryData::temp_song_image_1_pngSize);
    }
private:
    Image backgroundImage;

    void paint (Graphics& g) override
    {
        g.drawImage (backgroundImage, getLocalBounds ().toFloat ());
    }
};
1 Like

Hey thank you very much for replying to me! appreciated!

This part is tripping me and many people up cpr!

What I’m doing is this, step by step:

  1. dragging my image.png file into projucer source folder.
  2. checking that BinaryResource and Compile checkboxes are ticked when selecting ‘Source’ folder.

Main.CPP
/*
==============================================================================

    This file was auto-generated!

    It contains the basic startup code for a JUCE application.

  ==============================================================================
*/

#include "../JuceLibraryCode/JuceHeader.h"
#include "MainComponent.h"

//==============================================================================
class ImageApplication  : public JUCEApplication
{
public:
    //==============================================================================
    ImageApplication() {}

    const String getApplicationName() override       { return ProjectInfo::projectName; }
    const String getApplicationVersion() override    { return ProjectInfo::versionString; }
    bool moreThanOneInstanceAllowed() override       { return true; }

    //==============================================================================
    void initialise (const String& commandLine) override
    {
        // This method is where you should put your application's initialisation code..

        mainWindow.reset (new MainWindow (getApplicationName()));
    }

    void shutdown() override
    {
        // Add your application's shutdown code here..

        mainWindow = nullptr; // (deletes our window)
    }

    //==============================================================================
    void systemRequestedQuit() override
    {
        // This is called when the app is being asked to quit: you can ignore this
        // request and let the app carry on running, or call quit() to allow the app to close.
        quit();
    }

    void anotherInstanceStarted (const String& commandLine) override
    {
        // When another instance of the app is launched while this one is running,
        // this method is invoked, and the commandLine parameter tells you what
        // the other instance's command-line arguments were.
    }
    
    class ExampleComponent : public Component
{
public:
    ExampleComponent ()
    {
        backgroundImage.setImage (ImageCache::getFromMemory (BinaryData::**image_png**, BinaryData::**image_pngSize**));
        
        backgroundImage.setImagePlacement (RectanglePlacement (RectanglePlacement::stretchToFit));
        // add this first so it is furthest back in z order
        addAndMakeVisible (backgroundImage);

        // add other components
    }
private:
    ImageComponent backgroundImage;

    void resized () override
    {
        backgroundImage.setBounds (getLocalBounds ());

        // positioning and size your other components
    }
};

    //==============================================================================
    /*
        This class implements the desktop window that contains an instance of
        our MainComponent class.
    */
    class MainWindow    : public DocumentWindow
    {
    public:
        MainWindow (String name)  : DocumentWindow (name,
                                                    Desktop::getInstance().getDefaultLookAndFeel()
                                                                          .findColour (ResizableWindow::backgroundColourId),
                                                    DocumentWindow::allButtons)
        {
            setUsingNativeTitleBar (true);
            setContentOwned (new MainComponent(), true);

           #if JUCE_IOS || JUCE_ANDROID
            setFullScreen (true);
           #else
            setResizable (true, true);
            centreWithSize (getWidth(), getHeight());
           #endif

            setVisible (true);
        }

        void closeButtonPressed() override
        {
            // This is called when the user tries to close this window. Here, we'll just
            // ask the app to quit when this happens, but you can change this to do
            // whatever you need.
            JUCEApplication::getInstance()->systemRequestedQuit();
        }

        /* Note: Be careful if you override any DocumentWindow methods - the base
           class uses a lot of them, so by overriding you might break its functionality.
           It's best to do all your work in your content component instead, but if
           you really have to override any DocumentWindow methods, make sure your
           subclass also calls the superclass's method.
        */

    private:
        JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow)
    };

private:
    std::unique_ptr<MainWindow> mainWindow;
};

//==============================================================================
// This macro generates the main() routine that launches the app.
START_JUCE_APPLICATION (ImageApplication)

doing the above still does not work for me, using your class implementation?
/Bubs

Remove my code from ExampleComponent, and put it into MainComponent. I just created that component to show you how you add a background image to ANY component. Btw, the paint() version is slightly more robust, as you don’t have to worry about the other child components ever being behind your background image.

I’m getting the idea that you are learning C++ at the same time you are learning JUCE? :wink: This will likely prove to be frustrating to you, as you will continue to have difficulty in taking advice from the forum and using it.

In this case, you take the code from the constructor in ExampleComponent (ExampleComponent::ExampleComponent) and put it in the constructor in MainComponent (MainComponent::MainComponent). And the code from ExampleComponent::paint(Graphics& g) and put it in MainComponent::paint(Graphics& g).

hehe, thanks - no hard feelings! :slight_smile:
I’m a C++ modem engineer by trade so I should know better!

…Still not working cpr - complains “use of undefined identifier ‘backgroundImage’”

MainComponent.CPP
#include “MainComponent.h”

//==============================================================================
MainComponent::MainComponent()
{
    setSize (600, 400);
    **backgroundImage = ImageCache::getFromMemory (BinaryData::**image_png**, BinaryData::**image_pngSize**);**
    
}

MainComponent::~MainComponent()
{
}

//==============================================================================
void MainComponent::paint (Graphics& g)
{
    // (Our component is opaque, so we must completely fill the background with a solid colour)
    g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));

    g.setFont (Font (16.0f));
    g.setColour (Colours::white);
    g.drawText ("Hello World!", getLocalBounds(), Justification::centred, true);
    **g.drawImage (backgroundImage, getLocalBounds ().toFloat ());**

void MainComponent::resized()
{
    // This is called when the MainComponent is resized.
    // If you add any child components, this is where you should
    // update their positions.
}

OK IT WORKS! :slight_smile:

THANK YOU!

For those interested there is complete setup!

Thank again cpr …really appreciated Mr!

**MainComponent.h**

**class** MainComponent : **public** Component

{

**public** :

//==============================================================================

MainComponent();

~MainComponent();

**void** paint (Graphics&) **override** ;

**void** resized() **override** ;

**Image backgroundImage;** .  << HERE

**private** :

//==============================================================================

// Your private member variables go here...

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)

};

**MainComponent.CPP**

MainComponent::MainComponent()
{
    setSize (600, 400);
    **backgroundImage = ImageCache::getFromMemory (BinaryData::image_png, BinaryData::image_pngSize);** << HERE
}
.
.
.

void MainComponent::paint (Graphics& g)
{
    // (Our component is opaque, so we must completely fill the background with a solid colour)
    g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));

    g.setFont (Font (16.0f));
    g.setColour (Colours::white);
    g.drawText ("Hello World!", getLocalBounds(), Justification::centred, true);
    **g.drawImage (backgroundImage, getLocalBounds ().toFloat ());** . << HERE
}

FYI, surrounding any code with three back ticks ` on their own lines, or select the code and hitting the “pre-formatted code” button image will make everything more readable. eg:

int anInteger = 0;
someMethod();

or if you want to just write something inline you can surround the thing you wanted inline with a single back-tick. :slight_smile:

OK noted! thank you Richie

1 Like