Problem with adding background colors using BorderLayout

Hello, my problem is as follows:

Firstly I want a background which is created using something like the following:

GradientPaint ii =new GradientPaint(0, 0, Color.white, d.width, d.height, Color.darkGray);

To create a faded effect accross the background of the main cotent of my JFrame, however it doesn't seem to let me do this using the standard frame.setBackground() method. So I tried making a seperate component and then adding it to the frame by doing something like this:

CenterBackground cb =new CenterBackground();//my background component

frame.add(cb, BorderLayout.CENTER);

This works fine, but then when I want to place my other graphics component ontop of this that moves about, which is simply just a little square created in a seperate graphics cpt class, and I also want to place that on the center doing like this:

graphicsCpt =new BallComponent();

this.add(graphicsCpt, BorderLayout.CENTER);

It places that over the top of it and my background disapears and I get a standard background instead of my chosen one.

You may ask why don't I just do the background and my ball in the same graphics cpt class, but if I do this when I move my ball around using button and ActionListener handlers the whole background moves aswell, which is obviously not good, so could someone give me a solution?

[1509 byte] By [tranquility2k4a] at [2007-11-26 15:42:12]
# 1

The center section of your BorderLayout can only have one component at a time. Adding the second component causes the first one to be removed.

You can make your gradient background into an image, draw the image and then draw your animation on top of it.

import java.awt.*;

import java.awt.geom.*;

import java.awt.image.BufferedImage;

import javax.swing.*;

public class Background extends JPanel {

BufferedImage image;

Ellipse2D.Double ball;

protected void paintComponent(Graphics g) {

Graphics2D g2 = (Graphics2D)g;

g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

RenderingHints.VALUE_ANTIALIAS_ON);

if(image == null)

initImage();

g2.drawImage(image, 0, 0, this);

g2.setPaint(Color.red);

g2.fill(ball);

}

private void initImage() {

int w = getWidth();

int h = getHeight();

int type = BufferedImage.TYPE_INT_RGB;

image = new BufferedImage(w, h, type);

Graphics2D g2 = image.createGraphics();

GradientPaint gradient = new GradientPaint(0, 0, Color.white,

w, h, Color.darkGray);

g2.setPaint(gradient);

g2.fillRect(0,0,w,h);

g2.dispose();

// initialize ball

int d = Math.min(w,h)/4;

ball = new Ellipse2D.Double(w/3, h/4, d, d);

}

public static void main(String[] args) {

JFrame f = new JFrame();

f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

f.getContentPane().add(new Background());

f.setSize(400,400);

f.setLocation(200,200);

f.setVisible(true);

}

}

crwooda at 2007-7-8 22:00:57 > top of Java-index,Security,Cryptography...
# 2

Thank you ever so much for your reply, it is very helpful although my problem still kind of exists, when im moving around the ball using buttons and ActionListeners, inside the updateGUI(); method in my main GUI frame class, which is called when I press the button, I make an instance of the graphicsCpt, then change the co-ordinates of that appropriately by using something like:

graphicsCpt.setLocation(xcord,ycord);

So it moves the whole graphics co-ordinate, in otherwords if I make the background and the ball in the same component the whole background moves aswell, which obviously I don't want to happen, do you know a solution to this?

tranquility2k4a at 2007-7-8 22:00:57 > top of Java-index,Security,Cryptography...
# 3

So it moves the whole graphics co-ordinate, in otherwords if I make the background and

the ball in the same component the whole background moves aswell

I don't have a clear understanding of what you are describing. Sounds like you are

animating (moving) the ball with your event code. And it looks like you have made the ball

a Component. I still don't understand the part about the background moving unless you are

shifting the graphics context around instead of the ball itself, ie, moving the whole

graphics context relative to its parent component instead of moving the ball within the

graphics context. Here is a simple animation for comparison. Your button/event code would

call the advance method (or something similar along these lines). The ball is moved within

the graphics context which is stationary.

import java.awt.*;

import java.awt.geom.*;

import java.awt.image.BufferedImage;

import javax.swing.*;

