如何摆脱函数中的重复代码?
How to get rid of repeating code in function?
我想从应用程序中删除重复代码。我尝试了多种方法,但当我这样做时,应用程序并没有像我预期的那样工作。只有将相同的代码放在一个函数中才会有效果。
简而言之,在应用程序中,我可以通过两种方式删除记录,一种是按下按钮,另一种是指向一条记录并用鼠标右键将其删除。删除按钮可以,但是不知道如何让鼠标删除也有同样的效果。
删除 table 中记录的按钮。
deleteButton.addActionListener(event -> {
String name;
name = Name.getText();
try {
removeSelectedRow(table1);
pst = con.prepareStatement("delete from recipe where recipe_name = ?");
pst.setString(1, name);
pst.executeUpdate();
JOptionPane.showMessageDialog(null, "Record deleted");
Name.setText("");
Time.setText("");
Difficulty.setSelectedItem("");
Name.requestFocus();
} catch (SQLException e) {
e.printStackTrace();
}
});
这里有一个应该用鼠标右键删除的函数,如您所见,它可以工作,但代码与前面的示例几乎相同。
public void setDeleteButton(ActionEvent event) {
JMenuItem menu = (JMenuItem) event.getSource();
if (menu == menuItemRemove) {
removeSelectedRow(table1);
}
String name;
name = Name.getText();
try {
removeSelectedRow(table1);
pst = con.prepareStatement("delete from recipe where recipe_name = ?");
pst.setString(1, name);
pst.executeUpdate();
JOptionPane.showMessageDialog(null, "Record deleted");
Name.setText("");
Time.setText("");
Difficulty.setSelectedItem("");
Name.requestFocus();
} catch (SQLException e) {
e.printStackTrace();
}
}
指向特定记录的函数
public void removeSelectedRow(JTable table) {
DefaultTableModel model = (DefaultTableModel) table1.getModel();
if (table.getSelectedRow() != -1) {
model.removeRow(table.getSelectedRow());
}
}
好的,所以这需要稍微改变一下心态。要使其真正灵活,您将需要支持“依赖注入”和“委派”等概念。
原因是,您的“操作”需要大量信息,但是,我们应该朝着 类 之间低水平的内聚或耦合方向发展。例如,您的“操作”不应该关心“如何”删除该行,只关心在请求时应该完成。
那么,让我们从一些基本的委派开始...
public interface MutableTableSupportable {
public void addListSelectionListener(ListSelectionListener listener);
public void removeListSelectionListener(ListSelectionListener listener);
}
public interface TableRowDeletable extends MutableTableSupportable {
public int getSelectedRowCount();
public void removeSelectedRow();
}
现在,很明显,我过度简化了这一点以满足我的更多需求,但在这里我提供了一个“基本”级别的委托和更有针对性的委托。为什么?因为如果您想提供“插入”操作会怎样?为什么要有“删除”功能?相反,我们故意隔离我们想要公开的功能。
接下来,我们需要设计我们的动作...
public class DeleteRowAction extends AbstractAction {
private TableRowDeletable delgate;
public DeleteRowAction(TableRowDeletable delgate) {
putValue(SHORT_DESCRIPTION, "Delete the currently selected row");
putValue(MNEMONIC_KEY, KeyEvent.VK_D);
putValue(NAME, "Delete Row");
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, KeyEvent.CTRL_DOWN_MASK));
this.delgate = delgate;
delgate.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
selectionDidChange();
}
});
selectionDidChange();
}
protected void selectionDidChange() {
setEnabled(delgate.getSelectedRowCount() > 0);
}
@Override
public void actionPerformed(ActionEvent e) {
delgate.removeSelectedRow();
}
}
好的,没什么特别的,这就是重点。它监视选择状态,因此我们可以 enable/disable 操作,当触发时,我们调用我们的委托来完成实际工作。这将操作与实现分离,因为操作不需要知道正在使用什么类型的 TableModel
或者它可能正在使用什么类型的数据源,它只是想告诉委托它应该携带进行某种操作。
另请注意,我们设置了一个键盘快捷键,可用于 JMenuItem
和助记符支持(按住 Alt 或 选项键)
好的,但这对我们来说真的很重要,或者是...
让我们看看删除操作可能是什么样子...
DeleteRowAction deleteRowAction = new DeleteRowAction(new TableRowDeletable() {
@Override
public int getSelectedRowCount() {
return table.getSelectedRowCount();
}
@Override
public void removeSelectedRow() {
DefaultTableModel model = (DefaultTableModel) table.getModel();
int visibleRowIndex = table.getSelectedRow();
if (visibleRowIndex == -1) {
return;
}
int modelIndex = table.convertRowIndexToModel(visibleRowIndex);
// I'm guessing here, but if you're deleting a row, you should
// use the row data
String recordId = (String) model.getValueAt(modelIndex, 0);
try (PreparedStatement pst = getConnection().prepareStatement("delete from recipe where recipe_name = ?")) {
pst.setString(1, recordId);
// You could check the number of rows effected by this change
pst.executeUpdate();
JOptionPane.showMessageDialog(TestPane.this, "Record deleted", "Success", JOptionPane.INFORMATION_MESSAGE);
model.removeRow(modelIndex);
} catch (SQLException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(TestPane.this, "Failed to delete row from database", "Error", JOptionPane.ERROR_MESSAGE);
}
}
@Override
public void addListSelectionListener(ListSelectionListener listener) {
table.getSelectionModel().addListSelectionListener(listener);
}
@Override
public void removeListSelectionListener(ListSelectionListener listener) {
table.getSelectionModel().removeListSelectionListener(listener);
}
});
现在,这只是一个示例,但基本思想是,我们已经为 MutableTableSupportable
和 TableRowDeletable
接口提供了实现(但 DeleteRowAction
没有关心“如何”),我们已经实现了 removeSelectedRow
功能来从 TableModel
和数据库中删除行。
同样,DeleteRowAction
不关心这是如何实现的,它只是委托责任,所以你可以有多个 DeleteRowAction
s,它们与不同的 TableModel
s 和数据一起工作同时来源
代表团
好的,但是所有这些如何协同工作?嗯,其实,真的很容易,事实上
可运行示例...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import java.sql.*;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JMenuBar menuBar = new JMenuBar();
JFrame frame = new JFrame();
frame.setJMenuBar(menuBar);
frame.add(new TestPane(menuBar));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JTable table;
public TestPane(JMenuBar menuBar) {
setLayout(new BorderLayout());
DefaultTableModel model = new DefaultTableModel(new Object[][]{new Object[]{"Test"}}, new Object[]{"Test"});
table = new JTable(model);
add(new JScrollPane(table));
DeleteRowAction deleteRowAction = new DeleteRowAction(new TableRowDeletable() {
@Override
public int getSelectedRowCount() {
return table.getSelectedRowCount();
}
@Override
public void removeSelectedRow() {
JOptionPane.showMessageDialog(TestPane.this, "Delete the row please", "Debug", JOptionPane.INFORMATION_MESSAGE);
}
@Override
public void addListSelectionListener(ListSelectionListener listener) {
table.getSelectionModel().addListSelectionListener(listener);
}
@Override
public void removeListSelectionListener(ListSelectionListener listener) {
table.getSelectionModel().removeListSelectionListener(listener);
}
});
JMenu actionsMenu = new JMenu("Actions");
actionsMenu.add(deleteRowAction);
menuBar.add(actionsMenu);
JButton deleteButton = new JButton(deleteRowAction);
add(deleteButton, BorderLayout.SOUTH);
}
}
public interface MutableTableSupportable {
public void addListSelectionListener(ListSelectionListener listener);
public void removeListSelectionListener(ListSelectionListener listener);
}
public interface TableRowDeletable extends MutableTableSupportable {
public int getSelectedRowCount();
public void removeSelectedRow();
}
public class DeleteRowAction extends AbstractAction {
private TableRowDeletable delgate;
public DeleteRowAction(TableRowDeletable delgate) {
putValue(SHORT_DESCRIPTION, "Delete the currently selected row");
putValue(MNEMONIC_KEY, KeyEvent.VK_D);
putValue(NAME, "Delete Row");
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, KeyEvent.CTRL_DOWN_MASK));
this.delgate = delgate;
delgate.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
selectionDidChange();
}
});
selectionDidChange();
}
protected void selectionDidChange() {
setEnabled(delgate.getSelectedRowCount() > 0);
}
@Override
public void actionPerformed(ActionEvent e) {
delgate.removeSelectedRow();
}
}
}
nb:此示例删除了数据库支持,因为我没有,而是显示一条消息
好的,让我们快速浏览一下这里的一些有趣的东西...
首先...
JMenuBar menuBar = new JMenuBar();
JFrame frame = new JFrame();
frame.setJMenuBar(menuBar);
frame.add(new TestPane(menuBar));
我们将菜单栏注入到面板中。这样做是为了让面板可以根据需要配置菜单栏。我们可以在这里使用一种类型的工厂或其他委托,但我会把它留给你自己想办法。
下一个...
JMenu actionsMenu = new JMenu("Actions");
actionsMenu.add(deleteRowAction);
menuBar.add(actionsMenu);
JButton deleteButton = new JButton(deleteRowAction);
add(deleteButton, BorderLayout.SOUTH);
我们构建 JMenu
并添加我们的删除行操作并创建一个 JButton
,使用相同的 Action
... 五行代码,我们实际上已经完成很多。我们已经能够设置每个组件显示的文本、工具提示文本、加速键和助记符...尝试手动执行此操作,然后需要更改一些东西(想要支持本地化 - 需要制作一个位置的变化)
但是等等,我们可以做得更多!!
如果我们添加...
InputMap inputMap = table.getInputMap(WHEN_FOCUSED);
ActionMap actionMap = table.getActionMap();
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0), "deleteRow");
actionMap.put("deleteRow", deleteRowAction);
到构造函数的末尾,我们可以为用户提供一个键绑定,这样当JTable
有键盘焦点并且命中他们Delete /Backspace键,也会触发动作!!!
现在我们有四种触发动作的方法:
- 按下按钮
- 打开并触发菜单项
- 使用菜单键盘“加速器”键绑定
- 点击删除键
操作
键绑定可运行示例...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JMenuBar menuBar = new JMenuBar();
JFrame frame = new JFrame();
frame.setJMenuBar(menuBar);
frame.add(new TestPane(menuBar));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JTable table;
public TestPane(JMenuBar menuBar) {
setLayout(new BorderLayout());
DefaultTableModel model = new DefaultTableModel(new Object[][]{new Object[]{"Test"}}, new Object[]{"Test"});
table = new JTable(model);
add(new JScrollPane(table));
DeleteRowAction deleteRowAction = new DeleteRowAction(new TableRowDeletable() {
@Override
public int getSelectedRowCount() {
return table.getSelectedRowCount();
}
@Override
public void removeSelectedRow() {
JOptionPane.showMessageDialog(TestPane.this, "Delete the row please", "Debug", JOptionPane.INFORMATION_MESSAGE);
}
@Override
public void addListSelectionListener(ListSelectionListener listener) {
table.getSelectionModel().addListSelectionListener(listener);
}
@Override
public void removeListSelectionListener(ListSelectionListener listener) {
table.getSelectionModel().removeListSelectionListener(listener);
}
});
JMenu actionsMenu = new JMenu("Actions");
actionsMenu.add(deleteRowAction);
menuBar.add(actionsMenu);
JButton deleteButton = new JButton(deleteRowAction);
add(deleteButton, BorderLayout.SOUTH);
InputMap inputMap = table.getInputMap(WHEN_FOCUSED);
ActionMap actionMap = table.getActionMap();
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0), "deleteRow");
actionMap.put("deleteRow", deleteRowAction);
}
}
public interface MutableTableSupportable {
public void addListSelectionListener(ListSelectionListener listener);
public void removeListSelectionListener(ListSelectionListener listener);
}
public interface TableRowDeletable extends MutableTableSupportable {
public int getSelectedRowCount();
public void removeSelectedRow();
}
public class DeleteRowAction extends AbstractAction {
private TableRowDeletable delgate;
public DeleteRowAction(TableRowDeletable delgate) {
putValue(SHORT_DESCRIPTION, "Delete the currently selected row");
putValue(MNEMONIC_KEY, KeyEvent.VK_D);
putValue(NAME, "Delete Row");
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, KeyEvent.CTRL_DOWN_MASK));
this.delgate = delgate;
delgate.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
selectionDidChange();
}
});
selectionDidChange();
}
protected void selectionDidChange() {
setEnabled(delgate.getSelectedRowCount() > 0);
}
@Override
public void actionPerformed(ActionEvent e) {
delgate.removeSelectedRow();
}
}
}
但这还不是全部!我们还可以向 JToolBar
添加一个按钮,因为,为什么不呢!?
我想从应用程序中删除重复代码。我尝试了多种方法,但当我这样做时,应用程序并没有像我预期的那样工作。只有将相同的代码放在一个函数中才会有效果。
简而言之,在应用程序中,我可以通过两种方式删除记录,一种是按下按钮,另一种是指向一条记录并用鼠标右键将其删除。删除按钮可以,但是不知道如何让鼠标删除也有同样的效果。
删除 table 中记录的按钮。
deleteButton.addActionListener(event -> {
String name;
name = Name.getText();
try {
removeSelectedRow(table1);
pst = con.prepareStatement("delete from recipe where recipe_name = ?");
pst.setString(1, name);
pst.executeUpdate();
JOptionPane.showMessageDialog(null, "Record deleted");
Name.setText("");
Time.setText("");
Difficulty.setSelectedItem("");
Name.requestFocus();
} catch (SQLException e) {
e.printStackTrace();
}
});
这里有一个应该用鼠标右键删除的函数,如您所见,它可以工作,但代码与前面的示例几乎相同。
public void setDeleteButton(ActionEvent event) {
JMenuItem menu = (JMenuItem) event.getSource();
if (menu == menuItemRemove) {
removeSelectedRow(table1);
}
String name;
name = Name.getText();
try {
removeSelectedRow(table1);
pst = con.prepareStatement("delete from recipe where recipe_name = ?");
pst.setString(1, name);
pst.executeUpdate();
JOptionPane.showMessageDialog(null, "Record deleted");
Name.setText("");
Time.setText("");
Difficulty.setSelectedItem("");
Name.requestFocus();
} catch (SQLException e) {
e.printStackTrace();
}
}
指向特定记录的函数
public void removeSelectedRow(JTable table) {
DefaultTableModel model = (DefaultTableModel) table1.getModel();
if (table.getSelectedRow() != -1) {
model.removeRow(table.getSelectedRow());
}
}
好的,所以这需要稍微改变一下心态。要使其真正灵活,您将需要支持“依赖注入”和“委派”等概念。
原因是,您的“操作”需要大量信息,但是,我们应该朝着 类 之间低水平的内聚或耦合方向发展。例如,您的“操作”不应该关心“如何”删除该行,只关心在请求时应该完成。
那么,让我们从一些基本的委派开始...
public interface MutableTableSupportable {
public void addListSelectionListener(ListSelectionListener listener);
public void removeListSelectionListener(ListSelectionListener listener);
}
public interface TableRowDeletable extends MutableTableSupportable {
public int getSelectedRowCount();
public void removeSelectedRow();
}
现在,很明显,我过度简化了这一点以满足我的更多需求,但在这里我提供了一个“基本”级别的委托和更有针对性的委托。为什么?因为如果您想提供“插入”操作会怎样?为什么要有“删除”功能?相反,我们故意隔离我们想要公开的功能。
接下来,我们需要设计我们的动作...
public class DeleteRowAction extends AbstractAction {
private TableRowDeletable delgate;
public DeleteRowAction(TableRowDeletable delgate) {
putValue(SHORT_DESCRIPTION, "Delete the currently selected row");
putValue(MNEMONIC_KEY, KeyEvent.VK_D);
putValue(NAME, "Delete Row");
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, KeyEvent.CTRL_DOWN_MASK));
this.delgate = delgate;
delgate.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
selectionDidChange();
}
});
selectionDidChange();
}
protected void selectionDidChange() {
setEnabled(delgate.getSelectedRowCount() > 0);
}
@Override
public void actionPerformed(ActionEvent e) {
delgate.removeSelectedRow();
}
}
好的,没什么特别的,这就是重点。它监视选择状态,因此我们可以 enable/disable 操作,当触发时,我们调用我们的委托来完成实际工作。这将操作与实现分离,因为操作不需要知道正在使用什么类型的 TableModel
或者它可能正在使用什么类型的数据源,它只是想告诉委托它应该携带进行某种操作。
另请注意,我们设置了一个键盘快捷键,可用于 JMenuItem
和助记符支持(按住 Alt 或 选项键)
好的,但这对我们来说真的很重要,或者是...
让我们看看删除操作可能是什么样子...
DeleteRowAction deleteRowAction = new DeleteRowAction(new TableRowDeletable() {
@Override
public int getSelectedRowCount() {
return table.getSelectedRowCount();
}
@Override
public void removeSelectedRow() {
DefaultTableModel model = (DefaultTableModel) table.getModel();
int visibleRowIndex = table.getSelectedRow();
if (visibleRowIndex == -1) {
return;
}
int modelIndex = table.convertRowIndexToModel(visibleRowIndex);
// I'm guessing here, but if you're deleting a row, you should
// use the row data
String recordId = (String) model.getValueAt(modelIndex, 0);
try (PreparedStatement pst = getConnection().prepareStatement("delete from recipe where recipe_name = ?")) {
pst.setString(1, recordId);
// You could check the number of rows effected by this change
pst.executeUpdate();
JOptionPane.showMessageDialog(TestPane.this, "Record deleted", "Success", JOptionPane.INFORMATION_MESSAGE);
model.removeRow(modelIndex);
} catch (SQLException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(TestPane.this, "Failed to delete row from database", "Error", JOptionPane.ERROR_MESSAGE);
}
}
@Override
public void addListSelectionListener(ListSelectionListener listener) {
table.getSelectionModel().addListSelectionListener(listener);
}
@Override
public void removeListSelectionListener(ListSelectionListener listener) {
table.getSelectionModel().removeListSelectionListener(listener);
}
});
现在,这只是一个示例,但基本思想是,我们已经为 MutableTableSupportable
和 TableRowDeletable
接口提供了实现(但 DeleteRowAction
没有关心“如何”),我们已经实现了 removeSelectedRow
功能来从 TableModel
和数据库中删除行。
同样,DeleteRowAction
不关心这是如何实现的,它只是委托责任,所以你可以有多个 DeleteRowAction
s,它们与不同的 TableModel
s 和数据一起工作同时来源
代表团
好的,但是所有这些如何协同工作?嗯,其实,真的很容易,事实上
可运行示例...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import java.sql.*;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JMenuBar menuBar = new JMenuBar();
JFrame frame = new JFrame();
frame.setJMenuBar(menuBar);
frame.add(new TestPane(menuBar));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JTable table;
public TestPane(JMenuBar menuBar) {
setLayout(new BorderLayout());
DefaultTableModel model = new DefaultTableModel(new Object[][]{new Object[]{"Test"}}, new Object[]{"Test"});
table = new JTable(model);
add(new JScrollPane(table));
DeleteRowAction deleteRowAction = new DeleteRowAction(new TableRowDeletable() {
@Override
public int getSelectedRowCount() {
return table.getSelectedRowCount();
}
@Override
public void removeSelectedRow() {
JOptionPane.showMessageDialog(TestPane.this, "Delete the row please", "Debug", JOptionPane.INFORMATION_MESSAGE);
}
@Override
public void addListSelectionListener(ListSelectionListener listener) {
table.getSelectionModel().addListSelectionListener(listener);
}
@Override
public void removeListSelectionListener(ListSelectionListener listener) {
table.getSelectionModel().removeListSelectionListener(listener);
}
});
JMenu actionsMenu = new JMenu("Actions");
actionsMenu.add(deleteRowAction);
menuBar.add(actionsMenu);
JButton deleteButton = new JButton(deleteRowAction);
add(deleteButton, BorderLayout.SOUTH);
}
}
public interface MutableTableSupportable {
public void addListSelectionListener(ListSelectionListener listener);
public void removeListSelectionListener(ListSelectionListener listener);
}
public interface TableRowDeletable extends MutableTableSupportable {
public int getSelectedRowCount();
public void removeSelectedRow();
}
public class DeleteRowAction extends AbstractAction {
private TableRowDeletable delgate;
public DeleteRowAction(TableRowDeletable delgate) {
putValue(SHORT_DESCRIPTION, "Delete the currently selected row");
putValue(MNEMONIC_KEY, KeyEvent.VK_D);
putValue(NAME, "Delete Row");
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, KeyEvent.CTRL_DOWN_MASK));
this.delgate = delgate;
delgate.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
selectionDidChange();
}
});
selectionDidChange();
}
protected void selectionDidChange() {
setEnabled(delgate.getSelectedRowCount() > 0);
}
@Override
public void actionPerformed(ActionEvent e) {
delgate.removeSelectedRow();
}
}
}
nb:此示例删除了数据库支持,因为我没有,而是显示一条消息
好的,让我们快速浏览一下这里的一些有趣的东西...
首先...
JMenuBar menuBar = new JMenuBar();
JFrame frame = new JFrame();
frame.setJMenuBar(menuBar);
frame.add(new TestPane(menuBar));
我们将菜单栏注入到面板中。这样做是为了让面板可以根据需要配置菜单栏。我们可以在这里使用一种类型的工厂或其他委托,但我会把它留给你自己想办法。
下一个...
JMenu actionsMenu = new JMenu("Actions");
actionsMenu.add(deleteRowAction);
menuBar.add(actionsMenu);
JButton deleteButton = new JButton(deleteRowAction);
add(deleteButton, BorderLayout.SOUTH);
我们构建 JMenu
并添加我们的删除行操作并创建一个 JButton
,使用相同的 Action
... 五行代码,我们实际上已经完成很多。我们已经能够设置每个组件显示的文本、工具提示文本、加速键和助记符...尝试手动执行此操作,然后需要更改一些东西(想要支持本地化 - 需要制作一个位置的变化)
但是等等,我们可以做得更多!!
如果我们添加...
InputMap inputMap = table.getInputMap(WHEN_FOCUSED);
ActionMap actionMap = table.getActionMap();
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0), "deleteRow");
actionMap.put("deleteRow", deleteRowAction);
到构造函数的末尾,我们可以为用户提供一个键绑定,这样当JTable
有键盘焦点并且命中他们Delete /Backspace键,也会触发动作!!!
现在我们有四种触发动作的方法:
- 按下按钮
- 打开并触发菜单项
- 使用菜单键盘“加速器”键绑定
- 点击删除键
操作
键绑定可运行示例...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JMenuBar menuBar = new JMenuBar();
JFrame frame = new JFrame();
frame.setJMenuBar(menuBar);
frame.add(new TestPane(menuBar));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JTable table;
public TestPane(JMenuBar menuBar) {
setLayout(new BorderLayout());
DefaultTableModel model = new DefaultTableModel(new Object[][]{new Object[]{"Test"}}, new Object[]{"Test"});
table = new JTable(model);
add(new JScrollPane(table));
DeleteRowAction deleteRowAction = new DeleteRowAction(new TableRowDeletable() {
@Override
public int getSelectedRowCount() {
return table.getSelectedRowCount();
}
@Override
public void removeSelectedRow() {
JOptionPane.showMessageDialog(TestPane.this, "Delete the row please", "Debug", JOptionPane.INFORMATION_MESSAGE);
}
@Override
public void addListSelectionListener(ListSelectionListener listener) {
table.getSelectionModel().addListSelectionListener(listener);
}
@Override
public void removeListSelectionListener(ListSelectionListener listener) {
table.getSelectionModel().removeListSelectionListener(listener);
}
});
JMenu actionsMenu = new JMenu("Actions");
actionsMenu.add(deleteRowAction);
menuBar.add(actionsMenu);
JButton deleteButton = new JButton(deleteRowAction);
add(deleteButton, BorderLayout.SOUTH);
InputMap inputMap = table.getInputMap(WHEN_FOCUSED);
ActionMap actionMap = table.getActionMap();
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0), "deleteRow");
actionMap.put("deleteRow", deleteRowAction);
}
}
public interface MutableTableSupportable {
public void addListSelectionListener(ListSelectionListener listener);
public void removeListSelectionListener(ListSelectionListener listener);
}
public interface TableRowDeletable extends MutableTableSupportable {
public int getSelectedRowCount();
public void removeSelectedRow();
}
public class DeleteRowAction extends AbstractAction {
private TableRowDeletable delgate;
public DeleteRowAction(TableRowDeletable delgate) {
putValue(SHORT_DESCRIPTION, "Delete the currently selected row");
putValue(MNEMONIC_KEY, KeyEvent.VK_D);
putValue(NAME, "Delete Row");
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, KeyEvent.CTRL_DOWN_MASK));
this.delgate = delgate;
delgate.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
selectionDidChange();
}
});
selectionDidChange();
}
protected void selectionDidChange() {
setEnabled(delgate.getSelectedRowCount() > 0);
}
@Override
public void actionPerformed(ActionEvent e) {
delgate.removeSelectedRow();
}
}
}
但这还不是全部!我们还可以向 JToolBar
添加一个按钮,因为,为什么不呢!?