简体   繁体   English

无法将焦点转移到未显示的CardLayout JPanel

[英]Can't shift focus to unshown CardLayout JPanel

Why can't I shift focus to an unshown JPanel card in a CardLayout ? 为什么不能将焦点转移到CardLayout未显示的JPanel卡上?

I'm implementing a CardLayout -based interface that needs to be keyboard navigation friendly. 我正在实现一个基于CardLayout的界面,该界面需要键盘导航友好。 When a user finishes tabbing through all the fields on one card, the user needs to be able to tab to the next card. 当用户完成一张卡上所有字段的制表符时,该用户需要能够制表到下一张卡。

I've already implemented a FocusTraversalPolicy that produces the right Component at each point in the process, and a FocusAdapter to pop up any cards newly tabbed to, but something is eating the messages and preventing focus change. 我已经实现了一个FocusTraversalPolicy ,可以在流程的每个点上生成正确的Component ,还可以实现一个FocusAdapter来弹出新标签到的所有卡,但是有些东西正在吞噬消息并阻止焦点更改。

I can uncleanly pass the CardLayout to the FocusTraversalPolicy to change the card— though any of its functions are called several times in Swing's many threads and leads to strange behavior. 可以CardLayoutFocusTraversalPolicy地传递给FocusTraversalPolicy来更改卡,尽管它的任何功能在Swing的许多线程中都会多次调用,并导致奇怪的行为。 Besides, that way's just dirty. 此外,那只是肮脏的。

I do not want to use key bindings b/c that would require reimplementing all of the focus work Java already does for me, and is also really unclean. 希望使用的键绑定B / C,将需要重新实现所有重点工作的Java已经做了我,也真的不洁净的。

Basically: Java dislikes shifting focus to unshown cards in CardLayout s— how can I override this? 基本上:Java不喜欢将焦点转移到CardLayout未显示的卡片上, 我该如何覆盖呢?

It sounds like you have a wizard-like UI. 听起来您有一个类似向导的UI。 If so, add a "Next" button as the last field on each card. 如果是这样,请在每个卡的最后一个字段中添加一个“下一步”按钮。

The action of the Next button would be to flip to the next card as set focus to the first entry field. 下一步按钮的作用是将焦点设置到第一个输入字段上,从而翻转到下一张卡片。

The last entry field on each card would transfer focus to the Next button, who could then be "pressed" with a strike of the spacebar when it receives focus (which is the default behavior of a JButton), keeping it keyboard-friendly. 每张卡上的最后一个输入字段会将焦点转移到“下一步”按钮,然后当该按钮收到焦点时可以按下空格键来“按下”(这是JButton的默认行为),从而使其对键盘友好。

This would alleviate the need for special KeyBindings or FocusTraversalPolicies. 这将减轻对特殊的KeyBindings或FocusTraversalPolicies的需求。

EDIT: 编辑:

Try this, using FocusListeners for the JTextFields. 尝试使用JTextFields的FocusListeners。 Tab thorugh the fields and the cards will flip to the next one automatically once you tab out of the last field. 通过跳格,一旦您跳出最后一个字段,该字段和卡片将自动翻转到下一个。 You could use ActionListeners instead if you wish: 如果愿意,可以改用ActionListeners:

EDIT 2: Added hack for panels that only have 1 field. 编辑2:为只有1个字段的面板添加了hack。

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);
    }
  } 
}

I want to keep the program compartmentalized, as it runs in distinct steps. 我想让程序分隔开来,因为它以不同的步骤运行。

This does not prevent you from creating a long scrolling form? 这不会阻止您创建长滚动表单吗?

You can still create individual panels the way you are doing now. 您仍然可以按照现在的方式创建单个面板。 Then instead of adding these panels to a CardLayout where you need to swap panels, you can add the panels to a panel using a BoxLayout (or GridBagLayout). 然后,无需将这些面板添加到需要交换面板的CardLayout中,而是可以使用BoxLayout(或GridBagLayout)将面板添加到面板中。

This would even give more flexibility since each panel can be of a different size without impacting the size of every individual panel. 这甚至将提供更大的灵活性,因为每个面板的大小可以不同,而不会影响每个单独面板的大小。

However, forms do not currently scroll automatically in a JScrollPane, so you may want to check out Scrolling a Form for a class this will do this for you. 但是,表单当前无法在JScrollPane中自动滚动,因此您可能需要签出为某个类滚动表单” ,这将为您做到这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM