I have a problem with how to make an other parameter in the paintComponent method.
I have not found other ways.
import javax.swing.*;
import java.awt.*;
public class Interface extends JPanel
{
protected void paintComponent(Graphics g *here(not part of code btw)*) {
super.paintComponent(g);
g.setColor(Color.orange);
g.fillRect(0, 0, 100, 100);
}
public void CreateWindow(String name, int Xsize, int Ysize) {
//laver et JFrame og klader det "frame" !
JFrame frame= new JFrame();
frame.setTitle(name);
frame.setSize(Xsize, Ysize);
frame.setLocation(200, 200);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
Interface JPanel = new Interface();
frame.add(JPanel);
Graphics Grafik = getGraphics();
paintComponent(Grafik);
}
}
When I run the code with a parameter there its doesn't draw a rectangle.
But if there are only the Graphics parameter it runs fine.
As you can see in the Javadoc, there is only one defined method for paintComponent in JComponent. This means that there is not a way that you can do this, without creating your own JComponent and extensions (subclasses) of JComponent (which would be unnecessarily complicated and difficult). Instead, consider that you can use fields within your class to store the persistent state you need when entering the method paintComponent. Temporary variables, on the other hand, are best defined as local to the method.
Additionally, it's not good practice to name your class Interface, as interface is a reserved keyword in Java.
tl;dr - Essentially, no. Use fields/local variables to store your additional data.
Related
I am trying to learn game design in Java and I am following a tutorial. The tutorial gives this code, but not a lot of elaboration. I had some questions regarding Java and graphics.
import java.awt.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Game2 extends JPanel {
#Override
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
g2d.fillOval(0, 0, 30, 30);
g2d.drawOval(0, 50, 30, 30);
g2d.fillRect(50, 0, 30, 30);
g2d.drawRect(50, 50, 30, 30);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Mini Tennis");
frame.add(new Game2());
frame.setSize(300, 300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Why do we need to extend JPanel into the class Game2? I have never used extends on my main class, so I'm not sure what it means in this case and why it is necessary.
What does frame.add(new Game2()); mean? Why are we allowed to make a new Game2() within the Game2() class?
What are the Graphics and Graphics2D objects? Also couldn't we just use a Graphics2D object as the parameter of paint() since we never use g outside of typecasting it to a Graphics2D object.
Lastly, why don't we need to call paint()?
You can extend (almost) whatever component you like. The crucial thing here is that you put the component onto a JFrame which makes it a base for the new window. Using JPanel is good because it contains no graphics and therefore can serve as plain canvas.
frame.add(new Game2()) puts the JPanel you're extending into a JFrame.
You can create class instances freely wherever you want as long as they're visible to you in the given scope.
An instance of the Graphics2D class is passed to the paint() method automatically whenever the underlying operating system decides it's time to redraw the component (for example upon showing the window or dragging another window over the component).
The parameter is always of type Graphics (meaning that the value can be of the same type or any class that extends it). This is given by the definition of the method (meaning that some of the parent classes or interfaces declares it like this) and you cannot change it.
Please take some time to get acquainted with the basics of object oriented programming before you start with anything more complicated:
https://www.w3schools.com/java/java_oop.asp
Disclaimer: I'm new to Java. I'm new to Swing. And I'm sure it shows.
I've viewed quite a number of examples/tutorials of how to draw on a jpanel "canvas". But they mostly have the same basic format and put all of their drawLine/drawRect/drawArc inside the paintComponent() method. It seems assumed that people want to draw static things to the jpanel one time. But what if I want to change the jpanel object over the course of the program's runtime, like a paint program, or a game?
I suppose I need to be able to access the jpanel object, and internal methods to paint. I'm betting what I'm doing isn't best practices, but here is what I have:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class PaintPanel extends JPanel {
public static JFrame frame;
private Graphics g = getGraphics();
public static void main(String[] args) {
frame = new JFrame();
frame.getContentPane().setBackground(new Color(32, 32, 32));
frame.setResizable(false);
frame.setBounds(1, 1, 800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
frame.setVisible(true);
frame.setLocationRelativeTo(null); // center frame on screen
PaintPanel paintPanel = new PaintPanel();
paintPanel.setBounds(10, 10, 100, 100);
paintPanel.setBackground(Color.red);
frame.add(paintPanel);
}
// constructor
public PaintPanel() {
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
}
public void DrawRect(Integer x, Integer y, Integer w, Integer h, Color color) {
g.setColor(color);
g.fillRect(x, y, w, h);
this.repaint(); // doesn't seem to do anything
}
}
This code results in a red panel box, but my user method DrawRect() doesn't draw anything.
I've read in some places that it's necessary to override the paintComponent() method. If there's nothing in it, what's the purpose?
How can I get my DrawRect() method to work?
The piece of the puzzle you're missing is the model object. There should be an external object that describes what should be drawn. In a game for example, it would be something that describes the current state of the game.
Your custom component looks at this model and takes the necessary steps to paint it. This is implemented in paintComponent and in helper methods you see fit to add.
To make an animation, you make a loop that modifies the model over time, and asks the custom component to redraw itself with repaint().
So I have two classes, one is in charge of creating the JPanel and also overrides paint. The other contains the main and uses this other class. For the sake of ease, I've cut out what isn't involved in graphics. This first one does the JPanel and paint. The second is the main. I apologize for any poor structure or mess, I'm relatively new and I've just been throwing things in to see what works. The stuff in the paint is only a test, it isn't the primary goal.
public class PokerTable extends JPanel {
private static final int WIDTH = 800;
private static final int HEIGHT = WIDTH * 3 / 4;
private static final String NAME = "Test";
private JFrame frame = new JFrame(NAME);
public PokerTable() {
//frame.setMinimumSize(new Dimension(WIDTH,HEIGHT));
//frame.setMaximumSize(new Dimension(WIDTH,HEIGHT));
frame.setPreferredSize(new Dimension(WIDTH,HEIGHT));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setBackground(Color.GREEN);
g2d.setColor(Color.RED);
g2d.fillOval(0, 0, 30, 30);
}
}
This next one does more than call the PokerTable, but I've left the other parts out as they rely on other classes and just print to console.
public class Poker{
public static void main(String[]args) {
System.out.println("hello");
PokerTable pt = new PokerTable();
pt.repaint();
}
Not that I necessarily expected it to work, I've changed the extension on PokerTable to Canvas and JFrame without any luck.
You're not adding the panel to the frame, try with:
frame.add(this);
in PokerTable constructor
You need to add the panel to the frame, or the panel will never repaint.
frame.add(panel) or frame.add(this)
is what you need to call depending on where you do it.
Also, you should be overriding paintComponent, and never paint directly. that won't cause your code to fail, but it is bad practice.
I have been playing around with Java's 2d painting tools and have hit a snag. I am attempting to move the objects. Here is the 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);
}
}
This only paints one of the two objects to the screen... it seems to be the second one as when I change the parameters of setLocation on [1] the one object it does paint moves. Any thoughts? Thanks
Edit: Edited above code to reflect what was said below.
You are adding two components to the JFrame in a default way. This will add the components BorderLayout.CENTER and so the second component will cover and obscure the first. You will want to read up on layout managers to fix this. Also read up on Swing Timers for simple animations, since your code, even if written correctly would do no animation.
If you want to move the drawing, then
Use only one Test JPanel
Override JPanel's paintComponent(...) method, not paint(...) method.
call the super.paintComponent(g) method first thing in your paintComponent method override.
Give the Test JPanel public methods to allow outside classes to change the location without having them directly futz with the field. Make the location field (name should begin with a lower-case letter) private just to be safe.
Use a Swing Timer to periodically call this method and change location, then call repaint() on the JPanel.
From previous experience, everyone will say "Don't use those setXxxSize methods! Use a layout manager!" However, what should I do in this case?
import java.awt.*;
import javax.swing.*;
public class Game {
public static void main(String[] args) {
new Game();
}
public Game() {
JFrame f = new JFrame("Hi this is a game");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new GamePanel());
f.pack();
f.setVisible(true);
}
private class GamePanel extends JPanel {
private GamePanel() {
setPreferredSize(600, 600);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
//paint stuff
}
}
}
This is just some example code I threw together real quick. What should I do when I need to make the game area, say, 600 by 600? Is it okay to use setPreferredSize here? I don't know of any layout manager that can just take a single component and give it a size, and even if there is, isn't it a lot easier to just use this instead of having to use an entire layout manager?
By the way, f.setSize(600, 600) doesn't work here because it takes into account the frame decorations (title bar, border things).
So the question is if I only have one component that needs to be a specific size, what do I do?
Override getPreferredSize, in GamePanel:
public Dimension getPreferredSize(){
return new Dimension(600, 600);
}
Why do this and not just setPreferredSize()?
As Game is a JPanel that is
Used solely for drawing,
Contains a default layout but no components and
Has a standard UI delegate,
the difference is negligible. There are still reasons to override getPreferredSize()
The intent is clear to other developers; demos and prototypes, like zombies, never go away.
Any one or all of those conditions may change as the class evolves.
It's an idiomatic reminder not to fall into this trap.