简体   繁体   English

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

[英]What is “Paint” event handler in Java?

What is the event handler in Java (using net beans, Swing) that resembles the Paint in C#? Java中的事件处理程序(使用Net Bean,Swing)是什么类似于C#中的Paint? 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. java.awt.Component类(这是所有Swing组件的超类)中的是绘画的回调方法。 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. Swing将自动确保为您完成绘画,并且没有可以听的“绘画事件”。 If you want to understand more about painting then you can read up on Painting in AWT and Swing . 如果您想了解有关绘画的更多信息,则可以阅读AWT和Swing中的绘画

If you want to know what event is fired when a form is: 如果您想知道表单是什么时候触发什么事件:

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

In the above cases read the appropriate section from the Swing Tuturial . 在上述情况下,请阅读Swing Tuturial中的相应章节。 You will also find a section on Custom Painting which explains why paint should be done in the paintComponent() method. 您还将在“自定义绘画”中找到一个部分,其中解释了为什么应在paintComponent()方法中进行绘画。

repaint() . repaint() it makes a request to call paint() eventually though, if I'm not mistaken. 如果我没记错的话,它最终会发出一个调用paint()的请求。 paint() is the real painter method but repaint() is fired in those restore, resize etc. paint()是真正的painter方法,但是在还原,调整大小等情况下会触发repaint()

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,它使您可以添加和删除绘画事件,而不必每次都将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);
        }
    }    
}

Here's a demonstration of using it(note no subclassing of JPanel anymore): 这是使用它的演示(请注意,不再包含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);
    }
}

在此处输入图片说明

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): 可重用性: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);

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. 该球以每1/60秒约1像素的速度向东南移动,当它离开画布时从另一侧开始。

Hopefully when Java9 comes around, this kind of stuff starts popping up in core Java. 希望当Java9出现时,此类内容会在核心Java中开始出现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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