gpt4 book ai didi

java - 处理 JDialog 和 JToggleButton 的状态和事件序列

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:54:09 28 4
gpt4 key购买 nike

我正在尝试构建一个 JToggleButton显示 JDialog (包含 JList )当 JToggleButton被按下。并且有 JDialogJToggleButton 消失时再次按下,或者如果用户点击离开或框架中的其他地方(当焦点丢失时,我通过 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);
}
}

最佳答案

建议:

  • 不要向 JToggleButton 添加 ActionListener
  • 而是添加一个 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);
}
}

关于java - 处理 JDialog 和 JToggleButton 的状态和事件序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36664141/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com