为什么我无法将焦点转移到JPanel
中未显示的CardLayout
卡?
我正在实现一个基于CardLayout
的界面,需要键盘导航友好。当用户完成对一张卡上所有字段的选项卡切换时,用户需要能够切换到下一张卡片。
我已经实施了一个FocusTraversalPolicy
,在此过程中的每个点生成了正确的Component
,并FocusAdapter
用于弹出新标记的卡片,但有些东西正在吃消息和防止焦点改变。
我可以不清楚地将CardLayout
传递给FocusTraversalPolicy
以更改卡片 - 虽然它在Swing的多个线程中多次调用它的任何函数并导致奇怪的行为。此外,那种方式只是肮脏的。
我不想要使用键盘绑定b / c,这需要重新实现Java已经为我做的所有焦点工作,并且也非常不洁净。
基本上:Java不喜欢将焦点转移到CardLayout
s中的未显示的卡片 - 如何覆盖它?
答案 0 :(得分:2)
听起来你有一个类似巫师的UI。如果是这样,请添加"下一步"按钮作为每张卡片上的最后一个字段。
“下一步”按钮的操作是将设置焦点翻转到下一张卡片到第一个输入字段。
每张卡片上的最后一个输入字段会将焦点转移到“下一步”按钮,然后可以按下"按下"获得焦点时空格键的敲击(这是JButton的默认行为),保持键盘友好。
这将减少对特殊KeyBindings或FocusTraversalPolicies的需求。
修改强>
尝试使用FocusListeners作为JTextFields。选项卡切换到字段,一旦您退出最后一个字段,卡片将自动翻转到下一个。如果您愿意,可以使用ActionListeners:
编辑2:为只有1个字段的面板添加了黑客攻击。
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
public class CardLayoutDemo2 implements Runnable
{
final static String CARD1 = "One";
final static String CARD2 = "Two";
final static String CARD3 = "Three";
JPanel cards;
CardLayout cardLayout;
JTextField tf1, tf2, tf3, tf4, tf5;
JButton dummy;
public static void main(String[] args)
{
SwingUtilities.invokeLater(new CardLayoutDemo2());
}
public void run()
{
tf1 = new JTextField(10);
tf2 = new JTextField(10);
tf2.addFocusListener(new CardFlipper(CARD2));
tf3 = new JTextField(10);
tf4 = new JTextField(10);
tf4.addFocusListener(new CardFlipper(CARD3));
tf5 = new JTextField(10);
tf5.addFocusListener(new CardFlipper(CARD1));
dummy = new JButton()
{
@Override
public Dimension getPreferredSize()
{
return new Dimension(0,0);
}
};
dummy.addFocusListener(new FocusAdapter()
{
@Override
public void focusGained(FocusEvent e)
{
dummy.transferFocus();
}
});
JPanel card1 = new JPanel();
card1.add(new JLabel("One"));
card1.add(tf1);
card1.add(new JLabel("Two"));
card1.add(tf2);
JPanel card2 = new JPanel();
card2.add(new JLabel("Three"));
card2.add(tf3);
card2.add(new JLabel("Four"));
card2.add(tf4);
JPanel card3 = new JPanel();
card3.add(dummy);
card3.add(new JLabel("Five"));
card3.add(tf5);
cardLayout = new CardLayout();
cards = new JPanel(cardLayout);
cards.add(card1, CARD1);
cards.add(card2, CARD2);
cards.add(card3, CARD3);
JFrame f = new JFrame("CardLayout Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(cards, BorderLayout.CENTER);
f.setSize(180, 200);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private class CardFlipper extends FocusAdapter
{
private String nextCard;
CardFlipper(String cardName)
{
this.nextCard = cardName;
}
@Override
public void focusLost(FocusEvent e)
{
cardLayout.show(cards, nextCard);
}
}
}
答案 1 :(得分:2)
我想让程序分开,因为它以不同的步骤运行。
这不会阻止您创建长滚动表单?
您仍然可以按照现在的方式创建单独的面板。然后,您可以使用BoxLayout(或GridBagLayout)将面板添加到面板,而不是将这些面板添加到需要交换面板的CardLayout。
这甚至可以提供更大的灵活性,因为每个面板可以具有不同的尺寸,而不会影响每个面板的尺寸。
但是,表单当前不会在JScrollPane中自动滚动,因此您可能需要查看Scrolling a Form这样的类,这将为您执行此操作。