我想擺脫應用程式中的重復代碼。我嘗試了幾種方法,但是當我這樣做時,應用程式并沒有像我預期的那樣作業。只有將相同的代碼放在函式中才會產生效果。
簡而言之,在應用程式中,我可以通過兩種方式洗掉記錄,或者通過按下按鈕或通過指向記錄并使用滑鼠右鍵洗掉它。按鈕洗掉有效,但我不知道如何使滑鼠洗掉具有相同的效果。
用于洗掉表中記錄的按鈕。
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());
}
}
uj5u.com熱心網友回復:
好的,所以這需要稍微轉變思維方式。為了使其真正靈活,您將需要支持諸如“依賴注入”和“委托”之類的概念。
這樣做的原因是,您的“操作”需要大量資訊,但是,我們應該努力使我們的類之間具有低水平的內聚或耦合。例如,您的“操作”不應該關心“如何”洗掉該行,只關心在請求時應該完成。
所以,讓我們從一些基本的委托開始......
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();
}
}
好吧,沒什么特別的,這就是重點。它監視選擇狀態,因此我們可以啟用/禁用操作,當觸發時,我們呼叫我們的委托來完成實際作業。這將動作與實作分離,因為動作不需要知道TableModel正在使用什么型別或它可能正在使用什么型別的資料源,它只是想告訴委托它應該執行某種操作.
另請注意,我們設定了一個鍵盤快捷鍵,可以由JMenuItem和助記符支持使用(按住Alt或Option鍵)
好的,但這對我們來說真的很重要,或者是......
讓我們看看洗掉操作可能是什么樣子......
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);
}
});
Now, this is just an example, but the basic idea is, we've provide implementation for both the MutableTableSupportable and TableRowDeletable interfaces (but the DeleteRowAction doesn't care about the "how") and we've implemented the removeSelectedRow functionality to delete the row from the TableModel and database.
Again, DeleteRowAction doesn't care how this is implemented, it's just delegating that responsibility, so you could have multiple DeleteRowActions which work with different TableModels and data sources all at the same time ??
Delegation ??
Okay, but how would all that work together? Well, actually, really easily in fact
Runnable example...
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: This example removes the database support, as I don't have one and instead displays a message
Okay, lets take a quick look at some of the interesting things here...
Firstly...
JMenuBar menuBar = new JMenuBar();
JFrame frame = new JFrame();
frame.setJMenuBar(menuBar);
frame.add(new TestPane(menuBar));
We inject the menu bar into the panel. This is done so that the panel can configure the menu bar as it needs. We could use a type of factory or another delegate here, but I'll leave that up to you to figure out.
Next...
JMenu actionsMenu = new JMenu("Actions");
actionsMenu.add(deleteRowAction);
menuBar.add(actionsMenu);
JButton deleteButton = new JButton(deleteRowAction);
add(deleteButton, BorderLayout.SOUTH);
We build the JMenu and add our delete row action and create a JButton, using the same Action ... for five lines of code, we've actually done a lot. We've been able to set up the text displayed by each component, the tooltip text, the accelerator key and mnemonic ... try doing that manually, and then need to change something down the track ?? (want to support localisation - need to make changes in one location)
But wait, we can do more!! ??
If we add...
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鍵時,它也會觸發動作!!!
現在我們有四種觸發動作的方法:
- 按下按鈕
- 打開并觸發選單項
- 使用選單鍵盤“加速器”鍵系結
- 敲Delete鍵
行動??
鍵系結可運行示例...
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();
}
}
}
但這還不是全部!我們還可以為 a 添加一個按鈕JToolBar,因為,為什么不呢!?
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/416540.html
標籤:
