我正在使用Swing程序并遇到一些麻烦。该程序有两个窗口(都是JFrame)。主窗口很好,不应该与这个问题相关。
我遇到问题的窗口包含一个带有JPanel的JScrollPane,并且有一个JMenuBar。 JPanel上有一堆JTextComponents(一些JTextFields,一些JTextAreas)。
我想要做的是将一个连接到JMenuItem的ActionListener找到具有焦点的JTextComponent。
我在focused component reference和How to find out which object currently has focus看过以前的帖子。我的问题是调用特定窗口的getFocusOwner()
方法只返回JFrame的JRootPane
,这完全没有用。有问题的JScrollPane和JPanel都可以根据他们的isFocusable()
方法进行关注。即使我在单击菜单项之前实际在其中一个JTextComponents中输入文本,也会发生这种情况。当我打开菜单时,光标仍然在文本字段中闪烁。对于它的价值,getMostRecentFocusOwner()
也只是返回JRootPane。
答案 0 :(得分:2)
如果使用TextActions,则操作知道哪个JTextComponent具有焦点。我修改了一些我发现here的代码,以表明即使TextActions来自一个JTextArea,它们仍会自动处理任何有焦点的文本组件:
import java.awt.GridLayout;
import javax.swing.*;
public class TextActionExample {
public static void main(String[] args) {
// Create a text area.
JTextArea ta = new JTextArea(15, 30);
ta.setLineWrap(true);
// Add all actions to the menu (split into two menus to make it more
// usable).
Action[] actions = ta.getActions();
JMenuBar menubar = new JMenuBar();
JMenu actionmenu = new JMenu("Actions");
menubar.add(actionmenu);
JMenu firstHalf = new JMenu("1st Half");
JMenu secondHalf = new JMenu("2nd Half");
actionmenu.add(firstHalf);
actionmenu.add(secondHalf);
int mid = actions.length / 2;
for (int i = 0; i < mid; i++) {
firstHalf.add(actions[i]);
}
for (int i = mid; i < actions.length; i++) {
secondHalf.add(actions[i]);
}
JTextField textField = new JTextField(20);
JPanel textFieldPanel = new JPanel();
textFieldPanel.add(textField);
JPanel mainPanel = new JPanel(new GridLayout(1, 0, 5, 5));
mainPanel.add(new JScrollPane(ta));
mainPanel.add(new JScrollPane(new JTextArea(15, 30)));
mainPanel.add(textFieldPanel);
// Show it . . .
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(mainPanel);
f.setJMenuBar(menubar);
f.pack();
f.setVisible(true);
}
}
这是非常有趣的东西,我必须要了解更多。
答案 1 :(得分:1)
我想我已经解决了这个问题,因为当你点击一个菜单项时你失去了焦点,我们只需要等待焦点返回到组件,然后再检查谁有焦点,我使用了一个等待100毫秒然后执行其方法以检查哪个组件具有焦点的摆动计时器:
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.TimerTask;
import javax.swing.*;
public class JavaApplication180 extends JFrame {
private JTextField[] JTextFields;
private JMenuBar menuBar;
private JMenu menu;
private JMenuItem item;
public JavaApplication180() {
initComponents();
createAndShowUI();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new JavaApplication180();
}
});
}
private void createAndShowUI() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new GridLayout(2, 2, 10, 10));
setJMenuBar(menuBar);
addComponentsToPane();
pack();
setVisible(true);
}
private void initComponents() {
JTextFields = new JTextField[4];
menuBar = new JMenuBar();
item = new JMenuItem("Who has focus?");
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
TimerTask tt = new TimerTask() {
@Override
public void run() {
JOptionPane.showMessageDialog(null, getMostRecentFocusOwner().getName());
}
};
new java.util.Timer().schedule(tt, 100);
}
});
menu = new JMenu("File");
menu.add(item);
menuBar.add(menu);
}
private void addComponentsToPane() {
for (int i = 0; i < JTextFields.length; i++) {
JTextFields[i] = new JTextField();
JTextFields[i].setText(String.valueOf(i));
JTextFields[i].setName(String.valueOf(i));
getContentPane().add(JTextFields[i]);
}
}
}
答案 2 :(得分:1)
我可能为时已晚,但我只是在我的JFrame构造函数中执行了以下操作。
this.rootPane.setFocusable(false);
现在
getFocusOwner()
将返回当前的JTextComponent而不是rootPane。 然后我在附加到我的JMenuItem的ActionListener中使用此代码来选择其中的文本。
if (getFocusOwner() instanceof JTextField)
{
((JTextField) getMostRecentFocusOwner()).selectAll();
}
应该注意的是,如果你有一个JScrollPane等,你可能必须对rootPane和textfields之间的所有组件使用setFocusable(false)。
希望这可以帮助其他人解决同样的问题!
来源:个人经历
答案 3 :(得分:0)
当我需要这个时,我写了一个焦点听众。我有一个带有两列JTextField的JPanel,焦点监听器跟踪用户上次使用的列。我允许用户通过单击按钮在最后一个聚焦列中输入一些文本。您只需将FocusListener的一个实例用于所有文本字段,并且具有引用最近聚焦的组件的字段。然后,您的菜单操作可以查询该字段以确定要使用的文本字段。
请参阅http://docs.oracle.com/javase/tutorial/uiswing/events/focuslistener.html