I'd like to know how you are supposed to override a paint method for each panel in the same class and how to call them separately?
I only know about the repaint() call when you are in a class that extends JPanel (so in only one panel), not when you just make panels.
Thanks in advance.
Typically you create a class that extends JPanel to override the paintComponent method:
public class Test extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// code here
}
public void doStuff() { repaint(); }
}
You might consider creating a nested class like so:
public class Test {
public class MyPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// code here
}
}
JPanel panel = new MyPanel();
panel.repaint();
}
Or you can do this without creating a class that extends JPanel:
JPanel panel1 = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// code here
}
};
panel1.repaint();
I think the normal thing is to extend JPanel for each unique panel you wish to create. In other words, each panel you create is its own class. Then you can overwrite the paint method for each individually.
Related
public void display() {
pan.repaint();
fen.add(pan);
fen.addKeyListener(this);
fen.setResizable(false);
fen.setTitle("Le Jeu 2D");
img.setText("Coucou");
pan.add(img);
pan.repaint();
pan.setBackground(Color.yellow);
fen.setVisible(true);
fen.setSize(480, 272);
pan.repaint();
fen.revalidate();
}
public void paintComponent(Graphics g) {
System.out.println("zzz");
pan.paint(g);
g.setColor(Color.red);
g.drawRect(10, 10, 10, 10);
}
It doesn't draw anything. Why? I have defined the paint component method, so I don't understand why.
Edit: I edited my code, please take a look
You don't create an instance of your Game class and don't add it to the JFrame.
Here is the Game panel which you are painting on:
Game.java
public class Game extends JPanel {
#Override
public final void paintComponent(final Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.drawRect(10, 10, 10, 10);
}
#Override
public Dimension getMinimumSize() {
return new Dimension(300, 300);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
#Override
public Dimension getMaximumSize() {
return new Dimension(300, 300);
}
}
You then need to create an instance of this Game panel and add it to your JFrame:
GameFrame.java
public class GameFrame extends JFrame {
public GameFrame() {
setLocationRelativeTo(null);
setResizable(false);
setTitle("2D Game");
Game game = new Game();
setContentPane(game);
pack();
setVisible(true);
}
}
Then when you create an instance of the JFrame:
Example.java
public class Example {
public static void main(String[] args) {
new GameFrame();
}
}
The panel will be added, and painted:
You never create an instance of the Game class and you never add the Game class to the frame. Even if you did create an instance the size would still be (0, 0) so there would be nothing to paint.
Basically the whole structure of your code is wrong.
I suggest you start over and start with the demo code found in the Swing tutorial on Custom Painting.
The basic structure of your code seems weird.
You could instantiate a JFrame in your main control class, ie. it should be GAME class in this case. Then you can create a new JPanel class and add its object into the JPanel object. Within the JPanel class, you can create all the elements you need and set corresponding parameters. You could also add the event listener in an inner class or a separate class.
Am I able to override a method on demand? I have a class that extends JFrame and has a JPanel inside. I want to draw a circle in the JPanel but I don't want to have an own class for the JPanel (then I could override paintComponent). My idea was something like this:
public class KugelClient extends JFrame {
public KugelClient() {
super("KugelClient");
JPanel panel = new JPanel();
panel.paintComponent(Graphics g) {
//overriding method here
g.fillOval(...);
}
}
Is there anything in Java which makes it possible to do something like this (e.g. with lambda?) or do I have do create an own class for the panel?
You can create an anonymous subclass of JPanel with an overriden paintComponent() method. Something like this:
JPanel panel = new JPanel() {
//overriding method here
public void paintComponent(Graphics g) {
g.fillOval(...);
}
};
I ran into a problem where no matter what I do my JPanel won't repaint. I was using the following method to create a connect four game board and dynamically change the color of the circles as the play progresses, but I've simplified it into a test class which has the same issue.
I decided to use a state pattern design for each of the circles. The following is the code for the classes so it knows which color to print which are JPanel children classes.
public class GridCircle extends JPanel
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillRect(0, 0, 100, 100);
}
}
public class WhiteGridCircle extends GridCircle
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.WHITE);
g.fillOval(5, 5, 80, 80);
}
}
public class RedGridCircle extends GridCircle
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.RED);
g.fillOval(5, 5, 80, 80);
}
}
The following is a test class where I attempt to change the class of a JPanel in the main method to see if it would change the color that is painted (which fails).
public class test extends JFrame
{
static JPanel testPanel = new WhiteGridCircle();
public static void main(String[] args)
{
new test();
testPanel = new RedGridCircle();
testPanel.revalidate();
testPanel.repaint();
}
test()
{
this.add(testPanel);
this.setSize(150,150);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}
}
I can't figure out why the panel wouldn't repaint no matter what I've tried. From what I understand repaint() has no guarantee to call a the paint method but I see no reason it shouldn't when theres nothing else going on.
Because instance you created and added this.add(testPanel); is still new WhiteGridCircle().
You changed instance but the original one added to JFrame remains in the frame.
To change call this.getContentPane().add(testPanel); after instantiating RedGridCircle and before revalidate() call.
I need to draw a square,line,circle when pressed the corespondent button. Also I need to do this using FactoryMethod design pattern.
I simply don't get how to draw on the same canvas, and because I have a class for every shape, how do i get the corresponding paint(Graphics g) method?
This is what I have so far:
public interface Shape
{
public void draw();
}
Square class
public class Square extends Canvas implements Shape
{
Graphics g;
Canvas c;
public Canvas getCanvas()
{
return c;
}
public void setCanvas(Canvas c)
{
this.c=c;
}
#Override
public void draw()
{
g.drawRect(20, 30,100,100);
}
public void paint(Graphics g)
{
g.drawRect(20, 30,100,100);
g.setColor(Color.BLUE);
}
}
Factory
public class ClassFactory extends Canvas{
JButton patrat;
Figura d;
String nameButon;
Graphics g;
Canvas c;
public Canvas getCanvas()
{
return c;
}
public void setCanvas(Canvas c)
{
this.c=c;
}
public ClassFactory()
{
super();
this.setBounds(0,0,500,450);
this.setBackground(Color.CYAN);
JButton square=new JButton("square");
patrat.setBounds(510, 10, 80,25);
JPanel panel=new JPanel();
panel.setLayout(null);
panel.setBounds(0,0,600,500);
panel.setBackground(Color.GRAY);
panel.add(this);
this.addComponentListener(p);
panel.add(square);
JFrame f=new JFrame("Draw");
f.setLayout(null);
f.setBounds(50,50,700,600);
f.getContentPane().setBackground(Color.DARK_GRAY);
f.setResizable(false);
f.add(panel);
f.show();
}
public Shape getFigure()
{
Shape d=null;
if(nameButton.equals("square"))
{
d=new Square();
}
return d;
}
}
Suggestions:
The factory should not create a GUI, should not extend Canvas, or really extend anything, it should not create a JFrame or do anything of the sort. It should concern itself only with creating objects of Shape child classes. The GUI creation code should be elsewhere.
Likely the factory's getFigure(...) method will be the one to produce this. It should likely accept a parameter, perhaps a String or an enum, that tells it what sub-class of Shape to produce.
Shape's draw method should likely accept a Graphics parameter so that its children can use it to draw with.
You shouldn't mix AWT components (i.e., Canvas) and Swing components together unnecessarily. Instead, just draw in a JPanel's paintComponent(Graphics g) method, not in a Canvas's paint(Graphics g) method.
In that JPanel have a Shape variable that is not initialized, perhaps called shape.
Inside of paintComponent(...) check if shape is null. If not, draw it by calling shape.draw(g).
In your JButton ActionListeners, have the Factory create a Shape child class object and assign it to the shape variable
Then call repaint() on the JPanel that does the drawing.
public class MyDrawPanel extends JPanel {
public void paintComponent(Graphics g){
Graphics2D gd2 = (Graphics2D) g;
GradientPaint gradient = new GradientPaint(70,70,Color.blue,150,150,Color.red);
}
}
Why is this valid but not this:
public class MyDrawPanel extends JPanel {
public void paintComponent(Graphics2D g){
GradientPaint gradient = new GradientPaint(70,70,Color.blue,150,150,Color.red);
g.setPaint(gradient);
g.fillOval(70,70,100,100);
}
}
First one renders, but the second one renders no graphics other than the frame. I noticed that paintComponent() requires a Graphics object, but if Graphics2D is a subclass of the Graphics object why can I not call a subclass of Graphics?
Is there some concept I am not picking up as to why this is?
It says that you should implement it this way, because Graphics2D is Graphics, while Graphics is not Graphics2D.
If you find casting disturbing, you can always create your own eg. MyJPanel that extends JPanel, define your own method, and subclass it in the future, overriding your defined method.
public class MyJPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
paintComponent((Graphics2D) g);
}
protected void paintComponent(Graphics2D g) {
}
}
Basically, when you override a method, you can be equally or less specific.
Think about this:
JPanel p = new MyPanel();
p.paintComponent(someGraphicsInstance);
A reference to a JPanel is expected to be able to accept a Graphics reference as a parameter to the paintComponent method. Your method, however, violates that requirement as it will not accept a Graphics instance, but only a Graphics2D.
More information about this can be found https://stackoverflow.com/a/9950538/567864