Calling a method from a different class containing Graphics g [JAVA] - java

im playing around with graphics and hit a bit of a roadblock. I can't seem to call my other class containing my graphics. Thanks in advance. As you can see i tried to call it as gameOBJ.Draw but its giving me errors.
This is the error:
The method Draw(Graphics) in the type GameObjects is not applicable for the arguments ()
public class Testing{
public boolean running = true;
public static void main(String[] args) {
GameObjects gameOBJ = new GameObjects();
gameOBJ.Draw();
Window window = new Window(Window.WIDTH, Window.HEIGHT, Window.TITLE);
}
public class GameObjects{
public void Draw(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, Window.WIDTH, Window.HEIGHT);
}
}

To fix of that compilation error you can pass a graphics object.
For example you can use windows graphics (But this may not be the requirement of your task/project. With JDK 10 Window.TITLE is not present, I doubt if it was there in earlier versions as well.)
Optionally: By conventions method names in Java should start with small cases characters so the method name should be draw.
public static void main(String[] args) {
GameObjects gameOBJ = new GameObjects();
//Pass the graphics object to the Draw method
Window window = new Window(Window.WIDTH, Window.HEIGHT, Window.TITLE);
Graphics graphics =window.getGraphics() ;
gameOBJ.Draw(graphics);
}

Here:
gameOBJ.Draw();
There:
public void Draw(Graphics g)
The method signature expects you to pass an argument, your invokation does not. Simply can't work that way.
The key thing here: you have to understand what you are doing: when your draw() method should draw "on something" then you have to pass that something to it, for example by first creating that window, to then fetch the graphics object belonging to the window.

Related

Why is my JPanel not being sized to JFrame when added?

I am trying to make a program that displays a graph drawn with Graphics2D methods. I have a class entitled Model which contains financial information that I want to represent graphically. In the main method of the program, I make the following declaration and call,
m = new Model(stock, strike, interest, dividend, volatility, expiration);
m.addGraph(fSelect, vSelect);
The model function constructor just passes the arguments along to some fields inside the class. fSelect and vSelect inform a Graph class I created what function to graph and what variable to graph over. The addGraph method looks like,
public void addGraph(int fSelection, int vSelection){
//Why is my panel not showing up?
graphPanel = new Graph(fSelection, vSelection, thisStock, thisStrike, thisInterest,
thisDividend, thisExpiration, thisVolatility);
JFrame jf = new JFrame();
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.add(graphPanel);
jf.setSize(300, 300);
graphPanel.drawGraph();
jf.setVisible(true);
}
The Graph class extends the JPanel class. It's constructor looks like this,
public Graph(int whichFunction, int whichVariable, double whichStock, double whichStrike, double whichInterest,
double whichDividend, double whichExpiration, double whichVolatility){
super();
//...pass arguments into class fields
}
When I run the program, I get a blank JFrame. I haven't got a clue why it's blank. I have to be doing something wrong in the drawGraph method, or at least that's what I'm thinking the source of the problem is. The gist of the drawGraph method is,
try{
Graphics2D g2 = (Graphics2D) this.getGraphics();
//draw stuff
//...
Toolkit.getDefaultToolkit().sync();
g2.dispose();
}
catch(Exception e) { }
I call a variety of Graphics2D methods, like fillRect, drawLine, etc., inside the try clause. Is this the proper way of drawing on a JPanel or am I missing something?

Java: How to avoid code duplication between display() and write(pdf)

