Java 中可以更改像素值的方法

Methods in Java which can change pixel values

我正在 java 开发一种动画程序,用于可视化。我正在使用 swingawt 库。我查看了它的十几个实现,它们都使用 paint Component 方法,然后当它们想在 JFrame 上绘制形状时使用 repaint()

有没有我可以从任何我想要的 class 调用的方法,例如可以更改单个像素值?

我还想制作一个形状为数组的列表:

ArrayList<Rectangle> rectangles = new ArrayList<Rectangle>(); 

而且我很好奇如何向其中添加内容。 我在想:

Rectangle rect = "something"
rectangles.add(rect);

但我不确定应该是什么。 我对此比较陌生,所以如果我遗漏了一些明显的东西,请随时表达你的观点。

Is there some method that I can call from any class that I want that can for example change a single pixel value?

您可以创建一个 BufferedImage,它有一个 setRGB(...) 方法,可以通过在 paintComponent(...) 方法中使用 Graphics drawImage(...) 方法绘制图像来实现您想要的效果。

关于 Rectangle rect = "something" -- 只需在 Rectangle API 中查找可用的 Rectangle 构造函数并使用最适合您的构造函数。

当我称每个人都是使用 repaint() 的白痴时,我显然是在咆哮;这是更好的方法。 假设我想在 jframe 上创建一个矩形或图像或线条或椭圆形,

public JFrame frame = new JFrame();
public void paintingHome(){
//set up the jframe and stuff
System.out.println("This is a rectangle");
paintARectangle(frame.getGraphics(), 42, 256);
}
public void paintARectangle(Graphics g, int xCoord, int yCoord, int width, int height){
g.fillRact(xCoord, yCoord, width, height);
//simple as that
}
//and you can have as many as you want
public void paintWhatever(Graphics g, Something whatever){
g.doSomethingWith(whatever);
//that won't actually work until oracle releases version 238249.3432.4
}
//the key is using the frame.getGraphics() method
//repaint is unnecessary and restrictive

有人建议您应该使用 getGraphics 而不是 paintComponent,让我们看一下……

糟糕,哦,这并不像我们预期的那样有效!让我们甚至忽略为什么你不应该直接绘制到顶层容器(因为那是在标题栏下绘制)

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JButton draw = new JButton("Draw");

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridBagLayout());
                frame.add(draw);
                frame.setSize(150, 150);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                draw.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        drawARectangle(frame.getGraphics());
                    }
                });
            }
        });
    }

    public void drawARectangle(Graphics g) {
        g.setColor(Color.RED);
        g.fillRect(20, 20, 100, 100);
    }

}

好吧,让我们看看paintComponentrepaint

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridBagLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private boolean drawBox;

        public TestPane() {
            setLayout(new GridBagLayout());
            JButton draw = new JButton("Draw");
            add(draw);
            draw.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    drawBox = !drawBox;
                    repaint();
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(150, 150);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (drawBox) {
                g.setColor(Color.RED);
                g.fillRect(20, 20, 100, 100);
            }
        }

    }

}

Swing 有详细的绘画过程文档,请查看 Painting in AWT and Swing and Performing Custom Painting 了解更多详细信息,并且应该在 API.

的设计中工作

在有人跳出我的喉咙并建议您可以使用 WindowListenerContainerListener 或其他一些听众之前,答案是,为什么? paintComponent 工作正常。

Swing 使用被动渲染引擎,这意味着绘制可能由于多种原因而发生,大多数情况下您没有实例化或不知道,因此除非您链接到绘制过程中,否则您不会不知道它发生了,调整大小只是一个很好的演示方式

那么我们能否停止建议使用 getGraphics 或使用 null 布局或 KeyListenerDocumentListener 实时过滤文本组件等不良方法,也许我们可以让一堆人省一堆头疼