С Nimbus laf моя панель JOptionPane не получает фокус при вызове из выпадающего списка ItemEvent

#java #swing #focus #joptionpane #nimbus

#java #swing #фокус #панель joptionpane #nimbus

Вопрос:

надеюсь, вы сможете помочь.

Я надеюсь, что это не просто ошибка, и мы сможем ее решить.

В настоящее время у меня есть Java-программа с JComboBox . Когда пользователь изменяет выбранный элемент в поле со списком, JOptionPane появляется сообщение, позволяющее пользователю подтвердить изменение.

Когда в поле со списком сделан новый выбор, JOptionPane отображается так, как требуется, но вы должны щелкнуть по нему дважды, чтобы использовать его. То есть щелкните по ней один раз, чтобы получить фокус, а затем нажмите кнопку, которую вы хотите использовать. Другой метод заключается в том, чтобы щелкнуть в пределах графического интерфейса программы (за панелью опций), а затем нажать кнопку.

Никаких исключений не возникает, и программа функционирует как обычно после нажатия кнопок.

Эта функциональность выполняется только с помощью Nimbus LookAndFeel, а не с помощью встроенного macos laf (построен на Mac, не тестировался в Windows), но мне нужно использовать nimbus по другим причинам.

Я просматривал отслеживание проблем Nimbus, но еще не нашел ошибку.

У меня есть JButton, который вызывает ТОТ ЖЕ код (ie JOptionPane.showConfirmDialog(... ), и это работает отлично, просто когда он вызывается из действия поля со списком.

Действительно надеюсь, что вы сможете помочь! Заранее приветствую!

 import javax.swing.UIManager.*;
import javax.swing.*;

public class TestJavaProblem extends JFrame {
    JComboBox jComboBox1;

    public TestJavaProblem() {
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        initComponents();
    }

    private void initComponents() {
        jComboBox1 = new JComboBox();

        //give it some values
        jComboBox1.setModel(new DefaultComboBoxModel(new String[] { "1", "2"}));

        //add listener
        jComboBox1.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) { fireTask(evt);}
        });

        this.add(jComboBox1);
        pack();
    }

    private void fireTask(java.awt.event.ItemEvent evt) {
        if (evt.getStateChange() == 1) { //so dialog fires only once
            int i = JOptionPane.showConfirmDialog(jComboBox1, "Message Text", "Title", JOptionPane.OK_CANCEL_OPTION);
            System.out.println("Result:"   i);
        }
    }

    public static void main(String args[]) {
        try {
            for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                break;
                }
            }
        } catch (Exception e) {/*no nimbus*/}

        new TestJavaProblem().setVisible(true);
    }
}
  

Комментарии:

1. не могли бы вы, пожалуйста, опубликовать код (в sscce.org формы), которые вызвали эту проблему, потому что есть несколько способов, как это сделать правильно

2. добавлен код. Приветствую, приятель. На самом деле мне кажется, что первый щелчок перемещает фокус из всплывающего меню, которое все еще открыто. Другие l-a-f закрывают свое всплывающее меню почти сразу.

Ответ №1:

не используйте магическое число,

 if (evt.getStateChange() == 1) { //so dialog fires only once
  

или

 int i = JOptionPane.showConfirmDialog(jComboBox1,
  

вот код обходного пути, но, похоже, требуется для MetalLookAndFeel, Substance в ОС Windows

 import javax.swing.UIManager.*;
import javax.swing.*;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;

public class TestJavaProblem extends JFrame {

    private static final long serialVersionUID = 1L;
    private JComboBox jComboBox1;
    private boolean boloComboBox = false;

    public TestJavaProblem() {
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        initComponents();
    }

    private void initComponents() {
        jComboBox1 = new JComboBox();
        jComboBox1.setModel(new DefaultComboBoxModel(new String[]{"1", "2"}));
        jComboBox1.addItemListener(new java.awt.event.ItemListener() {

            @Override
            public void itemStateChanged(final java.awt.event.ItemEvent evt) {
                if (jComboBox1.isPopupVisible()) {
                    jComboBox1.setPopupVisible(false);
                    SwingUtilities.invokeLater(new Runnable() {

                        @Override
                        public void run() {
                            fireTask(evt);
                        }
                    });
                }
            }
        });
        jComboBox1.addPopupMenuListener(new PopupMenuListener() {

            @Override
            public void popupMenuCanceled(PopupMenuEvent e) {
                System.out.println(e.getSource());
            }

            @Override
            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                System.out.println(e.getSource());
            }

            @Override
            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
                System.out.println(e.getSource());
            }
        });
        add(jComboBox1);
        pack();
    }

    private void fireTask(java.awt.event.ItemEvent evt) {
        if (evt.getStateChange() == 2) {
            int i = JOptionPane.showConfirmDialog(jComboBox1, 
                "Message Text", "Title", JOptionPane.OK_CANCEL_OPTION);
            System.out.println("Result:"   i);
        }
    }

    public static void main(String args[]) {
        try {
            for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (Exception e) {
        }
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestJavaProblem().setVisible(true);
            }
        });
    }
}
  

Комментарии:

1. Твое здоровье, приятель, только этот код все исправил! if (jComboBox1.isPopupVisible()){jComboBox1.setPopupVisible(false);} Что вы имели в виду, говоря о неиспользовании int i = JOptionPane.showConfirmDialog... ?

2. int i JOptionPane.YES_OPTION , if (evt.getStateChange() == 1) есть SELECTED , рад помочь 1