0

I have a custom class which extends JPanel and overrides the paintComponent() method. Here's what that looks like:

@Override
protected void paintComponent(Graphics g)
{
    if(redrawRequested)
    {
        g.setColor(ETCH_BACKGROUND_COLOR);
        g.fillRect(0, 0, owner.getAppWidth(), owner.getAppHeight());
        redrawRequested = false;
    }

    g.setColor(Color.BLACK);
    g.fillRect(pointX, pointY, PIXEL_SIZE, PIXEL_SIZE);
}

The same custom class also implements KeyListener. I am listening for some keys, and more specifically Space which calls a method requestRepaint(). Here's what that method looks like:

public void requestRepaint()
{
    redrawRequested = true;
    revalidate();
    repaint();
}

My problem is, when the program starts, whats in the if block inside paintComponent get's fired but the fillRect doesn't work(?) or is not the right color. I have checked my custom color ETCH_BACKGROUND_COLOR and it isn't null and it carries the correct values. Also, the the redrawRequested boolean is true, like I said the if IS BEING FIRED.

I have tried forcing the panel to do a requestRepaint() after the frame is visible, I have tried doing it after a Thread.sleep() and neither accomplishes drawing the background color properly.
The ONLY way I have gotten this to work is when I use AWT's Robot and simulate a key press on the Space key.

Any ideas why this isn't working?

2
Contributors
17
Replies
44
Views
1 Year
Discussion Span
Last Post by JamesCherrill
Featured Replies
  • No, sorry, can't see any problems their either. This is baffling! ps: I see you are defining local constrants to save typing `KeyEvent.` All the time Do you know about `import static`? import static java.awt.event.KeyEvent.*; Then you can just use the public static members from that class without needing to … Read More

0

Have you checked owner.getAppWidth/Height? Maybe those values have not yet been initialised when the panel is painted for the very first time?

Edited by JamesCherrill

0

Yup, I did. They were the correct values.

I added some debug code for some output. Here's the new paintComponent():

@Override
protected void paintComponent(Graphics g)
{
    System.out.println("redrawRequested: " + redrawRequested);
    if(redrawRequested)
    {
        System.out.println("Color: [" + ETCH_BACKGROUND_COLOR.getRed() + ", " + ETCH_BACKGROUND_COLOR.getGreen() + ", " + ETCH_BACKGROUND_COLOR.getBlue() + "]");
        System.out.println("Width: " + owner.getAppWidth() + ", Height: " + owner.getAppHeight());
        g.setColor(ETCH_BACKGROUND_COLOR);
        g.fillRect(0, 0, owner.getAppWidth(), owner.getAppHeight());
        redrawRequested = false;
    }

    g.setColor(Color.BLACK);
    g.fillRect(pointX, pointY, PIXEL_SIZE, PIXEL_SIZE);
}

And here's the output I got:

redrawRequested: true
Color: [200, 200, 175]
Width: 1200, Height: 800
redrawRequested: false
redrawRequested: false

Process finished with exit code 0

Edited by Doogledude123: Added debug code

0

OK. Excellent!

So we would expect to see (some of?) a 1200x800 rectangle coloured in some kind of yucky pale grey/green. What do you actually see?

Edited by JamesCherrill

0

I tried to reproduce your problem I edited your code into a little class

    class MP extends JPanel {

        {
            setSize(400, 400);
        }
        boolean redrawRequested = true;
        Color ETCH_BACKGROUND_COLOR = new Color(200, 200, 175);

        @Override
        protected void paintComponent(Graphics g) {
            System.out.println("redrawRequested: " + redrawRequested);
            if (redrawRequested) {
                System.out.println("Color: [" + ETCH_BACKGROUND_COLOR.getRed() + ", " + ETCH_BACKGROUND_COLOR.getGreen() + ", " + ETCH_BACKGROUND_COLOR.getBlue() + "]");
                System.out.println("Width: " + 1200 + ", Height: " + 800);
                g.setColor(ETCH_BACKGROUND_COLOR);
                g.fillRect(0, 0, 1200, 800);
                redrawRequested = false;
            }
            g.setColor(Color.BLACK);
            g.fillRect(10, 10, 10, 10);
        }
    }

and added a new MP()to a JFrame and it displayed a black small square on a yucky grey/green background.

... which leads me to suspect we are looking in the wrong place?

Edited by JamesCherrill

0

Well, maybe it's an issue with adding it to the JFrame. Here's my application code that is called in the main method like this: new Etch(1200, 800);