public class Background2 extends JPanel {

BufferedImage image;

Ellipse2D.Double ball;

int dx = 3;

int dy = 2;

public void advance() {

if(ball == null) return;

checkBoundries();

double x = ball.x + dx;

double y = ball.y + dy;

ball.setFrameFromDiagonal(x, y, x+ball.width, y+ball.height);

repaint();

}

private void checkBoundries() {

if(ball.x + dx < 0 || ball.x + ball.width + dx > getWidth())

dx *= -1;

if(ball.y + dy < 0 || ball.y + ball.height + dy > getHeight())

dy *= -1;

}

protected void paintComponent(Graphics g) {

Graphics2D g2 = (Graphics2D)g;

g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

RenderingHints.VALUE_ANTIALIAS_ON);

if(image == null)

initImage();

g2.drawImage(image, 0, 0, this);

g2.setPaint(Color.red);

g2.fill(ball);

}

private void initImage() {

int w = getWidth();

int h = getHeight();

int type = BufferedImage.TYPE_INT_RGB;

image = new BufferedImage(w, h, type);

Graphics2D g2 = image.createGraphics();

GradientPaint gradient = new GradientPaint(0, 0, Color.white,

w, h, Color.darkGray);

g2.setPaint(gradient);

g2.fillRect(0,0,w,h);

g2.dispose();

// initialize ball

int d = Math.min(w,h)/6;

ball = new Ellipse2D.Double(w/3, h/4, d, d);

}

public static void main(String[] args) {

Background2 test = new Background2();

BallHandler handler = new BallHandler(test);

JFrame f = new JFrame();

f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

f.getContentPane().add(test);

f.setSize(400,400);

f.setLocation(200,200);

f.setVisible(true);

handler.start();

}

}

class BallHandler implements Runnable {

Background2 component;

Thread thread = null;

boolean running = false;

public BallHandler(Background2 b2) {

component = b2;

}

public void run() {

while(running) {

try {

Thread.sleep(50);

} catch(InterruptedException e) {

System.out.println("interrupted");

stop();

}

component.advance();

}

}

public void start() {

if(!running) {

running = true;

thread = new Thread(this);

thread.setPriority(Thread.NORM_PRIORITY);

thread.start();

}

}

private void stop() {

running = false;

if(thread != null)

thread.interrupt();

thread = null;

}

}

If I am way off from understanding you then I would suggest posting some code that shows

the behavior.

crwooda at 2007-7-8 22:00:57 > top of Java-index,Security,Cryptography...
# 4

Say for instance I have this for my graphicsCpt, which contains a small box im moving around and also a kinda background gradient colouring:

import java.awt.*; //colours, Paint, and Shape interfaces

import java.awt.geom.*;//for shapes: Line, Ellipse etc

import javax.swing.*;//Various GUI components and widgets

import javax.swing.border.LineBorder;

