我想拥有历史记录的命令窗口。我制作了okAction
并将其绑定到Ok
按钮。发出命令时会调用此命令。
如果命令成功,则从输入单元格中删除命令文本并将其添加到历史记录中。这是使用可编辑的JComboBox
。
如果用户从历史记录中选择某个命令,则与按Ok
按钮时的命令相同。所以我也把同样的动作绑在了组合框上。
不幸的是,使用组合框进行操作也会导致操作调用。在以下示例中,模拟命令失败,一个名为3次的动作。
为什么?
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
import javax.swing.border.*;
public class JCommandWindow extends JFrame {
private static final Random rnd = new Random();
private static final long serialVersionUID = 1L;
private AbstractAction okAction = new AbstractAction("Ok") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
if (issue((String) inputComboBox.getSelectedItem())) {
inputComboBox.setSelectedItem("");
} else {
inputComboBox.getEditor().selectAll();
}
}
};
private AbstractAction cancelAction = new AbstractAction("Cancel") {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e) {
close();
}
};
private JTextArea logTextArea = new JTextArea();
{
logTextArea.setWrapStyleWord(true);
logTextArea.setBorder(new EtchedBorder());
logTextArea.setEditable(false);
}
private JScrollPane logScrollPane = new JScrollPane(logTextArea);
{
logScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
logScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
}
private JPanel logPanel = new JPanel();
{
logPanel.setLayout(new BorderLayout());
logPanel.setBorder(new EmptyBorder(5, 5, 0, 5));
logPanel.add(logScrollPane, BorderLayout.CENTER);
}
private DefaultComboBoxModel historyModel = new DefaultComboBoxModel();
private JComboBox inputComboBox = new JComboBox();
{
inputComboBox.setModel(historyModel);
inputComboBox.setEditable(true);
inputComboBox.addActionListener(okAction);
}
private JPanel inputPanel = new JPanel();
{
inputPanel.setLayout(new BorderLayout());
inputPanel.setBorder(new EmptyBorder(5, 5, 5, 0));
inputPanel.add(inputComboBox, BorderLayout.CENTER);
}
private JButton okButton = new JButton(okAction);
private JButton cancelButton = new JButton(cancelAction);
private JPanel buttonPanel = new JPanel();
{
buttonPanel.setLayout(new FlowLayout());
buttonPanel.add(okButton);
buttonPanel.add(cancelButton);
}
private JPanel bottomPanel = new JPanel();
{
bottomPanel.setLayout(new BorderLayout());
bottomPanel.add(inputPanel, BorderLayout.CENTER);
bottomPanel.add(buttonPanel, BorderLayout.EAST);
}
private final JRootPane rootPane = getRootPane();
{
rootPane.setLayout(new BorderLayout());
rootPane.add(logPanel, BorderLayout.CENTER);
rootPane.add(bottomPanel, BorderLayout.SOUTH);
rootPane.setDefaultButton(okButton);
rootPane.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
cancelAction.actionPerformed(null);
}
}
});
addWindowFocusListener(new WindowFocusListener() {
@Override
public void windowLostFocus(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowGainedFocus(WindowEvent e) {
inputComboBox.requestFocusInWindow();
}
});
}
public JCommandWindow() {
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
}
public void close() {
WindowEvent wev = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(wev);
}
@Override
public void pack() {
super.pack();
// Get the size of the screen
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
int w = dim.width * 2 / 3;
int h = dim.height * 2 / 3;
setSize(w, h);
int x = (dim.width - w) / 2;
int y = (dim.height - h) / 2;
// Move the window
setLocation(x, y);
}
public void addText(String text) {
logTextArea.append(text + "\n");
logTextArea.setCaretPosition(logTextArea.getDocument().getLength());
}
public void rememberCommand(String command) {
historyModel.addElement(command);
}
public boolean issue(String command) {
/*
if( rnd.nextBoolean() ) {
addText(command + " succeeded");
rememberCommand(command);
return true;
}
else {
addText(command + " failed");
return false;
}
*/
addText(command + " failed");
return false;
}
public static void main(String[] args) {
JCommandWindow commandWindow = new JCommandWindow();
commandWindow.pack();
commandWindow.setVisible(true);
}
}
答案 0 :(得分:4)
当可编辑的组合框失去焦点时,会触发contentsChanged
事件的JComboBox
方法,触发actionPerformed
的{{1}}。然后,ActionListener
再次调用相同的focusLost
。
然后,触发按钮按下的动作。