I have two functions within a class
void display()
and
void write(PGraphics pdf)
I use display() to display elements to the screen. Is there a way of invoking the code within display() so that I do not have to write out each of the functions again within write(pdf)? e.g.
line(0,0,100,100) to pdf.line(0,0,100,100) etc
You could do this by drawing to a PGraphics image instead of drawing directly to the screen, then draw that image to the screen. That way you could swap it out for the PDF PGraphics without changing any code. Something like this:
PGraphics pg;
PGraphics pdf;
boolean usePdf = false;
void setup() {
size(100, 100);
pg = createGraphics(width, height);
pdf = //whatever
}
void draw(){
if(usePdf){
display(pdf);
}
else{
display(pg);
image(pg, 0, 0);
}
}
void display(PGraphics g) {
g.beginDraw();
g.background(100);
g.stroke(255);
g.line(20, 20, mouseX, mouseY);
g.endDraw();
}
If you want to use all of the code jsut call it inside (but I guess you don't want to do that)
You should refractor the code and put the stuff you want to use in both methods into it's own method like:
private void hopefullyIGetABetterName(...) {...}
You can call this method inside of display as well as in write
I hope this helps, otherwise feel free to ask :-)
extract a common interface between drawing to screen and to the PDF (lets call it Drawable)
Implement Drawable for drawing to the screen.
Implement Drawable for drawing to the PDF
Create a single draw method that takes that interface.
Change display() to call draw(screenDrawable)
Change write(...) to call draw(pdfDrawable)

How to create more than one window of a single sketch in Processing?

I want to create two windows by using just one single sketch in Processing.
What I'm trying to do is that if I click a button in one window, then some image appear in another window.
I've searched Google and found some examples. Actually, I found the same question in this 'stack overflow web'. Here are the links.
Create more than one window of a single sketch in Processing
http://forum.processing.org/one/topic/multiple-windows-2-4-2011.html
Here is the codes of second links.
import java.awt.Frame;
PFrame f;
secondApplet s;
//f = new PFrame();
void setup() {
size(320, 240);
f = new PFrame();
}
void draw() {
background(255,0,0);
fill(255);
rect(10,10,frameCount%0,10);
s.background(0, 0, 255);
s.fill(100);
s.rect(10,20,frameCount%0,10);
s.redraw();
}
public class PFrame extends Frame{
public PFrame() {
setBounds(100,100,400,300);
s = new secondApplet();
add(s);
s.init();
show();
}
}
public class secondApplet extends PApplet {
public void setup() {
size(400, 300);
noLoop();
}
public void draw() {
}
}
But when I run this codes, I get the following error message at add(s);.
The method add(Component) in the type Container is not applicable for the arguments (multi_window_test.secondApplet)
Code of first comment of first link is similar, but when I run this code, I get the same error message.
Other example codes that I found are all similar. They all create PFrame class and secondApplet which extends PApplet. They said these codes works well but I can't run these codes.
I couldn't find the reason of my error message. Other people seems to have no problem when running this example code except me.
If someone knows the solution, please help me.
Also, if there is a other simple way to create multi-windows in one sketch, please let me know.
The reason for the error message is pretty self-explanatory: the add() function is expecting a Component, and PApplet is not a Component. This is because PApplet no longer extends Applet as of Processing 3, so old code that uses it as a Component will no longer work.
Instead, consider my answer to this question. Basically, just create a class that extends PApplet for your second window, and then call PApplet.runSketch() using that second PApplet as a parameter:
void setup() {
size(100, 100);
String[] args = {"TwoFrameTest"};
SecondApplet sa = new SecondApplet();
PApplet.runSketch(args, sa);
}
void draw() {
background(0);
ellipse(50, 50, 10, 10);
}
public class SecondApplet extends PApplet {
public void settings() {
size(200, 100);
}
public void draw() {
background(255);
fill(0);
ellipse(100, 50, 10, 10);
}
}

Java - Slick 2D - Placing text (or any graphics) on a rectangle (or any Shape)

