Java对已添加的对象进行更改

时间:2016-05-07 00:34:13

标签: java swing

我目前正在为学校开展一个小项目,而且我还处于起步阶段。我刚刚开始阅读JFrame和所有这些内容,所以不要错过为什么我可能不会那么熟悉你将给我看的一切。

现在的目标是拥有一个程序,该程序可以显示图像并能够手动更改该图像的每个像素。因此,我写了以下代码:

public class JavaGraphicsTest {
    private static Pixel pixel;

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.setVisible(true);
        pixel = new Pixel(1600, 900);
        frame.getContentPane().add(pixel);
        //pixel.testChange();
    }
}

public class Pixel extends Component {
    private BufferedImage img;
    private int width;
    private int height;
    private Graphics graphics;

    public Pixel(int w, int h) {
        width = w;
        height = h;
    }

    public void create() {
        img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        //Set any color for now
        for(int wc = 0; wc < width; wc++) {
            for(int hc = 0; hc < height; hc++) {
                img.setRGB(wc, hc, new Color(0xAAFFBB).getRGB());
            }
        }
    }      

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        graphics = g;
        create();
        update();
    }

    public void update() {
        graphics.drawImage(img, 0, 0, null);
    }

    public void testChange() {
        for(int i = 50; i < 80; i++) {
            for(int  j = 80; j < 120; j++) {
                img.setRGB(i, j, new Color(0xFF8876).getRGB());
            }
            for(int  j = 460; j < 493; j++) {
                img.setRGB(i, j, new Color(0xFF8876).getRGB());
            }
        }
    }
}

嗯,代码工作到目前为止(经过几个小时的讨厌错误发现xD),但我现在想要做的似乎是没有工作到目前为止:我想调用方法&#34; pixel.testChange() &#34;在主要方法(它目前评论)。但据我所知,JFrame是如何工作的,一旦我将它添加到JFrame中,我就无法对对象做任何事情。但那谁应该工作呢?如何修改任何活动对象而不删除并重新添加它?

PS:如果您不了解testChange方法应该做什么:它应该将图像的两个块更改为另一种颜色,它基本上是一个测试,看看我是否成功更改了图像

如果您需要有关该项目的更多信息,请问我:)

提前致谢, 儒略

2 个答案:

答案 0 :(得分:4)

不要存储Graphics对象。如初。

public class Pixel extends Component {
    private Graphics graphics;  // <<-- DO NOT DO THIS

    @Override
    public void paint(Graphics g) {
        // ...
        graphics = g;    // <<-- DO NOT DO THIS
        // ...
    }
}

每次调用#paint(Graphics g)时都可以重新创建图形对象,并在#paint(Graphics g)退出时失效,销毁或损坏。

同上,请勿在{{1​​}}来电期间创建图片。只有在创建#paint(Graphics g)时才能执行此操作。

Pixel

但您可以安全地将public class Pixel extends Component { @Override public void paint(Graphics g) { // ... create(); // <<-- DO NOT DO THIS, EITHER. // ... } } 对象传递给从Graphics调用的其他方法。

paint(Graphics g)

确定。对于手头的业务 - 您的public class Pixel extends Component { // ... public Pixel(int w, int h) { width = w; height = h; create(); } @Override public void paint(Graphics g) { super.paint(g); update(g); } private void update(Graphics g) { graphics.drawImage(img, 0, 0, null); } } 方法。更改图像后,您只需让Swing使用#testChange()调用再次绘制您的组件。

#repaint()

最后一点说明:除了事件调度线程(EDT)之外,你真的不应该更改Swing对象。创建第一个窗口时,但在设置可见之前,通常允许例外。

public class Pixel extends Component {

    public void testChange() {
        int rgb = new Color(0xFF8876).getRGB());  // Cached, for efficiency.

        for(int i = 50; i < 80; i++) {
            for(int  j = 80; j < 120; j++) {
                img.setRGB(i, j, rgb);
            }
            for(int  j = 460; j < 493; j++) {
                img.setRGB(i, j, rgb);
            }
        }

        repaint(); // <<-- Ask Swing to repaint the component.
    }
}

相反,您可以像这样重构代码:

public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
    frame.setVisible(true);             // <<-- Window becomes visible here
    pixel = new Pixel(1600, 900);
    frame.getContentPane().add(pixel);  // <<-- DANGEROUS!!
}

更好的是,使用public static void main(String[] args) { JFrame frame = new JFrame(); frame.setExtendedState(JFrame.MAXIMIZED_BOTH); pixel = new Pixel(1600, 900); frame.getContentPane().add(pixel); // <<-- Safe - window not visible yet. frame.setVisible(true); // <<-- Window becomes visible here } 实际切换到EDT:

SwingUtilities.invokeLater(...)

哦,使用Java8,您可以摆脱大部分public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { JFrame frame = new JFrame(); frame.setExtendedState(JFrame.MAXIMIZED_BOTH); frame.setVisible(true); // <<-- Window becomes visible here pixel = new Pixel(1600, 900); frame.getContentPane().add(pixel); // <<-- Safe - running on EDT. pixel.testChange(); // <<-- Also safe - running on EDT } }); } 样板代码:

Runnable

答案 1 :(得分:0)

testChange方法结束时(或在调用它之后),您应该在invalidate对象上调用Pixel,这是一个通知组件重绘的信号,因为它已被改变。

同时检查this SO question