I am really new in Java. Thought I had figure some stuff out by now, but I have a problem that proves otherwise!
Ok! Here it is. I have this code (Edited - Not original):
import java.util.*;
import java.awt.*;
public class MyClass extends HisClass
{
public void drawRectangle(int width, int height)
{
int x1 = this.getXPos();
int y1 = this.getYPos();
java.awt.Graphics.drawRect(x1, y1, width, height);
}
public static void main(String[] args)
{
AnotherClass theOther = new AnotherClass();
MyClass mine = new MyClass(theOther);
mine.move();
}
}
The error it gives me is this:
MyClass.java:66: error: non-static method drawRect(int,int,int,int) cannot be referenced from a static context
Can you please provide me with a solution?
It would be very appreciated. Thanks.
java.awt.Graphics.drawRect(x1, y1, width, height);
drawRect method is not static.. You should get an instance of your Graphics class somehow to use it: -
(graphicsInstance).drawRect(x1, y1, width, height);
Since Graphics class is abstract, so you need to find appropriate way to instantiate your Graphics object, to get graphicsInstance
You can use GraphicsContext to draw whatever you want to.. GraphicsContext is an object belonging to Graphics class which you can use to drawRect()
See these post. Might be useful: -
How do I initialize a Graphics object in Java?
what is a graphics context (In Java)?
Here is some example code that draws a Rectangle using drawRect() onto the JPanel by overriding its paintComponent(Graphics g) method and adding it to the JFrame:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DrawRect extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
//draw our rect
g.setColor(Color.blue);
g.drawRect(10, 10, 100, 50);
}
//or else we wont see the JPanel
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setTitle("DrawRect");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new DrawRect());
frame.pack();
frame.setVisible(true);
}
}
Related
My goal is to make a class that contains rectangle and then use it and change it in other classes.
I tried to write this code and make an object Rect rect = new Rect(); but when i start the program the rectangle doesn't show up.
I also tried to add it with window.add(rect); but had same problem i'm sure im doing something wrong but i don't really know what.
One more thing that i tried was calling method from other class Rect.drawRect(g); but then it asks for "Argument" and if i add Argument g like i had in method drawRect it says "g cannot be resolved to a variable"
I hope someone can explain and tell me what did i do wrong, also would be great to know how to make rectangle or a circle and later use it in other classes and maybe change its color and size, I only found how to do it in one class.
import javax.swing.JFrame;
public class Main extends Rect{
public static void main(String[] args ) {
JFrame window = new JFrame("test");
window.setSize(1000, 800);
window.setVisible(true);
window.setResizable(false);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Rect rect = new Rect();
}
}
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Rect extends JPanel{
public void drawRect(Graphics g){
g.setColor(Color.RED);
g.fillRect(100, 100, 200, 200);
}
}
The most important thing is that you need to write some code to do the painting. This is done by overriding the paintComponent method inside your Rect class a bit like this:
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(100, 100, 200, 200);
}
Your second issue is that you want to be able to change the colour and size of your rectangle from other classes. For a simple example, this can easily be done by adding some static values inside your Rect class:
public static Color myColor = Color.RED;
public static int myX = 100;
public static int myY = 100;
public static int myWidth = 200;
public static int myHeight = 200;
Now update your paint method to use the static values:
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(myColor);
g.fillRect(myX, myY, myWidth, myHeight);
}
Now, whenever or wherever you use the Rect panel it will now show the rectangle according to the static values.
For example, below is a simple and working program, note how it uses the following:
//create Rect
Rect rect = new Rect();
//set the size of the new panel
rect.setPreferredSize(new Dimension(800, 600));
//add the rect to your JFrame
window.add(rect);
//now you can change the color for all Rect instances
//Note how I use Rect instead of rect, however, both will work.
Rect.myColor = Color.BLUE;
//And dont forget to repaint it if you want to see the changes immediatly
rect.repaint();
Full example, main class:
import javax.swing.JFrame;
import java.awt.Color;
public class Main{
//Note how we don't need to extend the Rect class (It just adds confusion)
public static void main(String[] args ) {
JFrame window = new JFrame("test");
window.setSize(1000, 800);
window.setVisible(true);
window.setResizable(false);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//create Rect
Rect rect = new Rect();
//set the size of the new panel
rect.setPreferredSize(new Dimension(800, 600));
//add the rect to your JFrame
window.add(rect);
//now you can change the color for all Rect instances
//Note how I use Rect instead of rect, however both will work.
Rect.myColor = Color.BLUE;
//And dont forget to update it
rect.repaint();
}
}
And the Rect class:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Rect extends JPanel{
public static Color myColor = Color.RED;
public static int myX = 10;
public static int myY = 10;
public static int myWidth = 200;
public static int myHeight = 200;
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(myColor);
g.fillRect(myX, myY, myWidth, myHeight);
}
}
Note, if you don't want to call Rect.repaint() every time you make a color/size change then just make a new method that changes each value and include repaint(), for example:
public void changeWidth(int width){
myWidth = width;
repaint();
}
UDP: You need override void paintComponent(Graphics g) instead void drawRect(Graphics g)and call super.paintComponent(g) inside method. Then you can use window.add(rect);.
Thanks #FredK for correction
I'd like to make a Java panel that creates objects where the user clicks. Since my actual application uses a MVC approach I'd like also for these objects to be able to repaint themselves when a model is changed, and provide menus to change their properties.
I think that the best way to control their x and y locations would be to take a canvas based approach whereby the JPanel calls a draw method on these objects from the paintComponent method. This however will only draw the shape on the canvas and does not add the object itself loosing all abilities to control object properties. I'd be very grateful if someone could tell me the best approach for what I want to do.
I've created some sample code which can be seen below. When clicked I'd like the circle to change colour, which is implemented using a MouseListener (it basically represents changing the models properties in this small example). Also I'd just like to make sure that zooming in/out still works with any sample code/advice can provide so I've added buttons to zoom the objects in and out as a quick test.
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.geom.Ellipse2D;
public class Main {
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ExamplePanel panel = new ExamplePanel();
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
});
}
//I could not get this to with when it extended JLayeredPane
private static class ExamplePanel extends JPanel {
private static final int maxX = 500;
private static final int maxY = 500;
private static double zoom = 1;
private static final Circle circle = new Circle(100, 100);
public ExamplePanel() {
this.setPreferredSize(new Dimension(maxX, maxY));
this.setFocusable(true);
Button zoomIn = new Button("Zoom In");
zoomIn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
zoom += 0.1;
repaint();
}
});
add(zoomIn);
Button zoomOut = new Button("Zoom Out");
zoomOut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
zoom -= 0.1;
repaint();
}
});
add(zoomOut);
// add(circle); // Comment back in if using JLayeredPane
}
#Override
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.scale(zoom, zoom);
super.paintComponent(g);
circle.paint(g); // Comment out if using JLayeredPane
}
}
static class Circle extends JPanel {
private Color color = Color.RED;
private final int x;
private final int y;
private static final int DIMENSION = 100;
public Circle(int x, int y) {
// setBounds(x, y, DIMENSION, DIMENSION);
this.x = x;
this.y = y;
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
color = Color.BLUE;
}
#Override
public void mouseReleased(MouseEvent e) {
}
});
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(color);
g2.fillOval(x, y, DIMENSION, DIMENSION);
}
// I had some trouble getting this to work with JLayeredPane even when setting the bounds
// In the constructor
// #Override
// public void paintComponent(Graphics g) {
// Graphics2D g2 = (Graphics2D) g;
// g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// g2.setPaint(color);
// g2.fillOval(x, y, DIMENSION, DIMENSION);
// }
#Override
public Dimension getPreferredSize(){
return new Dimension(DIMENSION, DIMENSION);
}
}
}
As an aside I did try using a JLayeredPane(useful because I'd also like to layer my objects) but could not get my objects to even render. I know it has no default layout manager so tried calling setBounds in the circle in the constructor, but sadly it did not work. I know it's better to use a layout manager but can't seem to find one suitable for my needs!
Thanks in advance.
Don't override paint components, use paintComponent and don't forget to call super.paintComponent
A component already has a concept of "location", so when painting, the top left position of your component is actually 0x0
What you are doing is actually painting beyond the boundaries of you component
For example, if you place your Circle at 100x100 and then did...
g2.fillOval(x, y, DIMENSION, DIMENSION);
You would actually start painting at 200x200 (100 for the actual location of the component and 100 for you additional positioning).
Instead use
g2.fillOval(x, y, DIMENSION, DIMENSION);
And go back and try using JLayeredPane.
You could actually write your own layout manager that takes the location of the component and it's preferred size and updates the components bounds and then apply this to a JLayeredPane. This gives you the "benefits" of an absolute layout, but keeps you within how Swing works to update its components when things change.
You should also be careful with doing anything like...
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
The Graphics context is a shared resource. That means, anything you apply to, will still be in effect when the next component is painted. This may produce some strange results.
Instead try using...
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//...
g2.dispose();
Updated
For zooming I would take a closer look at JXLayer (or JLayer in Java 7)
The JXLayer (and excellent PBar extensions) have gone quite on the net, so you can grab a copy from here
(I tried finding a better example, but this is the best I could do with the limited time I have available)
Updated with working zooming example
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.RenderingHints;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.jdesktop.jxlayer.JXLayer;
import org.pbjar.jxlayer.demo.TransformUtils;
import org.pbjar.jxlayer.plaf.ext.transform.DefaultTransformModel;
public class TestJLayerZoom {
public static void main(String[] args) {
new TestJLayerZoom();
}
public TestJLayerZoom() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JXLayer<JComponent> layer;
private DefaultTransformModel transformModel;
private JPanel content;
public TestPane() {
content = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridy = 0;
JLabel label = new JLabel("Hello");
JTextField field = new JTextField("World", 20);
content.add(label, gbc);
content.add(field, gbc);
gbc.gridy++;
gbc.gridwidth = GridBagConstraints.REMAINDER;
final JSlider slider = new JSlider(50, 200);
slider.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
int value = slider.getValue();
double scale = value / 100d;
transformModel.setScale(scale);
}
});
content.add(slider, gbc);
transformModel = new DefaultTransformModel();
transformModel.setScaleToPreferredSize(true);
Map<RenderingHints.Key, Object> hints = new HashMap<>();
//hints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//hints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
//hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
layer = TransformUtils.createTransformJXLayer(content, transformModel, hints);
setLayout(new BorderLayout());
add(layer);
}
}
}
I've left the rendering hints in to demonstrate their use, but I found that they screwed with the positing of the cursor within the text field, but you might like to have a play
I'd just like to add that I fixed the zooming issue not in the way suggested by the answer, but just by keeping the line that applied a scaled transform call in the ExamplePanel paintComponent method:
g2.scale(zoom, zoom);
I thought that this was the nicest implementation since none of the components require any knowledge about zooming and it seemed far simpler than JLayer since I only required basic zooming functionalities.
I've been trying for a while to load an image into this JFrame for it to display it without success. Here is the code:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JOptionPane;
public class Main extends JPanel{
Bird bird = new Bird(this);
public void paint(Graphics g){
super.paint(g);
Graphics2D g2D = (Graphics2D) g;
g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
bird.paint(g2D);
}
public static void main(String[] args)throws InterruptedException{
JFrame frame = new JFrame("Java Birds");
Main game = new Main();
frame.add(game);
frame.setSize(500, 300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while(true){
game.repaint();
Thread.sleep(10);
}
}
}
This is my Bird Class:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;
public class Bird {
private static final Image sprite = Toolkit.getDefaultToolkit().getImage("bird.jpeg");
private static final int DIAMETER = 30;
double g = 0.12, vy = 0, xo = 100, yo = 10;
private Main game;
public Bird(Main game){
this.game = game;
}
public void paint(Graphics2D g){
g.setColor(Color.BLACK);
g.drawImage(sprite, 30, 30, game);
}
}
When I run this nothing shows up onscreen, but if I place a g.fillOval instruction I do get a circle in the panel. Help much appreciated, please.
There are a cascade of issues, first...
public void paint(Graphics g){
super.paint(g);
Graphics2D g2D = (Graphics2D) g;
g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
bird.paint(g2D);
}
You're overriding paint, it is highly unrecommended to do so, instead, it is recommended that you override paintComponent instead.
Another problem is...
Toolkit.getDefaultToolkit().getImage("bird.jpeg");
The problem with this is getImage(String) expects that the value you pass it refers to a file on the file system. In most cases, this is not true and the image is stored as an embedded resource, in which use you would need to use something more like...
Toolkit.getDefaultToolkit().getImage(Bird.class.getResource("bird.jpeg"));
or
Toolkit.getDefaultToolkit().getImage(Bird.class.getResource("/bird.jpeg"));
There is still no guarantee that the image is loaded and none of these approaches actually tells you when it has failed.
A better solution would be to use ImageIO to read the image, apart from supporting more formats, it will throw an IOException when it fails...
public class Bird {
private Image sprite;
//...
public Bird(Main game) throws IOException {
image = ImageIO.read(getClass().getResource("/bird.jpeg"));
This...
while(true){
game.repaint();
Thread.sleep(10);
}
Is also very dangerous, you've started this in the main method, but you've take no consideration into what thread main might be called in. While in "normal" operations, main is called by the JVM from what is known as the "main thread", there is no guarantee that this is how your main method is called. It might called by another class from the context of the EDT which would cause the program to freeze.
Generally you should either use a javax.swing.Timer or a separate thread all together.
To display an image which fills the entire panel, you should have the following. You can use ImageIO.read(File) to read in an image from a file (you can adjust the position and size of the image inside the paintComponent method). You may want to also see Graphics.drawImage`.
import javax.swing.*;
import java.awt.image.*;
import java.awt.*;
public class PictureFrame extends JComponent{
private final Image img;
public PictureFrame(final String file) throws IOException {
this(new File(file));
}
public PictureFrame(final File file) throws IOException {
this(ImageIO.read(file));
}
public PictureFrame(BufferedImage img){
this.img = img;
this.setPreferredSize(new Dimension(img.getWidth(), img.getHeight()));
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(img, 0, 0, getWidth(), getHeight(), null);
}
}
Tester main:
public static final String TEST_FILE = "file path here";
public static void main(String... args) throws IOException {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
}
final JFrame frame = new JFrame();
final JComponent picture = new PictureFrame(TEST_FILE);
frame.setContentPane(picture);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 300);
frame.setVisible(true);
}
This question already has answers here:
Triangle Draw Method
(6 answers)
Closed 9 years ago.
Hey I know that it is simple to draw oval/rectangle and fill it using
g.fillOval(30, 40, 20, 20);
but how to draw a triangle? It would be the best if it would have random coordinates.
There are at least two basics ways you can achieve this, based on your needs.
You could use Polygon or you could make use the 2D Graphics Shape API
Which you might choose comes down to your requirements. Polygon requires you to know, in advance the position of the points within 3D space, where the Shape API gives you more freedom to define the shape without caring about the position in advance.
This makes the Shape API more flexible, in that you can define the shape once and simply translate the Graphics context as needed and repaint it.
For example...
Red is a Polygon, green is a Shape, which is translated into position...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TriangleTest {
public static void main(String[] args) {
new TriangleTest();
}
public TriangleTest() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private TriangleShape triangleShape;
private Polygon poly;
public TestPane() {
triangleShape = new TriangleShape(
new Point2D.Double(50, 0),
new Point2D.Double(100, 100),
new Point2D.Double(0, 100)
);
poly = new Polygon(
new int[]{50, 100, 0},
new int[]{0, 100, 100},
3);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
g2d.fill(poly);
g2d.setColor(Color.GREEN);
g2d.translate(50, 100);
g2d.fill(triangleShape);
g2d.dispose();
}
}
public class TriangleShape extends Path2D.Double {
public TriangleShape(Point2D... points) {
moveTo(points[0].getX(), points[0].getY());
lineTo(points[1].getX(), points[1].getY());
lineTo(points[2].getX(), points[2].getY());
closePath();
}
}
}
Using the legacy Graphics class, this would be done by using the legacy method
drawPolygon(int[] x, int[] y, int pointCount).
The newer class Graphics2D supports a much nicer implementation using Path2Ds. You will need either the draw(Shape) or fill(Shape) method. Given the fact that almost everywhere in Java a Graphics object is actually a Graphics2D object, you can cast it so, that is the way to go, IMHO.
Graphics g = ...;
Graphics2D g2d = (Graphics2D) g;
Path2D.Double triangle = new Path2D.Double();
triangle.moveTo(x1, y1);
triangle.pathTo(x2, y2);
triangle.pathTo(x3, y3);
triangle.closePath();
g2d.fill(triangle);
I am desperately trying to implement some things which I don't think I fully understand. I am attempting to set it up so the commented out actions can be taken (I will need to change syntax but I want to make sure I am on the right track first).
Am I going about this the right way? Where will my drawing actions go if not in the draw method? I get lots of errors when I move it there. Thanks
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Graphics2D;
import java.awt.Graphics;
public class Test extends JPanel{
abstract class graphic {
public Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
private int[] location = new int[] {screenSize.width/2,screenSize.height/2};
}
public class gladiator extends graphic {
void draw() {
//g2d.setColor(Color.green);
//g2d.fillArc(location[0], location[1], 100, 100, 45, 90);
//g2d.setColor(Color.black);
//g2d.fillArc((location[0]+50-10),(location[1]+50-10), 20, 20, 0, 360);
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
new Timer(200, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// setLocation((location[0]+1),location[1]);
repaint();
System.out.println("repainting");
}
}).start();
}
public void setLocation(int x, int y){
//this.location[0] = x;
//this.location[1] = y;
}
public static void main(String[] args){
JFrame jf=new JFrame();
jf.setDefaultCloseOperation
(JFrame.EXIT_ON_CLOSE);
jf.setPreferredSize(Toolkit.getDefaultToolkit().getScreenSize());
jf.add(new Test());
jf.pack();
jf.setVisible(true);
}
}
My original code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Test extends JPanel{
private int[] location = new int[2];
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.fillArc(location[0], location[1], 100, 100, 45, 90);
g.setColor(Color.black);
g.fillArc((location[0]+50-10),(location[1]+50-10), 20, 20, 0, 360);
new Timer(2000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setLocation((location[0]+50),50);
repaint();
System.out.println("repainting");
}
}).start();
}
public void setLocation(int x, int y){
this.location[0] = x;
this.location[1] = y;
}
public static void main(String[] args){
JFrame jf=new JFrame();
jf.setDefaultCloseOperation
(JFrame.EXIT_ON_CLOSE);
jf.setPreferredSize(new Dimension(300,500));
jf.setLocation(100,100);
jf.add(new Test());
jf.pack();
jf.setVisible(true);
}
}
Edit: Should have included this bit, first commenter was right.
The error is cannot find symbol, referring to g2d or g, whichever. I take it to mean that drawing can only happen inside of paint components and that I will have to find a way to include all the instructions for drawing there. I want to make sure I'm just doing something fundamentally wrong, though as this is my first brush with both abstract classes and 2d drawing in java. Also, I know the location[0] etc will not work as is. Lets ignore that.
The bottom code is what I am trying to accomplish (at least at first), but I am trying to use something similar to the top code to create multiple instances of it which can operate independently.
Move the timer out of paintcomponent.
You have declared an abstract class that has a draw method that needs a Graphics2D object to be able to draw, it has no access to it. It also makes little sense to declare a class just to hold two values (screensize and location) if that class also does stuff like drawing.
To fix the issues with 2, you can either let your gladiator extend JComponent, override its paintcomponent and place your draw() code in there and add gladiator to the panel as a component.
You can alternatively do active rendering, which means that you get the Graphic2D object of your canvas (the panel in this case) and take control of the rendering yourself instead of relying on swing.
Since you are working with swing I will give you a working example of what you probably intend to do. If you have more specific questions please do leave a comment.
public class Test extends JPanel {
public static abstract class graphic extends JComponent {
public Dimension dim = new Dimension(500, 500);
private int[] loc = new int[] { 250, 250 };
#Override
#Transient
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
public int[] getLoc() {
return loc;
}
public Dimension getDim() {
return dim;
}
}
public static class gladiator extends graphic {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.green);
g2d.fillArc(getLoc()[0], getLoc()[1], 100, 100, 45, 90);
g2d.setColor(Color.black);
g2d.fillArc((getLoc()[0] + 50 - 10), (getLoc()[1] + 50 - 10), 20,
20, 0, 360);
}
}
public static void main(String[] args) {
JFrame frame = new JFrame();
Test canvas = new Test();
gladiator gladiator = new gladiator();
canvas.add(gladiator);
frame.getContentPane().add(canvas);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
This renders