2016-10-09 2 views
4

Я заметил, что весь метод JOptionPane «вмешивается» в ActionListeners. Мне нужно, чтобы ActionListener оставался активным после открытия JOptionPane.Избегайте вмешательства JOptionPane с прослушивающими действиями

Например:

У меня есть JButton, зарегистрировать мышь нажата и нарисовать красную кнопку. После освобождения я рисую его синим.

  • Если я просто нажмите это, кнопка станет синим. Ok
  • Если я держу его, кнопка останется красной. Ok
  • Если я нажмите его и установить его открытым диалог JOptionPane, он остается красным, даже если я выпустил мышь. Не Ok

я не смог найти никакой документации по этому конкретному поведению, может кто-то мне точку в правильном направлении?

Мне действительно нужно использовать JOptionPane.

ответ

4

Один из вариантов - очередь на вызов, чтобы открыть JOptionPane в очереди событий Swing. Это немного замедлит открытие модальной JOptionPane, позволяя выполнять другие действия с кнопками.

Другой вариант - извлечь JDialog из JOptionPane и вызвать его в немодальным способом.

Например:

import java.awt.Color; 
import java.awt.Component; 
import java.awt.Dialog.ModalityType; 
import java.awt.Dimension; 
import java.awt.event.ActionEvent; 
import javax.swing.*; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

public class TestOptionPane extends JPanel { 
    private static final Color FOREGROUND = Color.RED; 
    private static final Color PRESSED_FG = Color.BLUE; 
    private JButton button1 = new JButton(new Button1Action()); 
    private JButton button2 = new JButton(new Button1Action()); 

    public TestOptionPane() { 
     setPreferredSize(new Dimension(600, 450)); 
     button1.getModel().addChangeListener(new ButtonModelListener(button1)); 
     button1.setForeground(FOREGROUND); 
     add(button1); 
     button2.getModel().addChangeListener(new ButtonModelListener(button2)); 
     button2.setForeground(FOREGROUND); 
     add(button2); 
    } 

    private class Button1Action extends AbstractAction { 
     public Button1Action() { 
      super("Queue JOptionPane on Swing event thread"); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      SwingUtilities.invokeLater(() -> { 
       JOptionPane.showMessageDialog(TestOptionPane.this, "hello"); 
      }); 
     } 
    } 

    private class Button2Action extends AbstractAction { 
     public Button2Action() { 
      super("Show non-modal JOptionPane"); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      SwingUtilities.invokeLater(() -> { 
       Component parentComponent = TestOptionPane.this; 
       JOptionPane optionPane = new JOptionPane("Hello", JOptionPane.PLAIN_MESSAGE); 
       JDialog dialog = optionPane.createDialog(parentComponent, "Fubars Rule!"); 
       dialog.setModalityType(ModalityType.MODELESS); 
       dialog.setLocationRelativeTo(parentComponent); 
       dialog.setVisible(true); 
      }); 
     } 
    } 

    private class ButtonModelListener implements ChangeListener { 
     private JButton button; 

     public ButtonModelListener(JButton button) { 
      this.button = button; 
     } 

     @Override 
     public void stateChanged(ChangeEvent e) { 
      ButtonModel model = (ButtonModel) e.getSource(); 
      if (model.isPressed()) { 
       button.setForeground(PRESSED_FG); 
      } else { 
       button.setForeground(FOREGROUND); 
      } 
     } 

    } 

    private static void createAndShowGui() { 
     JFrame frame = new JFrame("TestOptionPane"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new TestOptionPane()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
} 
+0

Я не знаю, если я больше впечатлен тем, насколько хорошо этот ответ или как быстро вы написали. Отлично работает, спасибо. Один вопрос: при создании графического интерфейса вы вызываете .invokeLater(), почему? Нужно ли мне ? Потому что просто вызывает его (.invokeLater), чтобы открыть OptionPane. –

+0

@LoryA: отредактирован ответ, чтобы показать ** оба метода **, включая первый, где я ставил очередь на панель joption в потоке событий, а второй, где я показываю optionpane как немодальный диалог. –

+2

@LoryA: Я стараюсь создать графический интерфейс в потоке событий Swing, чтобы предотвратить странные, непредсказуемые ошибки потоковой передачи. Иногда они происходят, и я их видел. –

Смежные вопросы