Search code examples
javaswingpaintrepaint

Java -Repaint() not working when i want to call it


I wonder why the repiant() method is not working as intended. My Code:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JPanel;

public class RightPanel extends JPanel implements ActionListener{
    JButton buttono;
    JButton buttonu;
    MyFrame frame;
    ButtomPanel s;
    
    public RightPanel(MyFrame frame){
        super();
        this.frame=frame;
         s= new ButtomPanel(frame);
        this.setPreferredSize(new Dimension((frame.getWidth()/3),frame.getHeight()));
        setBackground(Color.green);
        setLayout(new BorderLayout());
        
        buttono = new JButton ("up");
        buttonu = new JButton ("down");
        buttono .addActionListener(this);
        buttonu .addActionListener(this);
        add(buttono , BorderLayout.NORTH);
        add(buttonu , BorderLayout.SOUTH);
        
        setVisible(true);
    }
    


    @Override
    public void actionPerformed(ActionEvent e) {
        
        
        if (e.getSource()==buttono) {
            System.out.println("Up");
        s.x=s.x+10;
        s.repaint();
        
        
    }
}

I want to Repaint following class:

import java.awt.Color;
import java.util.Timer;
import java.util.TimerTask;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class ButtomPanel extends JPanel {
    MyFrame frame;

    
     BufferedImage image;
     boolean geklickt=false;
     
     public static int x=0;;
    public ButtomPanel(MyFrame frame) {
        super();
        this.frame=frame;
        this.setPreferredSize(new Dimension(((frame.getWidth()/3)*2),585));     
        setBackground(Color.blue); 
        
        
        
        java.net.URL resource = getClass().getResource("/resources/siegel.jpg");
        try {
            image = ImageIO.read(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
    
        setVisible(true);
        
    }

    public void paint(Graphics g) {
        super.paint(g);       
        g.drawImage(image, 150+x, 150+x, 150, 150, null);}
 
 }
}

I want to change with the ActionListener in the RightPanel Class the x from the BottomPanel Class and then repaint it, but it doesnt work. I can raise the x, but s.repaint() does not call the paint-Method.


Solution

  • s is never added to anything, so it will never be painted.

    this.setPreferredSize(new Dimension((frame.getWidth()/3),frame.getHeight())); is a horribly bad idea. The window should be conforming to the size of the components, not the other way round. In fact, there's never really a good reason to expose MyFrame to the components this way, it provides these components control over MyFrame which they should never have.

    java.net.URL resource = getClass().getResource("/resources/siegel.jpg");
    try {
        image = ImageIO.read(resource);
    } catch (IOException e) {
        e.printStackTrace();
    }
    

    is a bad idea. The class should be throwing the exception to those using it, so that they know something has gone wrong. Doing it this way not only consumes the error in a way which is difficult to trace, but also sets you up for a NullPointerException when you call g.drawImage(image, 150+x, 150+x, 150, 150, null)

    Don't override paint

    public void paint(Graphics g) {
        super.paint(g);       
        g.drawImage(image, 150+x, 150+x, 150, 150, null);
    }
    

    prefer paintComponent instead. paint is actually a very complex method. See Painting in AWT and Swing and Performing Custom Painting for more details

    public static int x=0; is a bad idea for a three reasons:

    1. static is not your friend. What happens when you have more than one instance of ButtomPanel? Generally speaking, when you use static in this way, it's a red flag telling you that your design is wrong.
    2. public is providing uncontrolled access to the property. This is generally discouraged and you could be preferring to use setters and getters to interact with the property.
    3. JPanel already has a x property, which could make it confusing (ie if if someone used getX instead of x). Better to rename it to something like imageX of imageXOffset.

    Runnable example...

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.imageio.ImageIO;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    public final class Main {
        public static void main(String[] args) {
            new Main();
        }
    
        public Main() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        JFrame frame = new JFrame();
                        frame.add(new RightPanel());
                        frame.pack();
                        frame.setLocationRelativeTo(null);
                        frame.setVisible(true);
                    } catch (IOException ex) {
                        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            });
        }
    
        public class RightPanel extends JPanel implements ActionListener {
            JButton buttono;
            JButton buttonu;
            ButtomPanel s;
    
            public RightPanel() throws IOException {
                super();
                s = new ButtomPanel();
                setBackground(Color.green);
                setLayout(new BorderLayout());
    
                buttono = new JButton("up");
                buttonu = new JButton("down");
                buttono.addActionListener(this);
                buttonu.addActionListener(this);
                add(buttono, BorderLayout.NORTH);
                add(buttonu, BorderLayout.SOUTH);
    
                add(s);
    
                setVisible(true);
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                if (e.getSource() == buttono) {
                    System.out.println("Up");
                    s.addToImageXOffset(10);
                }
            }
        }
    
        public class ButtomPanel extends JPanel {
            private BufferedImage image;
            private int imageXOffset = 0;
    
            public ButtomPanel() throws IOException {
                super();
                setBackground(Color.blue);
                image = ImageIO.read(getClass().getResource("/images/Heart.png"));
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(400, 400);
            }
    
            public void addToImageXOffset(int delta) {
                setImageXOffset(getImageXOffset() + delta);
            }
    
            public void setImageXOffset(int imageXOffset) {
                this.imageXOffset = imageXOffset;
                repaint();
            }
    
            public int getImageXOffset() {
                return imageXOffset;
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
                g.drawImage(image, 150 + imageXOffset, 150 + imageXOffset, this);
            }
    
        }
    }