2 回答

TA貢獻(xiàn)1801條經(jīng)驗(yàn) 獲得超8個(gè)贊
您應(yīng)該拆分您ActionListener和您的業(yè)務(wù)代碼:您不應(yīng)該執(zhí)行長(zhǎng)時(shí)間運(yùn)行的查詢,ActionListener因?yàn)樗鼤?huì)通過阻止 EDT(事件調(diào)度線程)來凍結(jié)您的應(yīng)用程序。
在處理 Swing(或其他框架,如 Java FX、SWT 等)時(shí),我最好執(zhí)行以下操作:
創(chuàng)建 GUI 組件,例如字段,...
配置或“初始化”布局,即將組件添加到它們的父級(jí)等等
配置任何事件監(jiān)聽器
那將是(如果您愿意,可以將“init”替換為“configure”):
private JCheckBox checkBox;
MyClass() { // constructor
this.init();
}
void init() {
initComponents();
initEventListeners();
}
void initComponents() {
this.checkBox = new JCheckBox("..."); // or in the constructor if you want final field.
// layout for the parent component
this.add(new JLabel("Label 1"));
this.add(checkBox);
}
void initEventListeners() {
this.checkBox.addActionListener(System.out::println);
}
此外,如果附加到 Swing 組件的事件是 lambda 或匿名類,則應(yīng)盡可能簡(jiǎn)單:相反,創(chuàng)建一個(gè)私有方法并使用其引用:
btnSearch.addActionListener(this::searchActionListener);
以及我使用另一個(gè)線程 ( ForkJoinPool.commonPool()) 在 EDT(事件調(diào)度線程)之外執(zhí)行長(zhǎng)時(shí)間運(yùn)行的工作的方法。否則,界面將被凍結(jié)。業(yè)務(wù)方法在外部完成,在另一個(gè)對(duì)象(business此處稱為)中。
應(yīng)該禁用搜索按鈕,否則用戶(在那種情況下)可能會(huì)向按鈕發(fā)送垃圾郵件,從而導(dǎo)致數(shù)據(jù)庫出現(xiàn)不必要的問題......
private void searchActionListener(ActionEvent event) {
btnSearch.setEnabled(false); // user should not be able to search while it's running
// extract Swing data before running outside the EDT
String query = txtSearch.getText()
boolean useName = chkName.isSelected();
boolean useAddress = chkAddress.isSelected();
// ... and so on
// do work OUTSIDE the EDT
ForkJoinPool.commonPool().execute(() -> {
Result result = business.find(query, useName, useAddress);
SwingUtilities.invokeLater(() -> {
processResult(result); // do whatever is needed
btnSearch.setEnabled(true);
});
});
}
如您所見,如果您在chkName事件偵聽器之前創(chuàng)建了 Swing 組件 ( , ...) ,則您可能不會(huì)在方法中引用它們:您應(yīng)該將它們創(chuàng)建為類的字段而不是變量。
否則,您必須在事件偵聽器之前創(chuàng)建它們。
此外,雖然問題中沒有討論,但您應(yīng)該重寫查詢,因?yàn)槟谧⑷?SQL:
"(SELECT " + tableName + "_SID FROM " + tableName + " WHERE " + tableName + "_NM LIKE '%" + txtSearch.getText() + "%') UNION ";
'%" + txtSearch.getText() + "%'應(yīng)該替換為?并且您應(yīng)該使用 PreparedStatement 來傳遞參數(shù)而不是注入它。

TA貢獻(xiàn)1772條經(jīng)驗(yàn) 獲得超6個(gè)贊
我不確定您是否讀過這篇文章,但我會(huì)先閱讀 The Java? Tutorials on Writing Event Listeners。當(dāng)我學(xué)習(xí)如何正確處理 GUI 事件時(shí),本教程對(duì)我?guī)椭艽?。因?yàn)橐幚淼氖录啵?Java 提供了EventListener沒有方法的調(diào)用的主要接口(這就是所謂的標(biāo)記接口)。每個(gè)都JComponent定義了它必須處理的事件類型。例如,JButton對(duì)象關(guān)注的事件集與JFrame對(duì)象不同。
你能做的最好的事情就是理解為什么需要這個(gè) API 的基本前提。GUI 必須是事件驅(qū)動(dòng)的,因?yàn)闆]有有效的方法可以在操作發(fā)生的那一刻捕獲用戶交互。例如,一個(gè)JButton對(duì)象必須至少監(jiān)聽“點(diǎn)擊”事件。這對(duì)你來說應(yīng)該是顯而易見的。但還有一些您可能沒有想到的其他事件。例如,將鼠標(biāo)懸停在按鈕上以顯示工具提示。
對(duì)于你的問題,
如果偵聽器使用其他對(duì)象,則必須在偵聽器代碼之前創(chuàng)建該對(duì)象......我應(yīng)該為此做什么?
有幾種方法可以處理這個(gè)問題。我將向您展示非常簡(jiǎn)單的案例,希望您可以使用這些案例進(jìn)行擴(kuò)展。假設(shè)您有一個(gè)帶有兩個(gè)按鈕的面板,OK 和 Cancel。顯然,您知道這兩個(gè)按鈕在單擊時(shí)將執(zhí)行不同的功能。對(duì)于這個(gè)例子,他們將要做的工作是無關(guān)緊要的。因此,我將在單擊時(shí)打印出一些消息。下面的代碼片段僅顯示相關(guān)部分。要處理按鈕點(diǎn)擊,您必須ActionListener向每個(gè)按鈕添加 。
public class MyActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
JButton button = (JButton)e.getSource();
String name = button.getName(); // Assuming you set "OK" and "Cancel" as the names
if (name.equals("OK")
System.out.println("I will comply with your command!");
else
System.out.println("You cancelled your request.");
}
}
然后,您可以像這樣向您的按鈕添加一個(gè)偵聽器......
MyActionListener listener = new MyActionListener();
cancelBtn.addActionListener(listener);
okBtn.addActionListener(listener);
該解決方案應(yīng)該可以正常工作,但擴(kuò)展性不是很好。如果您要向您的應(yīng)用程序添加更多按鈕,那么只有一個(gè)這樣的偵聽器是不好的,因?yàn)槟膫陕犉鲿?huì)變得過度工作。稍微好一點(diǎn)的解決方案是為每個(gè)實(shí)例提供自己的偵聽器。您可以利用匿名類來做到這一點(diǎn)。這是如何做:
cancelBtn.addActionListener(new MyActionListener(){
public void actionPerformed(ActionEvent e) {
System.out.println("I will comply with your command!");
}
});
okBtn.addActionListener(new MyActionListener(){
public void actionPerformed(ActionEvent e) {
System.out.println("You cancelled your request.");
}
});
有些人不太喜歡匿名類,因?yàn)樗鼤?huì)影響代碼的可讀性。我碰巧喜歡這樣一個(gè)事實(shí),即每個(gè)對(duì)象的實(shí)例都有自己的個(gè)性化偵聽器,它可以準(zhǔn)確地完成對(duì)象實(shí)例在操作發(fā)生時(shí)需要完成的工作。
我認(rèn)為這種方法應(yīng)該適用于您的情況。還有其他方法,但我認(rèn)為您應(yīng)該開始使用這種簡(jiǎn)單的方法,直到您獲得更多關(guān)于如何處理事件的知識(shí)。讓我知道你的想法。
添加回答
舉報(bào)