什么是Java中的“Paint”事件处理程序?

时间:2010-03-13 10:31:43

标签: java swing

Java中的事件处理程序(使用net beans,Swing)是什么类似于C#中的Paint? 表单恢复时应触发的事件,调整大小......等等。

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();
}

5 个答案:

答案 0 :(得分:4)

方法:

public void paint(Graphics g)
java.awt.Component类(它是所有Swing组件的超类)中的

是绘制的回调方法。因此,任何需要重新绘制的组件最终都会调用此方法,因此如果您希望执行自己的绘画,则可以覆盖它。

== UPDATE ==

您需要对组件进行子类化以获取绘制回调,例如

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

如果您不想创建一个全新的类,也可以使用匿名内部类,例如。

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

答案 1 :(得分:3)

您应该覆盖paintComponent方法,因为paint还负责绘制子组件,边框和执行其他操作。

答案 2 :(得分:1)

  

当发生时将被解雇的事件   表格被恢复,调整大小......等等。

我不确定我理解你的问题。 Swing将自动确保为您完成绘画,并且没有您可以收听的“绘画事件”。如果您想了解更多关于绘画的知识,那么您可以阅读Painting in AWT and Swing

如果您想知道表单是什么时触发的事件:

a)调整大小 - 使用ComponentListener
b)恢复 - 使用WindowListener

在上述情况下,请阅读Swing Tuturial中的相应部分。您还可以找到一个关于自定义绘画的部分,它解释了为什么应该在paintComponent()方法中完成绘制。

答案 3 :(得分:0)

repaint()。如果我没有弄错的话,它最终请求调用paint()paint()是真正的画家方法,但repaint()在恢复,调整大小等时被触发。

答案 4 :(得分:0)

在一个更美好的世界里,你不必重新发明轮子,但在当前的轮胎中,你可以这样做。

所以这里有一个BetterJPanel,它允许你添加和删除绘制事件,而不必每次都为JPanel创建子类。

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);
        }
    }    
}

以下是使用它的演示(注意不再有JPanel的子类化):

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);
    }
}

enter image description here

黑色矩形由第一个事件绘制,蓝色矩形由第二个事件绘制。

为什么要经历所有这些麻烦?可重用性:jjs(使用jjs -cp . test.js运行,随所有新Java版本一起提供):

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);

这个球以1/60秒的速度向东南方向移动,当它离开画布时从另一侧开始。

希望当Java9出现时,这种东西开始在核心Java中出现。