Calling paintComponent(Graphics g) in another class

Dear Friends,

I have a class (Class Pee) where I implemented the paintComponent(Graphics g) and another class (Class Bee) where I generate some datas. My intention is to call the paintComponent(Graphics g) method in class Pee at class Bee to make use of the generated data to draw some figures.

I imported java.awt .Graphics, java.awt.Graphics2D, Polygon and geom and declared Graphics2D g2d = (Graphics2D) g;

as well, but still when I call paintComponent (Graphics g) it fails to recognize the g. What is actually wrong.

See code:

Class Pee

import java.awt.Color;

import java.awt.Graphics;

import java.awt.Polygon;

import javax.swing.JPanel;

-

-

publicclass Peeextends JPanel{

privateint offset;

publicvoid paintComponent(Graphics g,int b[],int c[]){

super.paintComponent(g);

Graphics2D g2D = (Graphics2D) g;

this.setBackground(Color.white);

-

-

-

}

}

Class Bee

import java.io.*;

import java.util.*;

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.geom.*;

import java.awt.Polygon;

import Graphic.Pee;//importing Pee Class

publicclass Bee{

int x[];

int y[];

// other variable declaration

public Bee{

x =newint [5];

y =newint [5];

Pee dr =new Pee();

Graphics2D g2d = (Graphics2D) g;

//code to generate data

dr.paintComponent(g,x,y);

}

}

It always say that "g" cannot be resolved. Please how do I get over this.

Thanks,

Jona_T

[2956 byte] By [Jona_Ta] at [2007-11-27 2:09:48]
# 1
You need to pass in a reference to the graphics object or make your other object somehow accessible so that the 2nd object can get it's Graphics.There are a lot of tutorials for learning to do custom painting. You should try to find one on google or this site
tjacobs01a at 2007-7-12 2:00:45 > top of Java-index,Security,Cryptography...
# 2
Hello,I declared "Graphics b" in class Bee and called the method paintComponent(b, x, y) but it continues to show error; "b cannot be resolved". Is there another way to declare Graphics objects?Jona_T
Jona_Ta at 2007-7-12 2:00:45 > top of Java-index,Security,Cryptography...
# 3

Swing calls the paintComponent method when we ask a component to draw itself. We do this by

calling its repaint method. So the general approach is to change the data in the component

that does the graphics for us and then ask the component to repaint itself. Swing does the

rest. One benefit of this way of doing things is that the graphic component keeps the data

and can render all or any part of it at any time. Trying to get a reference to the

components graphics context from within another class and using it to draw graphics in the

graphics component prevents this and the foreign class event code can never know when the

graphics component needs to be re–rendered.

So the idea is to keep the graphics/rendering component independent from the event code. The

event code controls the state (member variables) in the graphics component and tells it when

to re–render itself.

There are a lot of (creative) ways of putting these things together. Here's an example.

import java.awt.*;

import java.awt.event.*;

import java.awt.geom.*;

import java.util.Random;

import javax.swing.*;

public class CallingGraphics implements ActionListener {

GraphicComponentClass graphicComponent;

DataGenerationClassdataGenerator = new DataGenerationClass();

public void actionPerformed(ActionEvent e) {

Point2D.Double[] data = dataGenerator.getData();

graphicComponent.setData(data);

}

private JPanel getGraphicComponent() {

graphicComponent = new GraphicComponentClass();

return graphicComponent;

}

private JPanel getLast() {

JButton button = new JButton("send data to graphics");

button.addActionListener(this);

JPanel panel = new JPanel();

panel.add(button);

return panel;

}

public static void main(String[] args) {

CallingGraphics test = new CallingGraphics();

JFrame f = new JFrame();

f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

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

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

f.setSize(400,300);

f.setLocation(200,200);

f.setVisible(true);

}

}

class GraphicComponentClass extends JPanel {

Ellipse2D.Double[] circles = new Ellipse2D.Double[0];

protected void paintComponent(Graphics g) {

super.paintComponent(g);

Graphics2D g2 = (Graphics2D)g;

g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

RenderingHints.VALUE_ANTIALIAS_ON);

for(int j = 0; j < circles.length; j++) {

g2.draw(circles[j]);

}

}