I am making an RTS game using Slick 2D. I have a building class and it contains an int called resources. I want the resources variable to become a string and be rendered onto the center of my building (which is just supposed to be a rectangle).
Here's my building class:
package test;
import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.geom.Rectangle;
public class BaseBuilding extends Rectangle{
private int resources;
private Graphics g;
public BaseBuilding(float x, float y, float width, float height) {
super(x, y, width, height);
resources = 0;
g = new Graphics();
} // end constructor
public void render(){
g.drawString("bro wat", resources, resources);
g.setColor(Color.gray);
g.fill(this);
g.drawString(Integer.toString(resources), this.width/2, this.height/2);
} // end update
public int getResources(){
return resources;
} // end getResources
public void addResources(int mulla){
resources += mulla;
if (resources < 0)
resources = 0;
} // end addResources
public void createBasicUnit(){
// create a BasicUnit object in a randomly, valid position close to this object
// TODO
} // end createBasicUnit
} // end class def
So far all my states are working and i got the rectangle to appear appropriately. My g.drawString(str, float, float) code with correct parameters will work on my GameState class(not shown) in its render function, but it gives me this error in my BaseBuilding class:
java.lang.NullPointerException
at org.newdawn.slick.Graphics.drawString(Graphics.java:1366)
at test.BaseBuilding.render(BaseBuilding.java:19)
at test.GameState.render(GameState.java:34)
at org.newdawn.slick.state.StateBasedGame.render(StateBasedGame.java:199)
at org.newdawn.slick.GameContainer.updateAndRender(GameContainer.java:688)
at org.newdawn.slick.AppGameContainer.gameLoop(AppGameContainer.java:411)
at org.newdawn.slick.AppGameContainer.start(AppGameContainer.java:321)
at test.StateBaseGame.main(StateBaseGame.java:22)
Sat Apr 18 03:18:55 EDT 2015 ERROR:Game.render() failure - check the game code.
org.newdawn.slick.SlickException: Game.render() failure - check the game code.
at org.newdawn.slick.GameContainer.updateAndRender(GameContainer.java:691)
at org.newdawn.slick.AppGameContainer.gameLoop(AppGameContainer.java:411)
at org.newdawn.slick.AppGameContainer.start(AppGameContainer.java:321)
at test.StateBaseGame.main(StateBaseGame.java:22)
So i dug around and found out it's this line that's causing me problems:
g.drawString(Integer.toString(resources), this.width/2, this.height/2);
Couldn't find it on the internet; help if you can please thanks.
After taking a look at the Slick source code, your problem comes from the font variable inside the Graphics class which is null.
You are instantiating Graphics with the default constructor which does not provide a default value for the font variable. And the other one, as the doc says, only the container should be instantiate Graphics.
So, you should never instantiate Graphics, instead just retrieve it from the GameContainer (getGraphics) which is everywhere, or you can also get g from the render method of your game class (Game, BasicGame, BasicGameState, StateBasedGame, depending on what you use...).
To keep it simple, just pass your Graphics object through your render method:
public void render(Graphics g){
g.drawString("bro wat", resources, resources);
g.setColor(Color.gray);
g.fill(this);
g.drawString(Integer.toString(resources), this.width/2, this.height/2);
} // end update
And inside your Game:
render(GameContainer container, Graphics g) {
myBaseBuilding.render(g);
}

Using rectangles to simulate straight line motion of an object

