简体   繁体   中英

What is “Paint” event handler in Java?

What is the event handler in Java (using net beans, Swing) that resembles the Paint in C#? The event which shall be fired when the form is restored, resized ... etc

public void paint(Graphics g2){
    g2 = pnlDrawing.getGraphics();
    g2.clearRect(0, 0, size, size);
    g2.setColor(Color.BLACK);
    g2.fillRect(size/2-1, 0, 2, size); // draw y axis
    g2.fillRect(0, size/2-1, size, 2); // draw x axis

    //set the font
    g2.setFont(new Font("Arial", 2, 12));

    // write the values on the X axis
    for(int i=0; i<=10; i++){
        if(i == 0)
            continue;
        int pos1 = (size/2-1)-i*30;
        int pos2 = (size/2-1)+i*30;
        g2.draw3DRect(pos1, size/2-3, 1, 5, true);
        g2.drawString(String.valueOf(-i),pos1-10,size/2-3+20);
        g2.draw3DRect(pos2, size/2-3, 1, 5, true);
        g2.drawString(String.valueOf(i),pos2-5,size/2-3+20);
    }

    for(int i=0; i<=10; i++){
        if(i == 0)
            continue;
        int pos1 = (size/2-1)-i*30;
        int pos2 = (size/2-1)+i*30;
        g2.draw3DRect(size/2-3, pos1, 5, 1, true);
        g2.drawString(String.valueOf(i),size/2-3+10,pos1+5);
        g2.draw3DRect(size/2-3, pos2, 5, 1, true);
        g2.drawString(String.valueOf(-i),size/2-3+10,pos2+5);
    }

       pnlDrawing.invalidate();
}

The method:

public void paint(Graphics g)

in the java.awt.Component class (which is the superclass for all Swing components) is the callback method for painting. So any repainting of the components that needs to be done will eventually call this method, so you can override it if you wish to perform your own painting.

== UPDATE ==

You need to subclass a component to get the paint callback, eg

public class MyPanel extends JPanel {
    public void paint(Graphics g) {
        // do your painting here
    }
}

Or you could use an anonymous inner class if you don't want to create a whole new class, eg

pnlDrawing = new JPanel() {
    public void paint(Graphics g) {
        // Your painting code
    }
}

您应该重写paintComponent方法,因为paint也负责绘制子组件,边框和其他一些工作。

The event which shall be fired when the form is restored, resized ... etc

I'm not sure I understand your question. Swing will automatically make sure the painting is done for you and there is no "paint event" that you can listen for. If you want to understand more about painting then you can read up on Painting in AWT and Swing .

If you want to know what event is fired when a form is:

a) resized - use a ComponentListener
b) restored - use a WindowListener

In the above cases read the appropriate section from the Swing Tuturial . You will also find a section on Custom Painting which explains why paint should be done in the paintComponent() method.

repaint() . it makes a request to call paint() eventually though, if I'm not mistaken. paint() is the real painter method but repaint() is fired in those restore, resize etc.

In a better world, you wouldn't have to reinvent the wheel, but in the current one, you do.

so here is a BetterJPanel which allows you to add and remove paint events without having to subclass JPanel every time.

BetterJPanel

import java.util.function.*;
import java.util.*;
import javax.swing.*;
import java.awt.*;

public class BetterJPanel extends JPanel
{
    protected Map<String, ArrayList<Function<Map<String, Object>,Void>>> events;
    public final static long serialVersionUID = -4405124172582504448L;

    public BetterJPanel()
    {
        super();
        this.events = new HashMap<String, ArrayList<Function<Map<String, Object>, Void>>>();         
    }

    public void paint(Graphics g)
    {   
        ArrayList<Function<Map<String, Object>,Void>> paintEvents = null;

        if (this.events.containsKey("paint")) {
            paintEvents = this.events.get("paint");

            for (Function<Map<String, Object>,Void> evt : paintEvents) {
                Map<String, Object> eventArguments = new HashMap<String, Object>();
                eventArguments.put("graphics", g);

                evt.apply(eventArguments);
            }    
        }            
    }

    public void on(String eventName, Function<Map<String, Object>, Void> cb)
    {
        if (!events.containsKey(eventName)) {
            ArrayList<Function<Map<String, Object>,Void>> tmp = new ArrayList<Function<Map<String, Object>,Void>>();

            events.put(eventName, tmp);
        }

        events.get(eventName).add(cb);
    }

    public void off(String eventName, Function<Map<String, Object>, Void> cb)
    {
        ArrayList<Function<Map<String, Object>,Void>> events = null;

        if (this.events.containsKey(eventName)) {
             events = this.events.get(eventName);

             events.remove(cb);
        }
    }    
}

Here's a demonstration of using it(note no subclassing of JPanel anymore):

import java.util.function.*;
import java.awt.*;
import javax.swing.*;
import java.util.*;

public final class TestBetterJPanel
{
    public static void main(String[] args)
    {
        JFrame f = new JFrame("Better JPanel Testing");
        BetterJPanel p = new BetterJPanel();

        p.on("paint", evt -> {
            Graphics g = (Graphics)evt.get("graphics");
            g.setColor(Color.BLACK);
            g.fillRect(0, 0, 800, 500);

            return null;
        });
        p.on("paint", evt -> {
            Graphics g = (Graphics)evt.get("graphics");
            g.setColor(new Color(0x33, 0x66, 0xff));
            g.fillRect(0, 0, 400, 500);

            return null;
        });

        p.setPreferredSize(new Dimension(800, 500));
        f.add(p);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

在此处输入图片说明

The black rectangle is drawn by first event, the blue one by the second event.

Why go through all this trouble? reusability: jjs(run with jjs -cp . test.js , comes with all new Java versions):

var Thread = java.lang.Thread;
var BetterJPanel = Java.type("BetterJPanel");
var JPanel = javax.swing.JPanel;
var Dimension = java.awt.Dimension;
var Color = java.awt.Color;
var JFrame = javax.swing.JFrame;

var frame = new JFrame("Hello, World!");
var panel = new BetterJPanel();

panel.setPreferredSize(new Dimension(800, 500));
frame.add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

var x = 20;
var y = 20;

panel.on("paint", function(e) {
    var g = e.graphics;

    g.setColor(Color.BLACK);
    g.fillRect(0, 0, 800, 500);

    g.setColor(new Color(0x33, 0x66, 0x99));
    g.fillOval(x, y, 30, 30);
});

new Thread(function() {
    for (;;) {
        x += 1;
        y += 1;

        if (x > 800) {
            x = 0;
        } 
        if (y > 500) {
            y = 0;
        }

        panel.repaint();
        Thread.sleep(1000 / 60);
    }
}).start();


frame.setVisible(true);

This ball is moving southeast at ~1 pixel per 1/60 of a second, starting over on the other side when it leaves the canvas.

Hopefully when Java9 comes around, this kind of stuff starts popping up in core Java.

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