有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

swing Java ActionListener将变量返回到包含ActionListener的方法

我有一个这样的方法,它被赋予一个JButton数组,并在按下它们时返回它们的文本:

public static String foo(JButton[] buttons) {
    for (JButton i : buttons) {
        i.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                return i.getText();
            }
        });
    }
}

但是,当然,这段代码不会编译,因为我正在将一个变量返回给null方法。那么,如何让i.getText()也通过foo()方法返回其输出呢


编辑,所有代码:

import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class JCustomFrame {
    public static void showMessageFrame(String title, String message,
            String[] textOnButtons, ImageIcon icon) {
        final JFrame frame = new JFrame();
        JPanel panel = new JPanel();

        panel.setLayout(new GridBagLayout());
        panel.setBackground(Color.WHITE);

        GridBagConstraints c = new GridBagConstraints();
        c.anchor = GridBagConstraints.EAST;
        c.fill = GridBagConstraints.RELATIVE;
        c.gridx = 0;
        c.gridy = 0;
        c.insets = new Insets(5, 5, 5, 5);

        JLabel messageLabel = new JLabel(message);
        messageLabel.setFont(messageLabel.getFont().deriveFont(16.0f));

        panel.add(messageLabel, c);

        c.gridy = 1;
        c.gridx = 0;
        for (int i = 0; i < textOnButtons.length; i++) {
            JButton button = new JButton(textOnButtons[i]);
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    return ((JButton) arg0.getSource()).getText();
                    frame.dispose();
                }
            });
            button.setFont(button.getFont().deriveFont(16.0f));
            panel.add(button, c);
            c.gridx++;
        }

        if (icon == null) {
            frame.setIconImage(new BufferedImage(1, 1,
                    BufferedImage.TYPE_INT_ARGB_PRE));
        } else {
            frame.setIconImage(icon.getImage());
        }
        frame.add(panel);
        frame.setTitle(title);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.pack();
    }

    public static void main(String[] args) {
        JCustomFrame.showMessageFrame("Test Frame",
                "Do you really want to do this?", new String[] { "Hell No",
                        "Sure, Why Not" }, null);
    }
}

共 (2) 个答案

  1. # 1 楼答案

    这种说法毫无意义:

    So, how would I have i.getText() return its output too the foo() method?

    在ActionListeners被添加到按钮之后,方法foo()不再运行,并且根据事件驱动编程的规则,当用户按下按钮时,方法肯定会结束。相反,尽管你可以让ActionListeners改变一个类的状态,任何一个类,这就足够了。例如:

    class FooClass {
        private String text;
    
        public void foo(JButton[] buttons) {
            for (JButton i : buttons) {
                i.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        text = e.getActionCommand(); 
                    }
                });
            }
        }
    }
    

    如果您需要更详细的可行解决方案,请告诉我们您的实际计划和具体问题的更多细节

    现在,如果您确实需要一个方法来返回按下的按钮的值,那么您需要通过通知机制和回调方法来实现这一点,但是解决方案的细节将取决于实际问题和代码的细节


    编辑

    你在试图模仿JOptionPane。您的解决方案是要么使用JOptionPane,向其中添加一个JPanel,要么使用模态JDialog创建自己的:

    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Dialog.ModalityType;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.Insets;
    import java.awt.Window;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.image.BufferedImage;
    import javax.swing.ImageIcon;
    import javax.swing.JButton;
    import javax.swing.JDialog;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class JCustomFrame2 {
    
       public static String showMessageFrame(Window owner, String title,
             String message, String[] textOnButtons, ImageIcon icon) {
          final JDialog dialog = new JDialog(owner);
          StringBuilder sb = new StringBuilder();
    
          // make it application modal!
          dialog.setModalityType(ModalityType.APPLICATION_MODAL);
          JPanel panel = new JPanel();
    
          panel.setLayout(new GridBagLayout());
          panel.setBackground(Color.WHITE);
    
          GridBagConstraints c = new GridBagConstraints();
          c.anchor = GridBagConstraints.EAST;
          c.fill = GridBagConstraints.RELATIVE;
          c.gridx = 0;
          c.gridy = 0;
          c.insets = new Insets(5, 5, 5, 5);
    
          JLabel messageLabel = new JLabel(message);
          messageLabel.setFont(messageLabel.getFont().deriveFont(16.0f));
    
          panel.add(messageLabel, c);
    
          c.gridy = 1;
          c.gridx = 0;
          for (int i = 0; i < textOnButtons.length; i++) {
             JButton button = new JButton(textOnButtons[i]);
             button.addActionListener(new ButtonListener(sb));
             button.setFont(button.getFont().deriveFont(16.0f));
             panel.add(button, c);
             c.gridx++;
          }
    
          if (icon == null) {
             dialog.setIconImage(new BufferedImage(1, 1,
                   BufferedImage.TYPE_INT_ARGB_PRE));
          } else {
             dialog.setIconImage(icon.getImage());
          }
          dialog.add(panel);
          dialog.setTitle(title);
          dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
          dialog.pack();
          dialog.setVisible(true);
    
          return sb.toString();
       }
    
       private static class ButtonListener implements ActionListener {
          private StringBuilder sb;
    
          public ButtonListener(StringBuilder sb) {
             this.sb = sb;
          }
    
    
          @Override
          public void actionPerformed(ActionEvent e) {
             sb.append(e.getActionCommand());
             Component component = (Component) e.getSource();
             Window win = SwingUtilities.getWindowAncestor(component);
             if (win != null) {
                win.dispose();
             }
          }
       }
    
       public static String showMessageFrame(String title,
             String message, String[] textOnButtons, ImageIcon icon) {
          return showMessageFrame(null, title, message, textOnButtons, icon);
       }
    
    
       public static void main(String[] args) {
          String result = JCustomFrame2.showMessageFrame("Test Frame",
                "Do you really want to do this?", new String[] { "Hell No",
                      "Sure, Why Not" }, null);
    
          System.out.println(result);
       }
    }
    
  2. # 2 楼答案

    为什么这么复杂?无论foo应该做什么,只需从ActionListener内部以按钮的名称作为参数调用另一个方法就会容易得多。或者,如果你真的想达到这样的效果,让线程等待用户按下按钮

    public void doSomething(){
        JButton[] someButtons = ...;//whereever you create the buttons
    
        System.out.println(foo(someButtons));
    }
    
    public static String foo(JButton[] buttons){
        final String someString = "";
    
        final Object lock = new Object();
    
        for(JButton b : buttons){
            b.addActionListener(e -> {
                 someString.concat(b.getName());
    
                 synchronized(lock){
                     lock.notifyAll();
                 }
            });
        }
    
        synchronized(lock){
            try{
                lock.wait();
            }catch(InterruptedException e){}
        }
    
        return someString;
    }