2015-06-29 2 views
1

У меня есть метод, как так, задаваемый массив из JButton и возвращает их текст всякий раз, когда они прижаты:Java ActionListener Return Переменная для метода, который содержит ActionListener

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

Но, конечно же, этот код будет не компилировать, потому что я возвращаю переменную в нулевой метод. Итак, как бы мне было 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); 
    } 
} 
+1

Вы думаете о линейном/процедурном режиме, это не то, как работают пользовательские интерфейсы, пользовательские интерфейсы управляются событиями, что означает, что что-то происходит (в какой-то момент времени), и вы отвечаете на него. Нет смысла возвращать значение обратно к методу foo, потому что код завершит выполнение задолго до того, как уведомление ActionListener будет уведомлено. Лучше, чтобы слушатель выполнил сами необходимые действия. – MadProgrammer

ответ

4

Это утверждение не имеет смысла:

Итак, как бы я i.getText() вернуть его Вывести также метод foo()? не

Метод foo() больше не работает после того, как ActionListeners были добавлены кнопки, и, безусловно, закончилось к тому времени, пользователь нажимает на кнопку, в соответствии с правилами событийного программирования. Вместо этого, хотя вы могли бы заставить 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); 
    } 
} 
+0

Вот мой код для моей программы: http://pastebin.com/fPudzGTi –

+0

@LucasBaizer: это должно быть опубликовано с вашим вопросом. Я позволил вам сделать это за вас. –

+0

@LucasBaizer: см. Править, чтобы ответить с кодом. –

0

Почему так сложно? независимо от того, что должно делать 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; 
} 
+0

Извините, но что такое 'synchronized'? –

+0

Используется для блокировки блока кода с указанным объектом. Это предотвращает одновременный доступ нескольких потоков к одному и тому же фрагменту кода на одном и том же объекте.Это просто приготовленная версия. Это более подробно описано здесь: http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html (для синхронизированных методов) и здесь: http://docs.oracle.com/javase/tutorial/essential /concurrency/locksync.html (для синхронизированных операторов) – Paul

+0

Вы протестировали это в текущей программе? Похоже, что он рискует заблокировать весь графический интерфейс, если он сделан не очень тщательно и в основном в фоновом потоке. –