需要帮助访问内部 class for 循环中的变量

need help accessing variable inside inner class for loop

我在访问内部变量 int i 时遇到问题 class 代码:

public class OnColumnSelectPanel {

JFrame jFrame;
JPanel mainJPanel;
//JPanel jPanel1;
//JTextField jTextField;
//JButton jButton;
//JComboBox jComboBox [];
MigLayout layout;
MigLayout frameLayout;
//column names
ColumnNames cn = new ColumnNames();
List<String> listedColumnNames = cn.getColumnNames();
String columnNames[] = listedColumnNames.toArray(new String[0]);

public OnColumnSelectPanel(int n) {

    //jPanel1 = new JPanel();
    jFrame = new JFrame("Create Structure of Columns");
    // mainJPanel = new JPanel();
    layout = new MigLayout("flowy", "[center]rel[grow]", "[]10[]");
    frameLayout = new MigLayout("flowx", "[center]rel[grow]", "[]10[]");
    //mainJPanel.setLayout(new BoxLayout(mainJPanel, BoxLayout.X_AXIS));
    //MigLayout mainJPanelLayout = new MigLayout("flowy", "[]rel[grow]", "[]5[]");

    // declare & initialize array
    JPanel jPanel[] = new JPanel[n];
    JComboBox jComboBox[] = new JComboBox[n];
    JButton jButton[] = new JButton[n];
    final int num = 0;
    for (int i = 0; i < n; i++) {

        //assign array
        jComboBox[i] = new JComboBox(columnNames);
        jButton[i] = new JButton("add Sub Heading");
        jPanel[i] = new JPanel();
        System.out.println("Loop number: " + i);

        jButton[i].addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {

                for (int j = 0; j < n; j++) {
                    if (j <= n) {
                        jComboBox[j] = new JComboBox(columnNames);
                        jPanel[j].add(jComboBox[j]);
                        jFrame.revalidate();
                    } else {
                        JOptionPane.showMessageDialog(null, "You have exceeded your limit");
                    }
                }

            }
        });
        //set layout
        jPanel[i].setLayout(layout);
        //jPanel[i].setPreferredSize(new Dimension(50, 400));
        //mainJPanel.setLayout(mainJPanelLayout);
        jFrame.setLayout(frameLayout);
        System.out.println(" height " + jPanel[i].getHeight());
        jPanel[i].add(jComboBox[i], new CC().newline());
        //jPanel.add(jTextField);
        jPanel[i].add(jButton[i]);
        //mainJPanel.add(jPanel[i], "spany");
        jPanel[i].repaint();

        jFrame.add(jPanel[i]);
        jFrame.pack();
        jPanel[i].revalidate();
        jFrame.revalidate();
        //mainJPanel.revalidate();
        //jFrame.revalidate();

    }
    //mainJPanel.setSize(600, 400);

    //jFrame.add(jPanel1);
    jFrame.setVisible(true);
    jFrame.setSize(600, 400);
    jFrame.setAlwaysOnTop(true);
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}

Output Frame

正如您所看到的输出图像。这里的问题是当我点击添加副标题按钮时,组合框被添加到每个 jpanel。这是因为我不能将值 i 传递给内部 class。 知道可能的解决方案会很有趣。

仅供参考,我正在使用 Mig 布局。

提前致谢。

只能从匿名 classes 访问 effectively final 变量。 i 被循环修改,所以它不是有效的 final。

解决方法如下所示:

for (int i = 0; i < n; i++) {
   ...

  final int effectivelyFinal = i;
  jButton[i].addActionListener(new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent ae) {
      ...
      // use effectivelyFinal instead of i
    });
}

但正如其他人所建议的那样,将匿名 class 提取到真实 class 并使用构造函数传递所有必需参数会更好。这可能看起来像这样:

class MyListener implements ActionListener {

    private final int index;

    // add more fields for other required parameters

    public MyListener(int index) {
        this.index = index;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
      // use index    
    }
}

用法:

jButton[i].addActionListener(new MyListener(i));