public class BoxComponent extends JComponent{

private Rectangle2D box;

public int shapeH=30;

public int shapeW=30;

public int xHome=60;

public int yHome=60;

public BoxComponent() {

//this.setPreferredSize(new Dimension(200,200));

//this.setBorder(new LineBorder(Color.red, 2));

box = new Rectangle2D.Double(xHome,yHome,shapeW,shapeH);

}

public void paintComponent(Graphics g) {

super.paintComponent(g);

Graphics2D g2 = (Graphics2D) g; //g is a Graphics2D object

//- Paint the background.--

/* This is done by drawing and filling a rectangle the same size

as the component.*/

//get the current dimensions, as the copmpoinent may have been re-sized

// Dimension d = this.getSize();

//set the fill color.

//g2.setPaint(new GradientPaint(0, 0, Color.white, d.width, d.height, Color.darkGray));

//Create an draw a 'filled' rectangle.

//g2.fill(new Rectangle2D.Float(0,0,d.width,d.height));

//draw the ball

//choose the paint colour

g2.setPaint(Color.orange);

//draw the shape using draw(ball) (-outline only) or fill(e) (-coloured in).

g2.fill(box);

}

I then have an updateGUI() method which is called from inside the ActionPerformed method which lays inside the event handling actionlistener of the button. Heres the updateGUI() method

public void updateGUI(int x, int y){

// does aload of stuff by looking at the x and y parameters sent and calculates where to move then puts it into variables xcord and ycord

// NOW this IS THE CRUCIAL BIT, here, I do the graphics cpt.setLocation and move it then repaint, and what it effectivly does is not just move the box (rectangle2D) but also the gradiaent background colouring I made for that component

graphicsCpt.setLocation(xcord,ycord);

repaint();

}

So what im effectivly trying to acheive is using that gradient paint in a component and having it fixed so it doesn't move and just the component does, I would like to use that setLocation method for simplicity of what im trying to acheive aswell.

I also tried creating 2 different components, 1 for the small box im moving around and 1 for gradient paint background but with layoutManager in java.awt and usin BorderLayout, it only lets you have 1 component in the center place, any other placed will replace the previous. Therefore from my knowledge I can only just get a standard colour background for the main frame >.<;

tranquility2k4a at 2007-7-8 22:00:57 > top of Java-index,Security,Cryptography...
# 5

import java.awt.*;

import java.awt.event.*;

import java.awt.geom.Rectangle2D;

import javax.swing.*;

public class CompAnim implements ActionListener {

GradientHost gradientHost;

BoxComp boxComp;

int dx = 3;

int dy = 2;

public void actionPerformed(ActionEvent e) {

moveBox();

}

private void moveBox() {

Rectangle parentBounds = gradientHost.getBounds();

Rectangle boxBounds = boxComp.getBoxBounds();

// boxBounds gives us the size and location of the Rectangle2D box

// within its parent component boxComp. We want to get the size and

// location of this Rectangle2D box in relation to gradientHost so

// we can use the information for boundry checking. In other words,

// we want to convert the bounds of the Rectangle2D box to the

// gradientHost coordinate system (its parents parent).

boxBounds = SwingUtilities.convertRectangle(boxComp, boxBounds, gradientHost);

//System.out.printf("parentBounds = [%3d, %3d, %3d, %3d]%n" +

//"boxBounds= [%3d, %3d, %3d, %3d]%n",

//parentBounds.x, parentBounds.y, parentBounds.width,

//parentBounds.height, boxBounds.x, boxBounds.y,

//boxBounds.width, boxBounds.height);

checkBoundries(parentBounds, boxBounds);

int x = boxComp.getX() + dx;

int y = boxComp.getY() + dy;

boxComp.setLocation(x, y);

}

private void checkBoundries(Rectangle out, Rectangle in) {

if(in.x + dx < out.x || in.x + in.width + dx > out.x + out.width)

dx *= -1;

if(in.y + dy < out.y || in.y + in.height + dy > out.y + out.height)

dy *= -1;

}

private Container getContent() {

boxComp = new BoxComp();

Dimension d = boxComp.getPreferredSize();

gradientHost = new GradientHost();

gradientHost.setLayout(null);

gradientHost.add(boxComp);

boxComp.setBounds(100, 100, d.width, d.height);

return gradientHost;

}

private JPanel getLast() {

JButton button = new JButton("move");

button.addActionListener(this);

JPanel panel = new JPanel();

panel.add(button);

return panel;

}

public static void main(String[] args) {

CompAnim test = new CompAnim();

JFrame f = new JFrame();

f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

f.getContentPane().add(test.getContent());

f.getContentPane().add(test.getLast(), "Last");

f.setSize(400,400);

f.setLocation(200,200);

f.setVisible(true);

}

}

class GradientHost extends JPanel {

protected void paintComponent(Graphics g) {

// As long as we continue to fill all of the surface of

// this component with opaque color we do not need to

// ask Swing to do it (with super.paintComponent(g)).

Graphics2D g2 = (Graphics2D)g;

int w = getWidth();

int h = getHeight();

GradientPaint gradient = new GradientPaint(0, 0, Color.white,

w, h, Color.darkGray);

g2.setPaint(gradient);

g2.fillRect(0,0,w,h);

}

}

class BoxComp extends JComponent{

private Rectangle2D box;

public int shapeH=30;

public int shapeW=30;

public int xHome=60;

public int yHome=60;

public BoxComp() {

setPreferredSize(new Dimension(200,200));

// This is useful to observe the boundries of this

// component inside its parent container.

//setBorder(BorderFactory.createEtchedBorder());

box = new Rectangle2D.Double(xHome,yHome,shapeW,shapeH);

}

protected void paintComponent(Graphics g) {

// JComponent is non-opaque which means that the next

// non-opaque parent in its component hierarchy will

// do the drawing of this component.

// Therefore, this next line is not neccessary.

//super.paintComponent(g);

Graphics2D g2 = (Graphics2D) g;

g2.setPaint(Color.orange);

g2.fill(box);

}

public Rectangle getBoxBounds() {

return box.getBounds();

}

}

crwooda at 2007-7-8 22:00:57 > top of Java-index,Security,Cryptography...