在 ActionListener 外部访问 JButton ActionListener 内部所做的更改

Accessing changes made inside JButton ActionListener outside the ActionListener

我会稍微解释一下我的代码:

我有一个包含项目列表的 JComboBox 当按下 JButton "Select" 时,它会注册 JComboBox 中最后一个选定项目的最后一个索引。

现在我需要在主目录中访问这个索引。

这是我的代码:

public static final JComboBox c = new JComboBox();

private static final JButton btnNewButton = new JButton("Select");

而 JButton ActionListener 是:

btnNewButton.addActionListener(新的 ActionListener() {

  public void actionPerformed(ActionEvent e)
  {
       ind = c.getSelectedIndex();
        frame.setVisible(false);
    }
  });      

所以按下按钮后,框架关闭

但是现在当我尝试通过

访问 main 中的这个 ind 时
public static void main(String[] args) {
System.out.println(ind);}

我得到一个 return 值 ind = 0

我理解这是因为已经初始化为0了

static ind = 0 

但是我如何在 JButton ActionListener 之外访问这个索引?

我需要在我的代码中进一步使用这个索引。

编辑

这是我的 MCVE

import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.SpringLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.UIManager;

public class MinimalExProgram
{
private static String[] description = { "One", "Two", "Three"};

static int ind;

public static final JComboBox c = new JComboBox(description);

private static final JButton btnNewButton = new JButton("Select");


public static void main(String[] args) {

JFrame frame = new JFrame();
frame.getContentPane().setForeground(UIManager.getColor("ComboBox.disabledBackground"));
frame.getContentPane().setBackground(UIManager.getColor("EditorPane.disabledBackground"));
SpringLayout springLayout = new SpringLayout();
springLayout.putConstraint(SpringLayout.NORTH, btnNewButton, 5, SpringLayout.NORTH, frame.getContentPane());
springLayout.putConstraint(SpringLayout.EAST, c, -6, SpringLayout.WEST, btnNewButton);
springLayout.putConstraint(SpringLayout.EAST, btnNewButton, -10, SpringLayout.EAST, frame.getContentPane());
springLayout.putConstraint(SpringLayout.WEST, c, 6, SpringLayout.WEST, frame.getContentPane());
springLayout.putConstraint(SpringLayout.NORTH, c, 6, SpringLayout.NORTH, frame.getContentPane());
frame.getContentPane().setLayout(springLayout);
frame.setSize(500, 150);
frame.setLocation(400, 200);
frame.setResizable(false);
c.setBackground(UIManager.getColor("ComboBox.disabledBackground"));


btnNewButton.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e)
{
      System.out.print("What I want:");
      ind = c.getSelectedIndex();
      System.out.println(ind);
        frame.setVisible(false);
}
});      

frame.getContentPane().add(c);
btnNewButton.setForeground(UIManager.getColor("ComboBox.buttonDarkShadow"));
btnNewButton.setBackground(UIManager.getColor("EditorPane.disabledBackground    "));

frame.getContentPane().add(btnNewButton);
frame.setVisible(true);
System.out.print("What I get: ");
System.out.println(ind);
}
}

我需要像之前提到的那样访问 main 里面的 ind 在这里,当我打印出 ind 时,无论我在组合框中做出什么选择,我都会得到零。

好吧,我猜是因为你还没有向我们展示足够的信息来做更多的事情,但我假设

  • 您正在显示第二个 window 作为主要 window
  • 的对话
  • 第二个 window 是一个 JFrame 并包含您的 JComboBox 和按钮
  • 你要让它在按下按钮时不可见,
  • 您尝试从组合框中获取信息,但它始终为 0
  • 这可能是因为您在用户有机会与第二个window互动之前获得了信息。

如果是这样,解决方案是使第二个window成为模态对话框window,例如模态 JDialog 而不是 JFrame。这样,调用代码将准确知道第二个 window 何时不再可见,因为调用代码的代码流将被阻塞,直到第二个 window 不再可见。


编辑

概念验证:更改您的代码:

  final JFrame frame = new JFrame();

至:

  // rename frame variable to dialog for clarity
  final JDialog dialog = new JDialog();
  dialog.setModalityType(ModalityType.APPLICATION_MODAL);

而且有效。


但是,我还是要去掉不必要的静态变量,不要在 main 方法中做太多代码。例如,...

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;

@SuppressWarnings("serial")
public class MinimalExProgram3 extends JPanel {
   private static void createAndShowGui() {
      MainPanel mainPanel = new MainPanel();

      JFrame frame = new JFrame("MinimalExProgram3");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

@SuppressWarnings("serial")
class MainPanel extends JPanel {
   private static final int PREF_W = 400;
   private static final int PREF_H = PREF_W;
   private JTextField field = new JTextField(8);
   private ComboPanel comboPanel = new ComboPanel();
   JDialog dialog = null;

   public MainPanel() {
      field.setFocusable(false);

      add(field);
      add(new JButton(new ShowComboAction("Show Combo")));
   }

   @Override // make it bigger
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   private class ShowComboAction extends AbstractAction {
      public ShowComboAction(String name) {
         super(name);
         int mnemonic = (int) name.charAt(0);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         Window mainWin = SwingUtilities.getWindowAncestor(MainPanel.this);
         if (dialog == null) {
            dialog = new JDialog(mainWin, "Dialog", ModalityType.APPLICATION_MODAL);
            dialog.add(comboPanel);
            dialog.pack();
            dialog.setLocationRelativeTo(null);
         }

         dialog.setVisible(true);

         // code called here after dialog no longer visible
         String text = comboPanel.getText();
         field.setText(text);
      }
   }
}

@SuppressWarnings("serial")
class ComboPanel extends JPanel {
   private static final String[] DESCRIPTION = { "One", "Two", "Three" };
   private int ind;
   private JComboBox<String> combo = new JComboBox<>(DESCRIPTION);
   private String text;
   private SelectionAction selectionAction = new SelectionAction("Select");
   private JButton selectionButton = new JButton(selectionAction);

   public ComboPanel() {
      add(combo);
      add(selectionButton);

      combo.setAction(selectionAction);
   }

   public int getInd() {
      return ind;
   }

   public String getText() {
      return text;
   }

   private class SelectionAction extends AbstractAction {
      public SelectionAction(String name) {
         super(name);
         int mnemonic = (int) name.charAt(0);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         ind = combo.getSelectedIndex();
         if (ind >= 0) {
            text = combo.getSelectedItem().toString();
         }
         Window win = SwingUtilities.getWindowAncestor(ComboPanel.this);
         win.dispose();
      }
   }
}