简体   繁体   中英

What did super.paintComponent(g) do?

So in the past few days I've tried to implement an easier version of a graph plotter. One big problem I was confronted with was a bug that occured on repainting. Basically I've designed my program in one class which is responsible for drawing the whole coordinate system and the given function after clicking a JButton in an other class. The other class contains the JButton which is pressed. After pressing the JButton it calls a function in the coordinate system class which repaints the picture. Both of those classes are extending JPanel.

The bug was that when I was doing the repainting on pressing the button, the button was drawn on the coordinate System and not in its original place, so in other words on the other JPanel even though I didn't change a thing about placements and stuff. Both classes were added to a JFrame which use a GridLayout.

Can anyone tell me why super.paintComponent(g); solved that bug?

Edit: Added Code

Window class

public class main {

public static void main(String[] args) throws SemanticFailureException {

    int x = 800;
    int y = 600;


    JFrame frame = new JFrame();
    frame.setLayout(new GridLayout());
    frame.setTitle("Function plotter");
    frame.setSize(2*x, 2*y);

    Surface test = new Surface(x, y, 10);
    CommandDraw test1 = new CommandDraw(x/2,y,test);


    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLocationRelativeTo(null);
    frame.add(test);
    frame.add(test1);


    frame.setVisible(true);

}
}

Coordinate System class: (changed drawing the coordinate system to a rectangle for simplicity, the bug still occures with only drawing a rectangle)

public class Surface extends JPanel {

/**
 * 
 */
private static final long serialVersionUID = 1L;
boolean drawFunct;

public Surface(int x1, int y1, int coordLength) {
    setSize(x1,y1);
    drawFunct = false;

}

public void paintComponent(Graphics g) {
    super.paintComponent(g); // without this the jbutton occures on the left

    // create Graphics object to get more functions
    Graphics2D g2 = (Graphics2D) g;
    // draw Plotter
    drawFunction(g2);

    if (drawFunct)
        g2.drawLine(0, 0, 80, 80);
}

public void drawFunction(Graphics2D g) {
    g.drawRect(40, 40, 30, 30);
}

public void redraw() {
    drawFunct = true;
    repaint();
}
}

The Class with the JButton:

public class CommandDraw extends JPanel {
/**
 * 
 */
private static final long serialVersionUID = 1L;
JButton makeDraw;
JTextField inputPoly;
Surface surf;

public CommandDraw(int x, int y, Surface surf) {
    this.surf = surf;
    setSize(x,y);
    setLayout(new FlowLayout());


    makeDraw = new JButton("draw Function");
    makeDraw.setBackground(Color.LIGHT_GRAY);
    makeDraw.setFocusable(false);

    makeDraw.addActionListener( new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            surf.redraw();

        }

    });

    add(makeDraw);


    inputPoly = new JTextField("Input polynomial");
    inputPoly.setHorizontalAlignment(JTextField.CENTER);
    add(inputPoly);


}
}

Can anyone tell me why super.paintComponent(g); solved that bug?

Because the call to paintComponent(g) of the superclass (JPanel) will guarantee that panel will be rendered as expected before you do your paint operations. You need to make sure that your JPanel will behave, in the Graphics perspective, like any other JPanel.

A template for a customized JPanel to draw should be something like:

import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;

public class MyDrawPanel extends JPanel {

    @Override
    protected void paintComponent( Graphics g ) {

        super.paintComponent( g );

        // create a new graphics context based on the original one
        Graphics2D g2d = (Graphics2D) g.create();

        // draw whatever you want...


        g2d.dispose();

    }

}

EDIT

You need to call super.paintComponent(g) to tell that the JPanel paintComponent(Graphics) version should be execute before you start doind your customized things. It's something like to ask the JPanel to prepare its paint capabilities to be used. A good starting point to these kind of doubts is the documentation: https://docs.oracle.com/javase/10/docs/api/javax/swing/JComponent.html#paintComponent(java.awt.Graphics)

The dispose() method is being called in the copy of the original Graphics . If you dispose the Graphics that is passed to the method, you may have some issues too. You could use the original Graphics to perform you painting operations, but you shouldn't, so a better practice is to make a copy of the original Graphics and dispose it after using.

Take a look here too: How does paintComponent work?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM