Java - how do I gain focus on JTextArea when selec

2019-07-16 07:36发布

问题:

I have a swing GUI with multiple JTabbedPanes; each tab contains two JButtons at the top, then a JTextArea (for user input), and a JTextField at the bottom for a result.

My problem is that I can't get the JTextArea to gain focus after switching tabs without either clicking in it with the mouse or using the tab key on the keyboard?

I have...

frame.addWindowFocusListener(new WindowAdapter() {
                        public void windowGainedFocus(WindowEvent e) {
                            textArea_1.requestFocusInWindow();

...and this works well when the app is first run (the textArea in the first tab has focus) but when I switch to another tabbedpane the first button now has the focus instead of the textArea, and when I switch back to the first tab the textArea has lost focus and once again the first button has focus.

I've tried adding a requestFocus to each textArea, and I've tried "Bring to front" on each textArea, and I've messed around with Focus Traversal but nothing I do seems to make the textArea gain focus on a tab change?

This has had me stumped for a week so any help will be gratefully received?

回答1:

Add a ChangeListener to your JTabbedPane. Here's the general idea:

[Sorry, I used JTextFields instead of JTextAreas since I had an old stub laying around - but the idea is the same.]

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.event.*;

public class JTabbedPaneDemo3 implements Runnable
{
  JTextField txtFoo;
  JTextField txtBar;
  JTabbedPane tabbedPane;

  public static void main(String[] args)
  {
    SwingUtilities.invokeLater(new JTabbedPaneDemo3());
  }

  public void run()
  {
    txtFoo = new JTextField(10);
    final JPanel pnlFoo = new JPanel();
    pnlFoo.add(new JButton("Button 1"));
    pnlFoo.add(new JLabel("Foo"));
    pnlFoo.add(txtFoo);

    txtBar = new JTextField(10);
    final JPanel pnlBar = new JPanel();
    pnlBar.add(new JButton("Button 3"));
    pnlBar.add(new JLabel("Bar"));
    pnlBar.add(txtBar);

    tabbedPane = new JTabbedPane();
    tabbedPane.addTab("Tab 1", pnlFoo);
    tabbedPane.addTab("Tab 2", pnlBar);

    tabbedPane.addChangeListener(new ChangeListener()
    {
      public void stateChanged(ChangeEvent e)
      {
        Component comp = tabbedPane.getSelectedComponent();
        if (comp.equals(pnlFoo))
        {
          txtFoo.requestFocusInWindow();
        }
        else if (comp.equals(pnlBar))
        {
          txtBar.requestFocusInWindow();
        }
      }
    });

    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(460, 200);
    frame.getContentPane().add(tabbedPane, BorderLayout.CENTER);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);

    txtFoo.requestFocusInWindow();
  }
}


回答2:

I couldn't make "getSelectedComponent()" work for me, it just wasn't seeing any changes made to the tab selection, but I modified your suggestion slightly and took MadProgrammer's advice and added invokeLater...

tabbedPane.addChangeListener(new ChangeListener()
        {
          public void stateChanged(ChangeEvent e)
          {
              JTabbedPane pane = (JTabbedPane) e.getSource();         
              int selectedIndex = pane.getSelectedIndex();         
              if (selectedIndex == 0)
                {
                SwingUtilities.invokeLater( new Runnable() {   
                public void run() {   
                textArea1.requestFocusInWindow(); }});
                }
             else if (selectedIndex == 1)
                {
                SwingUtilities.invokeLater( new Runnable() {   
                public void run() {   
                textArea2.requestFocusInWindow(); }});
                }
             else if (selectedIndex == 2)
                {
                SwingUtilities.invokeLater( new Runnable() {   
                public void run() {   
                textArea3.requestFocusInWindow(); }});
                }
             else if (selectedIndex == 3)
                {
                SwingUtilities.invokeLater( new Runnable() {   
                public void run() {   
                textArea4.requestFocusInWindow(); }});
                }
             else if (selectedIndex == 4)
                {
                SwingUtilities.invokeLater( new Runnable() {   
                public void run() {   
                textArea5.requestFocusInWindow(); }});
                }
          }
       });

...and now all is right with the world again! Thanks to all.