public void setData(Point2D.Double[] p) {

double w = getWidth();

double h = getHeight();

double dia = 75.0;

circles = new Ellipse2D.Double[p.length];

for(int j = 0; j < circles.length; j++) {

double x = p[j].x*(w - dia);

double y = p[j].y*(h - dia);

circles[j] = new Ellipse2D.Double(x,y,dia,dia);

}

repaint();

}

}

class DataGenerationClass {

Random seed = new Random();

public Point2D.Double[] getData() {

int n = seed.nextInt(25);

Point2D.Double[] locs = new Point2D.Double[n];

for(int j = 0; j < n; j++) {

double x = seed.nextDouble();

double y = seed.nextDouble();

locs[j] = new Point2D.Double(x, y);

}

return locs;

}

}

crwooda at 2007-7-12 2:00:45 > top of Java-index,Security,Cryptography...
# 4

In class Bee, define a method paintData(Graphics2D g) where you draw all the data to g. In class Pee, within the paintComponent(Graphics g) method, call b.paintData(g), where b is an instance of Bee.

So:

class Bee {

Bee() {

// generate data

}

void paintData(Graphics2d g) {

g.draw(...);

...

}

}

class Pee extends JPanel {

private Bee b = new Bee();

public void PaintComponent(Graphics g) {

Graphics2D g2 = (Graphics2D) g;

b.paintData(g2);

....

}

}

James_Vagabonda at 2007-7-12 2:00:45 > top of Java-index,Security,Cryptography...
# 5

Hello Friends,

Thanks for your help but am still not able to move forward. The initial problem was calling paintComponent(Graphic g) from another class which I learnt is not the best thing to do, so I decided to just have one class but the problem still exits.

The problem definition is;

(1)I have a file to read

(2)In each line, sort the strings, and get the frequency of which each string occurs.

(3)Let the Strings be node points and draw a clique joining all the node points

(4) To draw the clique, I need to generate some random values (x and y Axis)

Repeat the same for each line.

Previously, I wrote two classes, one for reading the file, sorting and generating of random points. The second is only to draw the objects. I tested the two classes separately and and it worked, but when I want to link them up the problem started.

See the new codes below:

