处理JDialog和JToggleButton

时间:2016-04-16 12:24:18

标签: java swing jdialog jtogglebutton focuslistener

我正在尝试构建JToggleButton,在按下JDialog时显示JList(包含JToggleButton)。再次按下JDialog时,JToggleButton会消失,或者如果用户点击或框架中的其他位置(我通过FocusListener上的JList进行了模拟)当焦点丢失时)。

按顺序按下按钮将正确显示和隐藏JDialog

然而,问题是当JDialog可见时,我点击框架上的其他位置时,JDialog会在焦点丢失时正确消失。但是,JToggleButton的状态仍未正确设置为已选中。这意味着现在点击JToggleButton将不会显示JDialog,因为JToggleButton的状态现在已不同步。相反,我需要按两次JToggleButton才能再次显示JDialog。我的代码示例演示了这个问题。

我似乎无法将JList的失去焦点与JToggleButton的状态同步。这似乎是一个简单的问题,但我很难找到解决方案。有人可以帮忙吗?感谢。

请参阅下面的代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;

public class MultiComboBox extends JToggleButton
{
    public MultiComboBox(JFrame frame, String buttonText)
    {
        super(buttonText);

        JDialog dialog = new JDialog(frame, false);
        dialog.setLayout(new BorderLayout());

        Object[] items = new Object[] { "one", "two", "three" };
        JList list = new JList(items);
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        JScrollPane listScrollPane = new JScrollPane(list,
            JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
            JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        listScrollPane.setPreferredSize(list.getPreferredSize());

        dialog.add(listScrollPane, BorderLayout.CENTER);
        dialog.pack();

        addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                final JToggleButton button = (JToggleButton) e.getSource();
                System.out.println("button clicked: " + button.isSelected());
                if (button.isSelected())
                {
                    Point p = button.getLocation();
                    p.setLocation(p.getX() + 300, p.getY());
                    SwingUtilities.convertPointToScreen(p, button);
                    dialog.setLocation(p);
                    dialog.setVisible(true);
                }
                else
                    dialog.setVisible(false);
            }
        });

        list.addFocusListener(new FocusListener()
        {
            @Override
            public void focusGained(FocusEvent e)
            {
            }

            @Override
            public void focusLost(FocusEvent e)
            {
                System.out.println("list focusLost, dialog: " + dialog.isVisible());
                dialog.setVisible(false);
            }
        });
    }

    public static void main(String[] args)
    {
        JFrame frame = new JFrame("Test");
        frame.setPreferredSize(new Dimension(300, 300));
        frame.setLayout(new BorderLayout());

        MultiComboBox mcb = new MultiComboBox(frame, "Toggle");

        JPanel buttonPanel = new JPanel(new BorderLayout());
        buttonPanel.setPreferredSize(new Dimension(80, 30));
        buttonPanel.add(mcb, BorderLayout.CENTER);

        JPanel blankPanel = new JPanel(new BorderLayout());
        frame.add(blankPanel, BorderLayout.CENTER);

        frame.add(buttonPanel, BorderLayout.PAGE_START);
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }
}

1 个答案:

答案 0 :(得分:1)

建议:

  • 不要将ActionListener添加到JToggleButton
  • 但是添加一个ItemListener。这将响应切换选择状态的变化
  • 在此侦听器内,更改对话框的可见状态。
  • 在您的FocusListener中,不要更改对话框的可见状态,而是更改切换选择状态。
  • 使用添加到JDialog本身的WindowFocusListener,如果失去焦点,则会收到通知。这样,侦听器代码可以在对话框组件的代码之外,这是一个更清晰的OOP解决方案。

例如:

import javax.swing.*;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

public class MultiComboBox2 extends JToggleButton {
    public MultiComboBox2(JFrame frame, String buttonText) {
        super(buttonText);

        JDialog dialog = new JDialog(frame, false);
        dialog.setLayout(new BorderLayout());

        Object[] items = new Object[] { "one", "two", "three" };
        JList list = new JList(items);
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        JScrollPane listScrollPane = new JScrollPane(list, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        listScrollPane.setPreferredSize(list.getPreferredSize());

        dialog.add(listScrollPane, BorderLayout.CENTER);
        dialog.pack();

        addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                final JToggleButton button = (JToggleButton) e.getSource();
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    Point p = button.getLocation();
                    p.setLocation(p.getX() + 300, p.getY());
                    SwingUtilities.convertPointToScreen(p, button);
                    dialog.setLocation(p);
                    dialog.setVisible(true);
                } else {
                    dialog.setVisible(false);
                }
            }
        });
        // addActionListener(new ActionListener() {
        // @Override
        // public void actionPerformed(ActionEvent e) {
        // final JToggleButton button = (JToggleButton) e.getSource();
        // System.out.println("button clicked: " + button.isSelected());
        // if (button.isSelected()) {
        // Point p = button.getLocation();
        // p.setLocation(p.getX() + 300, p.getY());
        // SwingUtilities.convertPointToScreen(p, button);
        // dialog.setLocation(p);
        // dialog.setVisible(true);
        // } else
        // dialog.setVisible(false);
        // }
        // });

        list.addFocusListener(new FocusListener() {
            @Override
            public void focusGained(FocusEvent e) {
            }

            @Override
            public void focusLost(FocusEvent e) {
                System.out.println("list focusLost, dialog: " + dialog.isVisible());
                // dialog.setVisible(false);
                MultiComboBox2.this.setSelected(false);
            }
        });
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Test");
        frame.setPreferredSize(new Dimension(300, 300));
        frame.setLayout(new BorderLayout());

        MultiComboBox2 mcb = new MultiComboBox2(frame, "Toggle");

        JPanel buttonPanel = new JPanel(new BorderLayout());
        buttonPanel.setPreferredSize(new Dimension(80, 30));
        buttonPanel.add(mcb, BorderLayout.CENTER);

        JPanel blankPanel = new JPanel(new BorderLayout());
        frame.add(blankPanel, BorderLayout.CENTER);

        frame.add(buttonPanel, BorderLayout.PAGE_START);
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }
}