Please help with a drawing on JPanel in a background.

Hello everybody,

I have already post this question in the main java forum and was adviced to place the question here. Since then, I have refactored the code. I need your opinion and advice.

My task is to draw some objects on the JPanel or some other components and to place the names to the objects, for example squares, but later, from the thread. Because it can take some time, untill the names will be avaliable.

So, I refactored the code I post before http://forum.java.sun.com/thread.jspa?threadID=5192586&tstart=15

And now, it draws on layers and from thread on resize, with some imitating interval.

Is it a good approach I use, is there a better way, to draw on JPanel, after some objects were already painted.

Here is my sample, try to resize window:

package test;

import java.awt.BorderLayout;

import java.awt.Color;

import java.awt.Dimension;

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.Point;

import java.awt.Rectangle;

import java.awt.event.ComponentEvent;

import java.awt.event.ComponentListener;

import java.awt.geom.Rectangle2D;

import javax.swing.JFrame;

import javax.swing.JLayeredPane;

import javax.swing.JPanel;

publicclass Painterextends JFrameimplements ComponentListener{

privatestaticfinallong serialVersionUID = 1;

private ThreadPainter threadPainter;

JPanel panel =new JPanel(){

privatestaticfinallong serialVersionUID = 1;

@Override

protectedvoid paintComponent(Graphics g){

super.paintComponent(g);

System.out.println("repaint");

Graphics2D g2d = (Graphics2D) g;

g2d.setColor(Color.gray);

g2d.fillRect(0, 0, 800, 600);

g2d.setColor(Color.white);

for (int i = 0; i < 6; i++){

Rectangle2D rec2d =new Rectangle2D.Double(10 + i * 100,

10 + i * 100, 10, 10);

g2d.fill(rec2d);

g2d.drawString("Square " + i, 10 + i * 100 + 20, 10 + i * 100);

}

// start thread to paint some changes later

if (threadPainter ==null){

threadPainter =new ThreadPainter();

threadPainter.start();

}

}

};

JPanelTest panel1 =new JPanelTest();

publicclass JPanelTestextends JPanel{

privatestaticfinallong serialVersionUID = 1;

privateint times = 0;

@Override

protectedvoid paintComponent(Graphics g){

super.paintComponent(g);

Graphics2D g2d = (Graphics2D) g;

g2d.setColor(Color.red);

System.out.println("repaint panel test");

System.out.println("repaitn times");

g2d.drawString("Square " + times, 10 + times * 100 + 20, 10 + times * 100);

}

publicvoid repaintMethod(int times){

this.times = times;

this.repaint(times * 100 + 20, times * 100, 300,300);

};

};

publicclass ThreadPainterextends Thread{

privateboolean stop =false;

@Override

publicvoid run(){

while (!stop){

int cnt = 0;

for (int i = 0; i < 6; i++){

System.out.println("do task");

panel1.repaintMethod(i);

// load data, do calculations

try{

// emulate calcilation

Thread.sleep(1000);

}catch (InterruptedException e){

e.printStackTrace();

}

if (stop){

break;

}

cnt++;

}

if (cnt == 6){

stopThread();

}

}

};

publicvoid stopThread(){

this.stop =true;

};

};

public Painter(){

this.setLayout(new BorderLayout());

JLayeredPane pane =new JLayeredPane();

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.setLocation(new Point(100, 100));

this.setPreferredSize(new Dimension(800, 600));

this.panel.setOpaque(false);

this.panel1.setOpaque(false);

pane.setOpaque(false);

pane.add(panel, JLayeredPane.DEFAULT_LAYER);

pane.add(panel1,new Integer(

JLayeredPane.DEFAULT_LAYER.intValue() + 1));

this.add(pane, BorderLayout.CENTER);

panel.setBounds(new Rectangle(0, 0, 800, 600));

panel1.setBounds(new Rectangle(0, 0, 800, 600));

this.addComponentListener(this);

}

publicstaticvoid main(String[] args){

Painter painter =new Painter();

painter.pack();

painter.setVisible(true);

}

@Override

publicvoid componentHidden(ComponentEvent e){

// TODO Auto-generated method stub

}

@Override

publicvoid componentMoved(ComponentEvent e){

// TODO Auto-generated method stub

}

@Override

publicvoid componentResized(ComponentEvent e){

if (threadPainter !=null){

threadPainter.stopThread();

threadPainter =new ThreadPainter();

threadPainter.start();

}

}

@Override

publicvoid componentShown(ComponentEvent e){

// TODO Auto-generated method stub

}

}

[9870 byte] By [flexeda] at [2007-11-27 9:57:23]
# 1

Each time, you resize the window, the Thread will be stopped and created again. Does it have some negative influence on performance?

Is there some better way, to do it?

panel - draw squares with white names.

Thread will be started and make all names red.

On resize, it will be restarted and do the same task again.

flexeda at 2007-7-13 0:27:39 > top of Java-index,Desktop,Core GUI APIs...
# 2

> and was adviced to place the question here.

You where also advised to do other things, which you haven't, but then I guess I really don't understand what you are trying to do.

It sounds like you are trying to add a component and descriptive text of this component to a panel. So the question is why are you overriding paintComponent() method on your main panel and why are you using a Thread.

Create a component that draws your "shape" and then add that component to the main panel that uses a null layout. That means you need to specify the bounds of the component. Then you can add a JLabel containing the releated text of the component. If you don't know the text then it can always be updated with the setText() method in the future. Also, the foreground can be updated as well.

You said the names will not be available right away. Well then you don't start a thread to schedule the repainting of the names since you don't know exactly when the name will be available. You wait until you have the names and then simple use the setText() method.

camickra at 2007-7-13 0:27:39 > top of Java-index,Desktop,Core GUI APIs...
# 3

Hello camickr,

thanks for your answers.

> It sounds like you are trying to add a component and

> descriptive text of this component to a panel. So the

> question is why are you overriding paintComponent()

> method on your main panel and why are you using a

> Thread.

JLabel is not a good way I think, because of the performance. Think about 1000 labels on the panel. And the text can have different style, so drawString method is better here.

> Create a component that draws your "shape" and then

> add that component to the main panel that uses a null

> layout. That means you need to specify the bounds of

> the component. Then you can add a JLabel containing

> the releated text of the component. If you don't know

> the text then it can always be updated with the

> setText() method in the future. Also, the foreground

> can be updated as well.

If it would be lable, I could update Text as us say and JLabels would be perfect. In this case, JLabels are not what I need.

> You said the names will not be available right away.

> Well then you don't start a thread to schedule the

> repainting of the names since you don't know exactly

> when the name will be available. You wait until you

> have the names and then simple use the setText()

> method.

I have decided this way.

Draw all objects on the panel in different layers, for different type of objects.

Get names and make some calculations, for example, optimal position of the text on the panel (in Thread) and after it repaint();

Repaint draw all objects, but now it have the names, which will be added too.

The requirement is: thousand of objects on the panel

Different type of ojbects should be drawn in different layers

Names should be added to the objects and maybe some other drawings (showing state). Name and drawing can be done later, but should be added dynamically, after all calculation are done.

flexeda at 2007-7-13 0:27:39 > top of Java-index,Desktop,Core GUI APIs...