9

前段时间我用Java写了一个小图像查看器/处理程序,一个迷你Photoshop,如果你愿意的话。

我希望有一个下拉菜单,我可以在其中选择我打开的哪一张图像将是“在桌子上”,即。显示和应用的方法。我希望图像的名称是菜单中显示的 JMenuItem 的名称。我还希望在添加新图像时出现一个新按钮。

我想了一段时间,最后产生了这个解决方案,一个新的类,在添加图像时处理新按钮的创建。代码如下:

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


public class ImageList{

    private ArrayList<JMenuItem> list;
    private ImageHandler main;
    private ImageLevel img;

    public ImageList() {}

    public void setHandler(ImageHandler hand) {
        main = hand;
        img = main.getImg1();
    }

    public void add(Buffer addi) {
        final String added = addi.getName();
        JMenuItem uusi = new JMenuItem(added);

        main.getMenu5().add(uusi);
        uusi.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                img.setBuffer(added);
                main.getScr().updateUI();
            }
        });
   }
}

这可以正常工作。对于这个网站,我将原来的芬兰名字翻译成英文,想知道为什么我最初用芬兰语写它们……我不擅长命名。

方法 add 应该在程序运行时被多次调用。

我真正无法理解的是接口ActionListener的内部类实现,即它的编译和它是如何工作的。

如果我的界面上有两个按钮,我希望它们做不同的事情,我需要两个内部类,每个类一个,每个都有自己的接口 ActionListener 的内部实现。但是在我的代码中,有一个类似乎可以完成许多工作,一个为它编译的 .class 文件,但最终结果就像有很多一样。

有人可以就这个问题教育我吗?这里的代码是一类,新按钮是它的实例吗?他们是新课程吗?每个新按钮都应该有一个新的 .class 文件吗?ETC...

4

6 回答 6

5

通常,内部类在只调用一次的代码中实例化(例如,当您在构造函数中扩展JPanel并添加ActionListenersJButtons 时)。在这里,您在多次调用的方法中实例化一个内部类(如果我正确理解您的描述)。每次调用add(),都会创建一个内部类的新实例。与命名类一样,只有一个类,但可能有很多实例。

于 2012-11-16T16:10:15.613 回答
3

在这段代码中:

public void add(Buffer addi) {
    . . .
    uusi.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            img.setBuffer(added);
            main.getScr().updateUI();
        }
    });
}

new ActionListener() {...}构造是一个匿名内部类。它的行为就好像它被单独声明为常规内部类一样。主要区别在于名称是由编译器自动生成的。它相当于:

private class Anonymous implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        img.setBuffer(added);
        main.getScr().updateUI();
    }
}

public void add(Buffer addi) {
    . . .
    uusi.addActionListener(new Anonymous());
}

每次执行addActionListener代码时,它都会创建此类的一个新实例。

匿名内部类还有一些其他限制,这些限制是匿名的后果。例如,如果他们声明了字段,则这些字段只能从类中访问(不使用反射)。

于 2012-11-16T16:15:57.453 回答
0

您正在为菜单项操作侦听器创建新的匿名类。

基本上,你的代码

menuItem.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent e) {
      img.setBuffer(added);
      main.getScr().updateUI();
  }
});

为 ActionListener 定义一个新的类实现

于 2012-11-16T16:10:34.287 回答
0
  • main.getScr().updateUI();不是更新已经可见的 Swing 对象的正确方法,此方法对外观敏感

  • 使用JPanel(不要忘记覆盖PreferredSize否则返回Dimension (0, 0))与paintComponent

  • 如果你想删除然后添加一个新的容器来保存 Image 然后你必须调用revalidate()repaint()


  • 与图像一起使用JList,而不是JMenuItem

  • 添加ListSelectionListenerJList,然后您可以在图像之间切换


  • 如果没有在holds中添加任何其他JComponent(s),则与ContainerImageJLabelIcon / ImageIcon
于 2012-11-16T16:13:58.833 回答
0

您正在做的是创建接口 ActionListener 的匿名实现。每个匿名实现都有自己的类文件(称为 ImageList$1.class、ImageList$2.class 等)。

你也可以这样做,得到类似的结果:

class MyActionListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      img.setBuffer(added);
      main.getScr().updateUI();
    }
};

menuItem.addActionListener(new MyActionListener());
于 2012-11-16T16:17:11.643 回答
0

类中的内部类被编译到“父”.class 文件中。您可以在 1 个类中拥有多个内部类。(编译后生成 1.class 文件)每次对内部类(运行时)的“调用”都将创建该内部类的一个对象(与“规范类”相同)。但它不会改变你的 .class 文件。

因此,当添加 3 个相同类型的按钮时,每次都会创建一个内部类的新对象。与按钮本身的原理相同。

于 2012-11-16T16:24:48.390 回答