private Etch(int initWidth, int initHeight)
{
    appWidth = initWidth;
    appHeight = initHeight;

    JFrame appFrame = new JFrame(APP_NAME + " - " + APP_VERSION);
    appFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    appFrame.setResizable(false);
    appFrame.setPreferredSize(new Dimension(appWidth, appHeight));

    sketchPanel = new SketchPanel(this);

    appFrame.add(sketchPanel);
    appFrame.addKeyListener(sketchPanel);

    appFrame.pack();

    appFrame.setLocationRelativeTo(null);
    appFrame.setVisible(true);

    /*try
    {
        Robot r = new Robot();
        r.keyPress(KeyEvent.VK_SPACE);
        r.keyRelease(KeyEvent.VK_SPACE);
    }
    catch(AWTException e)
    {
        e.printStackTrace();
    }*/
}

public int getAppWidth()
{
return appWidth;
}

public int getAppHeight()
{
return appHeight;
}
0

Here's the full SketchPanel class.

package com.geodox.etch;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

/**
 * Panel which controls drawing and handles key events
 *
 * Created by GeoDoX on 2015-10-05.
 */
public class SketchPanel extends JPanel implements KeyListener
{
    private static final int PIXEL_SIZE = 6;
    private static final Color ETCH_BACKGROUND_COLOR = new Color(200, 200, 175);

    private static final int ARROW_UP = KeyEvent.VK_UP;
    private static final int ARROW_LEFT = KeyEvent.VK_LEFT;
    private static final int ARROW_DOWN = KeyEvent.VK_DOWN;
    private static final int ARROW_RIGHT = KeyEvent.VK_RIGHT;
    private static final int W = KeyEvent.VK_W;
    private static final int A = KeyEvent.VK_A;
    private static final int S = KeyEvent.VK_S;
    private static final int D = KeyEvent.VK_D;
    private static final int CLEAR = KeyEvent.VK_SPACE;

    private EtchASketch owner;

    private int pointX, pointY;
    private boolean redrawRequested;

    protected SketchPanel(EtchASketch owner)
    {
        this.owner = owner;
        redrawRequested = true;

        pointX = 0;
        pointY = 0;
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        System.out.println("redrawRequested: " + redrawRequested);
        if(redrawRequested)
        {
            System.out.println("Color: [" + ETCH_BACKGROUND_COLOR.getRed() + ", " + ETCH_BACKGROUND_COLOR.getGreen() + ", " + ETCH_BACKGROUND_COLOR.getBlue() + "]");
            System.out.println("Width: " + owner.getAppWidth() + ", Height: " + owner.getAppHeight());
            g.setColor(ETCH_BACKGROUND_COLOR);
            g.fillRect(0, 0, owner.getAppWidth(), owner.getAppHeight());
            redrawRequested = false;
        }

        g.setColor(Color.BLACK);
        g.fillRect(pointX, pointY, PIXEL_SIZE, PIXEL_SIZE);
    }

    @Override
    public void keyPressed(KeyEvent e)
    {
        int tempX = pointX, tempY = pointY;

        switch (e.getKeyCode())
        {
            case ARROW_UP:
            case W:
                if(isInBounds(pointX, pointY - PIXEL_SIZE))
                    pointY -= PIXEL_SIZE;
                break;
            case ARROW_LEFT:
            case A:
                if(isInBounds(pointX - PIXEL_SIZE, pointY))
                    pointX -= PIXEL_SIZE;
                break;
            case ARROW_DOWN:
            case S:
                if(isInBounds(pointX, pointY + PIXEL_SIZE))
                    pointY += PIXEL_SIZE;
                break;
            case ARROW_RIGHT:
            case D:
                if(isInBounds(pointX + PIXEL_SIZE, pointY))
                    pointX += PIXEL_SIZE;
                break;
            case CLEAR:
                requestRepaint();
                break;
        }

        if(tempX != pointX || tempY != pointY || redrawRequested)
            requestRepaint();
    }

    @Override
    public void keyReleased(KeyEvent e)
    {

    }

    @Override
    public void keyTyped(KeyEvent e)
    {

    }

    public void requestRepaint()
    {
        redrawRequested = true;
        revalidate();
        repaint();
    }

    private boolean isInBounds(int x, int y)
    {
        return x >= 0 && x <= owner.getAppWidth() && (y >= 0 && y <= owner.getAppHeight());
    }
}
1

No, sorry, can't see any problems their either. This is baffling!

ps: I see you are defining local constrants to save typing KeyEvent. All the time
Do you know about import static?

import static java.awt.event.KeyEvent.*;

Then you can just use the public static members from that class without needing to qualify them. eg case VK_UP;

It's not just the save of time/space. You shoiuld assume that somene treading yur code knows the relevant Java, so VK_SPACE will be recognised but CLEAR could be anything.

Votes + Comments
Nice tip with the static, I do know it so I'm not sure why I didn't bother using it.
0

Just another long-shot guess...

Try setting the size of the SketchPanel in its constructor - JPanels tend to be 0,0 size until you put something in them or use a parent's layout manager that sets their size.

0

What makes this all the more annoying is that your code is so beautifully written and presented. Anything that professional really should work!

0

Could it possibly be that I'm setting the sketchpanel to be the JFrames KeyListener, and also adding it as a component?

This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.