0

I'm new to GUI programming and I tried out some code and wanted to constantly change the background of a JPanel called "HeaderPanel".

Why isnt this working as I wished? (Color stays the same...)

private void changeColors() {
    int r = 0;
    int g = 155;
    int b = 12;

    while(true) {
        r = (r+1)%255;
        g = (g+1)%255;
        b = (b+1)%255;

        Color color = new Color(r,g,b);
        HeaderPanel.setBackground(color);
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
AirUp
  • 426
  • 1
  • 8
  • 18

3 Answers3

3

Your while loop is stopping the repaint manager from ever getting around to changing the colors.

You need to, some how, execute the request in the background, something like this

public class TestLabel extends JLabel {

    private Timer timer;

    private int r = 0;
    private int g = 155;
    private int b = 12;

    public TestLabel() {

        setText("Hello world");
        setOpaque(true);

        timer = new Timer(1000, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                System.out.println("tick");

                r = (r + 1) % 255;
                g = (g + 1) % 255;
                b = (b + 1) % 255;

                Color color = new Color(r, g, b);
                setBackground(color);

                System.out.println(color);

                if (r == 0 && b == 0 && g == 0) {

                    r = 0;
                    g = 155;
                    b = 12;

                }

                invalidate();
                revalidate();
                repaint();

            }
        });

        timer.setRepeats(true);
        timer.setCoalesce(true);
        timer.start();

    }
}

You might like to read up on

UPDATED with Extended Example

public class TestLabel extends JLabel {

    private Timer timer;

    private Object[][] colors = {{"Black", Color.BLACK},
        {"Blue", Color.BLUE},
        {"Cyan", Color.CYAN},
        {"Dark Gray", Color.DARK_GRAY},
        {"Gray", Color.GRAY},
        {"Green", Color.GREEN},
        {"Light Gary", Color.LIGHT_GRAY},
        {"Mangenta", Color.MAGENTA},
        {"Orange", Color.ORANGE},
        {"Pink", Color.PINK},
        {"Red", Color.RED},
        {"White", Color.WHITE},
        {"Yellow", Color.YELLOW}};

    public TestLabel() {

        setText("Hello world");
        setOpaque(true);

        timer = new Timer(1000, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                System.out.println("tick");

                int index = (int) Math.round((colors.length - 1) * Math.random());

                Object[] group = colors[index];

                setBackground((Color)group[1]);
                setText((String)group[0]);

            }
        });

        timer.setInitialDelay(0);
        timer.setRepeats(true);
        timer.setCoalesce(true);
        timer.start();

    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • 1
    I'm quite sure that [invalidate(); (re)validate, repaint()](http://stackoverflow.com/questions/6368160/how-to-convert-icon-from-jlabel-into-bufferedimage) is never needed in Java6 and higher ... for JLabel on EDT – mKorbel Aug 11 '12 at 01:03
  • @mKorbel your probably right, I'm old school (Java 1.3) and the color change was subtle I wanted to make sure it was been updated :P – MadProgrammer Aug 11 '12 at 01:06
  • pssst don't talking about nothing JLabel required (only) repaint() for MouseMotionListener, otherwise any changes .... :-), lost in API, somebody to forgot to add this code line :-) – mKorbel Aug 11 '12 at 01:09
  • +1 for using `setOpaque()`, the only thingy many a programmers miss, while setting colour to a particular `JComponent`, though as suggested by @mKorbel , those thingies are really not needed, Opaque property is enough :-) – nIcE cOw Aug 11 '12 at 03:58
  • -1 as an incentive to remove the noise ;-) There's enough bad example code around that randomly and unnecessarily calls x-validate/paint ... – kleopatra Aug 11 '12 at 08:23
  • I tried this now with Threads and .setText() on a JLabel, that was working correctly as I wished and constantly updated. But the changing backgroundcolor will still not work, even not with threads. But I ll get behind it... – AirUp Aug 11 '12 at 10:41
  • @BlackCurrant check out the extended example, it still works for me. The color shift of your OP is VERY slight, hence the reason I'm getting in trouble ;). I would *AVOID* using `Thread`s for this as it's just a lot more work then is required. `javax.swing.Timer` will take care of the `EventQueue` synchronization for you. – MadProgrammer Aug 11 '12 at 21:03
0

I'm not a swing developer, but don't you have to "repaint" or something like that when you change the color property? In the other hand, you will need another thread to keep updating the colors.

Summarizing

  • A code to change the panel background color (include repaint)
  • A thread to invoke the above code.
psabbate
  • 767
  • 1
  • 5
  • 22
  • That was my first thought, too. – AirUp Aug 10 '12 at 23:59
  • no, typically no repaint needed on changing the base properties. And when in doubt, don't assume but read the source :-) And no, you certainly don't want a thread other than the EDT to access those properties. – kleopatra Aug 11 '12 at 08:30
  • Kleopatra, according to the example code from Curzon,seems that he needs a background task.So if you need to change the color based on time or in another non-user event, you definitely must add a thread. – psabbate Aug 15 '12 at 16:13
-1

You need to tell your JPanel to paint itself, probably by calling invalidate().

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268