I am relatively new to Java and have been trying to simulate the motion of an object (say a car) on a straight path.
I want my object to move in steps in the output, instead of appearing just at the last point of the line.
I have used 2 classes :Veh.java - the vehicle object and SimuFrame.java - to create the simulation environment.
I have referred to some online tutorials for ideas: http://www.newthinktank.com/2012/07/java-video-tutorial-52/ (This simulates the asteroids game. Howeer I want my object to move in a straight line instead of in a random direction)
Please help me understand where I am wrong and what to do next..
Thanks a lot.
Here's my code:
import java.awt.*;
import java.awt.event.*;
public class Veh extends Rectangle{
int uLeftX, uLeftY; //upper LH Position for Rectangle
static int height = 20;
static int width = 20;
int[] pathCoords=new int[1000];
int startPosY; // start position of the objet - anywhere on the left bounday of the frame.
int goalPosY; // end position of the objet - anywhere on the right boundary of the frame.
//Constructor to Create a new Veh
public Veh(int startPosY,int goalPosY){
//Create a new rectangle vehicle from super class constructor
super(0, startPosY, height, width);
this.startPosY=startPosY;
this.goalPosY=goalPosY;
this.pathCoords = Pathmove();
}
//Calculating the 1000 points on the line joining (0,startPosY) and (goalPosY,999)
int[] Pathmove(){
//Slope calculation
float s=(float)(this.goalPosY-this.startPosY)/999;
pathCoords[0]=this.startPosY;
System.out.println("First xy pair is: 0," +this.pathCoords[0]);
for(int m=1; m<1000; m++){
pathCoords[m]= (int)(m*s)-(int)((m-1)*s)+ pathCoords[m-1];
}
return pathCoords;
}
//Function to move the Reactangular object along the line using the Y coordinate values from Pathmove()
void move(){
int[] a = (int[])this.pathCoords.clone();
for (int c=0; c<a.length;c++){
this.setLocation(c,a[c]);
}
}
}
This is the code for creating the simulation environment.
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class SimuFrame extends JFrame{
public static int frameWidth=1000;
public static int frameHeight=1000;
public static void main(String[] args){
new SimuFrame();
}
public SimuFrame(){
this.setSize(frameWidth,frameHeight);
this.setTitle("Path Planning Results");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SimuObject SO=new SimuObject();
this.add(SO);
// Used to execute code after a given delay
// The attribute is corePoolSize - the number of threads to keep in
// the pool, even if they are idle
ScheduledThreadPoolExecutor executor= new ScheduledThreadPoolExecutor(5);
executor.scheduleAtFixedRate(new RepaintTheFrame(this), 0L, 20L, TimeUnit.MILLISECONDS);
this.setVisible(true);
}
}
// Class implements the runnable interface
// By creating this thread I want to continually redraw the screen
// while other code continues to execute
class RepaintTheFrame implements Runnable{
SimuFrame theFrame;
public RepaintTheFrame(SimuFrame theFrame){
}
#Override
public void run() {
theFrame.repaint();
}
}
class SimuObject extends JComponent{
//Holds every Veh created
public ArrayList<Veh> vehs=new ArrayList<Veh>();
public SimuObject(){
int startPosY = (int)(Math.random()*999);
int goalPosY = (int)(Math.random()*999);
vehs.add(new Veh(startPosY,goalPosY));
}
public void paint(Graphics g){
// Allows me to make many settings changes in regards to graphics
Graphics2D graphicSettings = (Graphics2D)g;
// Draw a background that is as big as the Simu board
graphicSettings.setColor(Color.WHITE);
graphicSettings.fillRect(0, 0, getWidth(), getHeight());
// Set rendering rules
graphicSettings.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// Set the drawing color to red
graphicSettings.setPaint( Color.RED);
// Cycle through all of the Rock objects
for(Veh veh : vehs){
// Move the vehicle
veh.move();
graphicSettings.draw(veh);
}
}
}
You have a number of problems in your code:
You have a (swallowed) NullPointerException (NPE) in RepaintTheFrame.run(), which causes ScheduledThreadPoolExecutor.scheduleAtFixedRate() to run only once, per scheduleAtFixedRate()'s javadoc.
You are moving your car in JComponent.paint().
In any graphical framework, the repaint will be called automatically by the framework, usually on an OS event, e.g. moving the window, moving the mouse over the window, etc.
Your paint() method should only draw. It should not modify your domain model.
Your move() method always ends up with the vehicle at the end. That's probably not your intent. You probably want your move() method to merely increment the car's position.
Moving from a start value to an end value in steps is called interpolation. You want linear interpolation specifically here. Its one of the easiest to grasp.
This page will be of great assistance to you.
Without getting fancy with interpolation, you could just change your move routine like so:
int index =0;
void move(){
//int[] a = (int[])this.pathCoords.clone();
if(index<this.pathCoords.length)
this.setLocation(c,pathCoords[index]);
index+=1;
}
Not sure why you were cloning the array there. It probably isn't necessary.

Categories