聚焦的 JTextField 阻止访问 JPanel 的 ActionMap
Focused JTextField prevents access to ActionMap of JPanel
下面的代码可以触发两个动作:
- the "Paste" action triggered by the "Paste" JButton or "Ctrl V" KeyStroke.
- the "Close" action triggered by the "Close" JButton or "Esc" KeyStroke.
如果满足以下条件,则每个操作都有效:
- you do not select a JTextField and you click the JButton.
- you do not select a JTextField and you use the Keystroke.
- you select a JTextField and you click the JButton.
如果复制电子表格的两个单元格的内容,"Paste" 操作会将每个单元格的内容粘贴到相应的 JTextField 中。
"Close" 操作将关闭 JFrame。
但是,如果 :
- you select a JTextField and you use the Keystroke.
如果复制电子表格的两个单元格的内容,"Paste" 操作将粘贴所选 JTextField 中所有单元格的内容。
"Close" 操作不会关闭 JFrame。
我该如何解决这个问题?
我尝试了很多东西,例如 How to UnFocus a JTextField。
我错过了一些东西,因为 none 他们工作了。
提前感谢您的回答。
这是代码:
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.Scanner;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
public class Test extends JFrame implements ActionListener {
private static JTextField[] A;
private static JButton[] B;
public static void main(String[] args) {
Test F = new Test();
JPanel H = new JPanel();
F.setContentPane(H);
A = new JTextField[2];
B = new JButton[2];
B[0] = new JButton("Paste");
H.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_V,InputEvent.CTRL_MASK),"0");
H.getActionMap().put("0",new AbstractAction() {
public void actionPerformed(ActionEvent J) {
B[0].doClick();
}
});
B[1] = new JButton("Close");
H.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0),"1");
H.getActionMap().put("1",new AbstractAction() {
public void actionPerformed(ActionEvent J) {
B[1].doClick();
}
});
GridBagLayout I = new GridBagLayout();
H.setLayout(I);
for (int i=0;i<A.length;i++) {
A[i] = new JTextField();
A[i].setHorizontalAlignment(SwingConstants.CENTER);
A[i].setPreferredSize(new Dimension((int)B[i].getPreferredSize().getWidth(),(int)A[i].getPreferredSize().getHeight()));
I.setConstraints(A[i],new GridBagConstraints(0,i,1,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,0,0),0,0));
H.add(A[i]);
}
for (int i=0;i<B.length;i++) {
B[i].addActionListener(F);
B[i].setActionCommand(String.valueOf(i));
I.setConstraints(B[i],new GridBagConstraints(0,A.length+i,1,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,0,0),0,0));
H.add(B[i]);
}
F.pack();
F.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
F.setLocationRelativeTo(null);
F.setTitle("Parameters");
F.setVisible(true);
}
public void actionPerformed(ActionEvent J) {
if(J.getActionCommand().equals("0")) {
try {
if (Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null)!=null && Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null).isDataFlavorSupported(DataFlavor.stringFlavor) && A[0].isEditable() && A[1].isEditable()) {
Scanner D = new Scanner((String)Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null).getTransferData(DataFlavor.stringFlavor));
A[0].setText(String.valueOf(D.next()));
A[1].setText(String.valueOf(D.next()));
D.close();
}
}
catch (Throwable K) {
System.out.println("Paste failed");
}
}
if (J.getActionCommand().equals("1")) {
this.dispose();
}
}
}
上面的代码甚至没有在选择 JTextField 时进入 JPanel 的 ActionMap。
因此,我找到的解决方案是通过添加将 JPanel 的 ActionMap 添加到每个 JTextField:
A[i].getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_V,InputEvent.CTRL_MASK),"0");
A[i].getActionMap().put(String.valueOf("0"),new AbstractAction() {
public void actionPerformed(ActionEvent J) {
B[0].doClick();
}
});
A[i].getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0),"1");
A[i].getActionMap().put(String.valueOf("1"),new AbstractAction() {
public void actionPerformed(ActionEvent J) {
B[1].doClick();
}
});
之后:
A[i] = new JTextField();
下面的代码可以触发两个动作:
- the "Paste" action triggered by the "Paste" JButton or "Ctrl V" KeyStroke.
- the "Close" action triggered by the "Close" JButton or "Esc" KeyStroke.
如果满足以下条件,则每个操作都有效:
- you do not select a JTextField and you click the JButton.
- you do not select a JTextField and you use the Keystroke.
- you select a JTextField and you click the JButton.
如果复制电子表格的两个单元格的内容,"Paste" 操作会将每个单元格的内容粘贴到相应的 JTextField 中。
"Close" 操作将关闭 JFrame。
但是,如果 :
- you select a JTextField and you use the Keystroke.
如果复制电子表格的两个单元格的内容,"Paste" 操作将粘贴所选 JTextField 中所有单元格的内容。
"Close" 操作不会关闭 JFrame。
我该如何解决这个问题?
我尝试了很多东西,例如 How to UnFocus a JTextField。
我错过了一些东西,因为 none 他们工作了。
提前感谢您的回答。
这是代码:
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.Scanner;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
public class Test extends JFrame implements ActionListener {
private static JTextField[] A;
private static JButton[] B;
public static void main(String[] args) {
Test F = new Test();
JPanel H = new JPanel();
F.setContentPane(H);
A = new JTextField[2];
B = new JButton[2];
B[0] = new JButton("Paste");
H.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_V,InputEvent.CTRL_MASK),"0");
H.getActionMap().put("0",new AbstractAction() {
public void actionPerformed(ActionEvent J) {
B[0].doClick();
}
});
B[1] = new JButton("Close");
H.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0),"1");
H.getActionMap().put("1",new AbstractAction() {
public void actionPerformed(ActionEvent J) {
B[1].doClick();
}
});
GridBagLayout I = new GridBagLayout();
H.setLayout(I);
for (int i=0;i<A.length;i++) {
A[i] = new JTextField();
A[i].setHorizontalAlignment(SwingConstants.CENTER);
A[i].setPreferredSize(new Dimension((int)B[i].getPreferredSize().getWidth(),(int)A[i].getPreferredSize().getHeight()));
I.setConstraints(A[i],new GridBagConstraints(0,i,1,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,0,0),0,0));
H.add(A[i]);
}
for (int i=0;i<B.length;i++) {
B[i].addActionListener(F);
B[i].setActionCommand(String.valueOf(i));
I.setConstraints(B[i],new GridBagConstraints(0,A.length+i,1,1,0,0,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,0,0),0,0));
H.add(B[i]);
}
F.pack();
F.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
F.setLocationRelativeTo(null);
F.setTitle("Parameters");
F.setVisible(true);
}
public void actionPerformed(ActionEvent J) {
if(J.getActionCommand().equals("0")) {
try {
if (Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null)!=null && Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null).isDataFlavorSupported(DataFlavor.stringFlavor) && A[0].isEditable() && A[1].isEditable()) {
Scanner D = new Scanner((String)Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null).getTransferData(DataFlavor.stringFlavor));
A[0].setText(String.valueOf(D.next()));
A[1].setText(String.valueOf(D.next()));
D.close();
}
}
catch (Throwable K) {
System.out.println("Paste failed");
}
}
if (J.getActionCommand().equals("1")) {
this.dispose();
}
}
}
上面的代码甚至没有在选择 JTextField 时进入 JPanel 的 ActionMap。
因此,我找到的解决方案是通过添加将 JPanel 的 ActionMap 添加到每个 JTextField:
A[i].getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_V,InputEvent.CTRL_MASK),"0");
A[i].getActionMap().put(String.valueOf("0"),new AbstractAction() {
public void actionPerformed(ActionEvent J) {
B[0].doClick();
}
});
A[i].getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0),"1");
A[i].getActionMap().put(String.valueOf("1"),new AbstractAction() {
public void actionPerformed(ActionEvent J) {
B[1].doClick();
}
});
之后:
A[i] = new JTextField();