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
# 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
# 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;
}
}
# 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);
....
}
}
# 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
# 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);
}
}
# 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
# 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
# 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