Public Class Sort extends JPanel{

//import all necessary lib

//define some variables

Sort(){

//initialize the variables

//call some methods

}

public void creation(){

// read the line

String line = br.readLine();

while( line != null){

// tokenize and sort the strings

doDraw(Graphics g) // Here is the big problem

line = br.readLine();

}

public void doDraw(Graphics g){

SetEntry(); // sets the string values and frequency (works fine)

generatePoints();// generate the random drawing points (works fine)

paintComponent(Graphics g, xAxis, yAxis, items, frequency);

}

public void paintComponent(Graphics g, int []xP, int y []yP, String allItems[], int []frequency){

// variable declarations;

Graphics2D gx = (Graphics2D) g;

// I draw the strings (works fine)

// I draw the clique (works fine)

gx.dispose();

}

public static void main(String [] args){

JFrame frame = new JFrame();

frame .setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Sort DD = new Sort;

DD.setBackground(Color.WHITE);

frame.add(DD);

frame.setSize(850, 710);

frame.setVisible(true);

}

}

I am ready to spend more Dukes although I do not have much left. I am also not too clear where to call the repaint() so that after each Line iteration, the panel will clear and re-draw the new image.

Thanks,

Jona_T

Jona_Ta at 2007-7-12 2:00:46 > top of Java-index,Security,Cryptography...
# 6

I am also not too clear where to call the repaint() so that after each Line iteration,

the panel will clear and re-draw the new image

I'm not sure what you are doing here. Are you reading one line and drawing its graph and

then reading another line and drawing its graph where the first graph was? Or drawing each

new graph below the last?

In other words, what are you doing after step 4 before you repeat the sequence of 4

steps.

//import all necessary lib

public class Sort extends JPanel{

//define some variables - the state.

int[] xP;

int[] yP;

String[] allItems;

int[] frequency;

Sort(){

//initialize the variables

//call some methods

}

public void creation(){

// read the line

String line = br.readLine();

while( line != null){

// tokenize and sort the strings

processData();

// If you want to wait for awhile before reading

// another line and than replacing the graph you'll

// need a timer or thread delay in here. This is

// awkward to keep the reader and file open while

// you process data and draw the graph. Another

// option is to read in the entire file, store it

// and draw each line/graph in an animation or via

// user inteaction, eg, button press.

// Draw the newly-processed data.

repaint();

// This is a problem. Java won't wait to repaint this

// component but will continue on with the next line.

line = br.readLine();

}

public void processData(){

// Set the member variables (the state) which will be

// rendered after your next call to repaint, assuming

// you get the timing worked out.

SetEntry();// sets the string values and frequency (works fine)

generatePoints(); // generate the random drawing points (works fine)

}

/**

* Swing looks for this method signature in a JPanel class.

* Swing provides the Graphics g, we don't. Set your member

* variables from within your event code and tell this to

* repaint itself.

*/

protected void paintComponent(Graphics g){

// cast to Graphics2D

Graphics2D gx = (Graphics2D) g;

// I draw the strings (works fine)

// I draw the clique (works fine)

}

public static void main(String [] args){

JFrame frame = new JFrame();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Sort DD = new Sort;

DD.setBackground(Color.WHITE);

frame.add(DD);

frame.setSize(850, 710);

frame.setVisible(true);

}

}

crwooda at 2007-7-12 2:00:46 > top of Java-index,Security,Cryptography...
# 7

Hello Crwood,

Thanks for the Java2D lecture. I appreciate it.

'm not sure what you are doing here. Are you reading one line and drawing its graph and

then reading another line and drawing its graph where the first graph was? Or drawing each

new graph below the last?

In other words, what are you doing after step 4 before you repeat the sequence of 4

steps.

I want to read each line and draw its graph and then reading another line and drawing the graph were the first graph existed. So, I will need a timer or delay thread as you rightly said.

On your comment;

// This is a problem. Java won't wait to repaint this

// component but will continue on with the next line.

line = br.readLine();

Is there any other way to solve the problem apart from storing all data which I do not want to do?

Thanks,

Jona_T

Jona_Ta at 2007-7-12 2:00:46 > top of Java-index,Security,Cryptography...
# 8

I did this first with three classes. Then did this in a single class; probably a better

place to start.

import java.awt.*;

import java.awt.event.*;

import java.io.*;

import javax.swing.*;

public class ReadingAndDrawing2 extends JPanel implements Runnable {

Thread thread = null;// animation

boolean running = false;//member

final int DISPLAY_TIME = 1000; //variables

String str = "0";// state/member variable

protected void paintComponent(Graphics g) {

super.paintComponent(g);

Graphics2D g2 = (Graphics2D)g;

g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,

RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

g2.setFont(g2.getFont().deriveFont(36f));

g2.drawString(str, 100, 50);

}

public void run() {

File file = new File("readingAndWriting.txt");

try {

BufferedReader br = new BufferedReader(

new InputStreamReader(

new FileInputStream(file)));

String line = null;

while((line = br.readLine()) != null) {

try {

Thread.sleep(DISPLAY_TIME);

} catch(InterruptedException e) {

System.out.println("interrupted");

}

if(line != null) {

// Set state variables in/from here.

str = line;

}

// Draw the new state.

repaint();

}

br.close();

//System.out.println("br closed");

} catch(IOException e) {

System.out.println("Read error: " + e.getMessage());

stop();

}

}

public void start() {

// Make sure this is up and running.

while(!isVisible()) {

try {

Thread.sleep(100);

} catch(InterruptedException e) {

System.out.println("interrupted");

}

}

if(!running) {

running = true;

thread = new Thread(this);

thread.setPriority(Thread.NORM_PRIORITY);

thread.start();

}

}

public void stop() {

running = false;

if(thread != null)

thread.interrupt();

thread = null;

}

public static void main(String[] args) {

ReadingAndDrawing2 test = new ReadingAndDrawing2();

JFrame f = new JFrame();

f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

f.getContentPane().add(test);

f.setSize(250,140);

f.setLocation(200,200);

f.setVisible(true);

test.start();

}

}

readingAndWriting.txt

1

2

3

4

5

crwooda at 2007-7-12 2:00:46 > top of Java-index,Security,Cryptography...
# 9
Hello Crwood,It is working and thanks for the good help. Now I can proceed with other areas of the code. Your dukes are on the way. Once more thank you for the time.Jona_T
Jona_Ta at 2007-7-12 2:00:46 > top of Java-index,Security,Cryptography...