我编写了一个 Swing Worker,其任务是计算一些文本统计数据,然后用结果更新 EDT 中的 GUI 元素。
经过一些实验,我发现你应该只在 done()
中操作 GUI。方法,不在doInBackground()
中。为了实现这一目标,我对工作人员进行了改造,使其具有返回值 String[]
,我应该能够用 get()
捕获它。
除了一些publish()
方法,您可能会发现来自 doInBackground()
的一些错误调用方法直接操作 GUI,如果您认为我的问题可能是由此引起的 - 请告诉我。
package my.worker;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import my.tools.CountKeywords;
import my.tools.FilterStopwords;
import my.tools.KeywordSuggestion;
import my.tools.RelevanceRanking;
public class ProcessDatabaseWorker extends SwingWorker<String[], String> {
private final JLabel debugJLabel;
private final JLabel infoJLabel;
private final JLabel warnJLabel;
private final JLabel errorJLabel;
private final JLabel infoboxJLabel;
private final String databaseString;
private final JProgressBar jProgressBar;
private final JComboBox keywordJComboBox;
private int percent;
private int index;
public ProcessDatabaseWorker(JProgressBar jProgressBar, String databaseString,
JLabel debugJLabel, JLabel errorJLabel, JLabel warnJLabel,
JLabel infoJLabel, JLabel infoboxJLabel,
JComboBox keywordJComboBox) {
this.percent = 1;
this.jProgressBar = jProgressBar;
this.databaseString = databaseString;
this.debugJLabel = debugJLabel;
this.errorJLabel = errorJLabel;
this.infoJLabel = infoJLabel;
this.warnJLabel = warnJLabel;
this.infoboxJLabel = infoboxJLabel;
this.keywordJComboBox = keywordJComboBox;
}
@Override
protected String[] doInBackground() throws Exception {
FilterStopwords fs = new FilterStopwords();
CountKeywords ck = new CountKeywords();
RelevanceRanking rr = new RelevanceRanking();
HashMap<String, Integer> nKeywords = new HashMap();
Map<String, TreeSet<Map.Entry<String, Double>>> keywordsPerDocument = new HashMap();
String replace = databaseString.toLowerCase();
String splitter = ("\\n");
String[] documentLines = replace.split(splitter);
int N = documentLines.length;
publish("Stopworte werden gefiltert...", "10");
String[] completeFilteredText = fs.filterStopwords(replace);
publish("Keywords werden gezählt...", "20");
HashMap<String, Integer> completeKeywords = ck.countKeywords(completeFilteredText);
index = 0;
percent = 1;
final double oneLinePercent = N / 100;
final double oneKeywordPercent = completeKeywords.size() / 100;
completeKeywords.forEach((String key, Integer value) -> {
int n = 0;
key = String.valueOf(key).trim();
for (String line : documentLines) {
String[] lineWords = line.split(" ");
for (String word : lineWords) {
word = word.trim();
if (word.equals(key)) {
n++;
nKeywords.put(key, n);
}
}
}
index++;
if (index == oneKeywordPercent) {
percent++;
publish("Zählung...", String.valueOf(percent));
index = 0;
}
});
publish("Keywords werden geranked...", "40");
index = 0;
percent = 1;
for (String documentLine : documentLines) {
TreeSet<Map.Entry<String, Double>> rankedKeywords;
String[] lineFilteredWords = fs.filterStopwords(documentLine);
HashMap<String, Integer> keywords = ck.countKeywords(lineFilteredWords);
rankedKeywords = rr.rankKeywords(keywords, lineFilteredWords, N, nKeywords);
keywordsPerDocument.put(documentLine, rankedKeywords);
index++;
if (index == oneLinePercent) {
percent++;
publish("Ranking...", String.valueOf(percent));
index = 0;
}
}
publish("Keyword-Vorschläge werden generiert...", "70");
KeywordSuggestion ks = new KeywordSuggestion();
TreeSet<Map.Entry<String, Double>> keywordSuggestionsTree = ks.keywordSuggestion(keywordsPerDocument);
String[] keywordSuggestionsArray = new String[keywordSuggestionsTree.size()];
index = 0;
int index2 = 0;
double onePercent = keywordSuggestionsTree.size() / 100;
percent = 1;
publish("Keyword-Vorschläge werden generiert...", "75");
for (Map.Entry<String, Double> entry : keywordSuggestionsTree) {
double round = round(entry.getValue(), 2);
keywordSuggestionsArray[index2] = round + " - " + entry.getKey();
index2++;
index++;
if (index == onePercent) {
percent++;
publish("Keywords...", String.valueOf(percent));
index = 0;
}
}
keywordJComboBox.removeAllItems();
for (String entry : keywordSuggestionsArray) {
publish("Keyword-Vorschläge werden befüllt...", "80");
}
这是返回 get() 所需的值的行...
return keywordSuggestionsArray;
}
public static double round(double value, int places) {
if (places < 0) {
throw new IllegalArgumentException();
}
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.doubleValue();
}
@Override
public void process(List<String> s) {
infoboxJLabel.setText(s.get(0));
jProgressBar.setValue(Integer.valueOf(s.get(1)));
}
@Override
protected void done() {
try {
这里是抛出 NullPointerException 的地方...
String[] get = get();
for (String entry : get) {
keywordJComboBox.addItem(entry);
}
} catch (InterruptedException | ExecutionException ex) {
Logger.getLogger(ProcessDatabaseWorker.class.getName()).log(Level.SEVERE, null, ex);
}
publish("Verarbeitung der Daten abgeschlossen!", "100");
}
}
有关更多信息,请参阅完整跟踪:
Apr 14, 2016 10:40:06 AM my.worker.ProcessDatabaseWorker done
SCHWERWIEGEND: null
java.util.concurrent.ExecutionException: java.lang.NullPointerException
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at javax.swing.SwingWorker.get(SwingWorker.java:602)
at my.worker.ProcessDatabaseWorker.done(ProcessDatabaseWorker.java:197)
at javax.swing.SwingWorker$5.run(SwingWorker.java:737)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(SwingWorker.java:832)
at sun.swing.AccumulativeRunnable.run(AccumulativeRunnable.java:112)
at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionPerformed(SwingWorker.java:842)
at javax.swing.Timer.fireActionPerformed(Timer.java:313)
at javax.swing.Timer$DoPostEvent.run(Timer.java:245)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Caused by: java.lang.NullPointerException
at my.logfileanalyzer.LogFileAnalyzerGUI.keywordJComboBoxItemStateChanged(LogFileAnalyzerGUI.java:830)
at my.logfileanalyzer.LogFileAnalyzerGUI.access$2400(LogFileAnalyzerGUI.java:48)
at my.logfileanalyzer.LogFileAnalyzerGUI$15.itemStateChanged(LogFileAnalyzerGUI.java:329)
at javax.swing.JComboBox.fireItemStateChanged(JComboBox.java:1223)
at javax.swing.JComboBox.selectedItemChanged(JComboBox.java:1271)
at javax.swing.JComboBox.contentsChanged(JComboBox.java:1330)
at javax.swing.JComboBox.intervalRemoved(JComboBox.java:1352)
at javax.swing.AbstractListModel.fireIntervalRemoved(AbstractListModel.java:179)
at javax.swing.DefaultComboBoxModel.removeAllElements(DefaultComboBoxModel.java:174)
at javax.swing.JComboBox.removeAllItems(JComboBox.java:771)
at my.worker.ProcessDatabaseWorker.doInBackground(ProcessDatabaseWorker.java:165)
at my.worker.ProcessDatabaseWorker.doInBackground(ProcessDatabaseWorker.java:43)
at javax.swing.SwingWorker$1.call(SwingWorker.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at javax.swing.SwingWorker.run(SwingWorker.java:334)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
现在,对于我的问题:我没有使用正确的工作程序部分或者我的程序逻辑哪里出了问题?正如您所看到的,我对使用 Swing Worker 和线程进行编程非常陌生,所以我确信有一个简单的解决方案可以解决由于缺乏经验而导致的简单错误。
此外,如果我的程序需要任何其他部分,请告诉我,以便更好地了解正在发生的情况。
编辑:错误正是用户 Moh-Aw 所描述的地方 - 编辑我的代码,如下修复它:
private void keywordJComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {
if (keywordJComboBox.getItemCount() != 0){
if (!((String) keywordJComboBox.getSelectedItem()).equals("")) {
String selected = (String) keywordJComboBox.getSelectedItem();
String[] blubb = selected.split(" ");
searchJTextField.setText(blubb[2]);
}
}
}
编辑:关于可能的重复 - 我很确定这篇文章是。老实说,我认为这是 swing workers
的错误实现,并不像实际那么简单 - 所以这篇文章最好关闭 ^^
最佳答案
问题出在 LogFileAnalyzerGUI
类的第 830 行。 keywordJComboBox
的 itemStateChanged()
方法导致 NullPointerException
此方法由您的 ProcessDatabaseWorker
在 keywordJComboBox.removeAllItems()
通过删除所有项目,ItemState
更改为 DESELECTED。
方法itemStateChanged()
再次运行,但ComboBox
中不再有任何项目,从而导致NPE。
关于java - SwingWorker did() 方法用 get() 抛出 nullpointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36618502/