gpt4 book ai didi

java - 在 SwingWorker 中调用 super.approveSelection()

转载 作者:行者123 更新时间:2023-11-30 09:24:30 25 4
gpt4 key购买 nike

我有一个自定义的 JFileChooser

它的 approveSelection() 方法稍作修改:

public void approveSelection()
{
File file = getSelectedFile();

changeGui();

final Object a = makeALongCalcualtion(file);

if (a != null)
{
super.approveSelection();

SwingWorker<Document, Void> open = new SwingWorker<Document, Void>()
{
@Override
protected Document doInBackground() throws Exception
{
return createADocument(a);
}

@Override
protected void done()
{
try
{
if(get() != null)
{
changeGui();
}

else
{
//TODO error message
changeGui();
}
}

catch (InterruptedException | ExecutionException e)
{
//TODO error message
changeGui();
}
}
};

open.execute();
}

else
{
//TODO error message
changeGui();
}
}

changeGui() 方法将 JProgressBar 设置为不确定并使用新字符串更新 JLabel。

如果提供给 makeALongCalcualtion(file) 的文件类型无效,它将返回 null,否则返回传递给 SwingWorker 的信息,SwingWorker 可以使用它在程序中实际创建文件的表示(Document 对象) .

但是,这并不能正常工作,因为 makeALongCalcualtion(file) 没有在 SwingWorker 方法中调用,这会阻止 EDT。

为了解决这个问题,我必须在 SwingWorker 中调用 makeALongCalcualtion(file)。我可以毫无问题地将那部分代码移动到 SwingWorker 中,但随后我将不得不(由于我的代码逻辑)将 super.approveSelection() 与其一起移动。

所以最重要的是,对于这种特定情况,我如何从 doInBackground() 中调用 super.approveSelection()?

//更多信息

应该发生什么:

  1. 用户选择并打开一个文件
  2. JLabel 和 JProgressBar 已更新,不确定的进度开始播放。
  3. 如果 makeALongCalcualtion(file) 返回空值,用户会收到一个错误窗口警告,但 JFileChooser 仍然打开,从而可以在错误窗口关闭时再次选择。
  4. 否则,调用 super.approveSelection(),允许选择器关闭。
  5. 已创建文档(但如果出现问题,创建文档的方法将返回 null)。
  6. 如果一切正常,JLabel 更新并停止 progressBar 动画(不确定设置为 false)。
  7. 如果出现问题,会发生与第 6 步相同的事情,只是 JLabel 中的消息不同。

发生了什么:

  1. 相同
  2. 相同
  3. 相同,但当 makeALongCalculation(file);开始,progressBar 卡住。
  4. 相同
  5. 相同
  6. 相同,但动画没有停止(因为进度条被卡住),只有卡住的“图片”被移除并且进度条返回到它之前的状态。
  7. 相同

编辑

我对我的程序做了一些改动,现在我有了这个:

批准选择():

public void approveSelection()
{
File file = getSelectedFile();

Main.getStatusBar().startOpen();

final WorkOpen open = new WorkOpen(file);

open.execute();

open.addPropertyChangeListener(new PropertyChangeListener()
{
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("state".equals(evt.getPropertyName())) {
if (evt.getNewValue().equals("DONE"))
{
if (open.failed())
{
//TODO error message
Main.getStatusBar().endOpen(false);
}

else
{
Main.getStatusBar().endOpen(true);
}
}
}
}
});
}

Swing worker :

class WorkOpen extends SwingWorker<Document, Void>
{
boolean failed = false;
File file;

public boolean failed()
{
return failed;
}

@Override
protected Document doInBackground() throws Exception
{
ArrayList<String> data = Opener.extractData(file);

if (data != null)
{
//My little path/name/similar managing system
FileComplex fullPath = new FileComplex(file.toString());

return Opener.createDocument(fullPath.getFullName(), fullPath.getFullPath(), data);
}

else
{
failed = true;
return null;
}
}

@Override
protected void done()
{
try
{
if(get() != null)
{
Main.addDocument(get());
}
}

catch (InterruptedException | ExecutionException e)
{
failed = true;
}
}

WorkOpen(File file)
{
this.file = file;
}
}

现在的问题是在哪里调用 super.approveSelection()。它必须等待 worker 完成执行,但我无法从属性更改监听器中调用它。

在这里做什么?

编辑 2

正如 HovercraftFullOfEels 所建议的,我修复了我的代码,它编译并运行了。但是 JProgressBar 卡住的问题仍然存在。另外,我不得不介绍一些我不知道是否应该拥有的东西:

private void superApproveSelection()
{
super.approveSelection();
}

public void approveSelection()
{
final File file = getSelectedFile();

class OpenWorker extends SwingWorker<Boolean, Void>
{
Document document;

Document getDocument()
{
return document;
}

@Override
protected Boolean doInBackground() throws Exception
{
ArrayList<String> data = Opener.extractData(file);

if (data != null)
{
//I had to start the progressBar here, because if invalid
//file was selected (extractData(file) returns null if it was),
//nothing should happen (maybe an error
//window later, handled with a new Runnable() same as this:
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
Main.getStatusBar().startOpen();
}
});

FileComplex fullPath = new FileComplex(file.toString());

document = Opener.createDocument(fullPath.getFullName(), fullPath.getFullPath(), data);

return true;
}

else
{
return false;
}
}
};

final OpenWorker opener = new OpenWorker();

opener.addPropertyChangeListener(new PropertyChangeListener()
{
@Override
public void propertyChange(PropertyChangeEvent evt)
{
if ("state".equals(evt.getPropertyName()))
{
if (evt.getNewValue() == SwingWorker.StateValue.DONE)
{
if(opener.getDocument() != null)
{
superApproveSelection();
Main.addDocument(opener.getDocument());
Main.getStatusBar().endOpen(true);
}

else
{
try
{
//I'm retrieveing doInBackground()'s value to see if
//progressBar needs stoping (it also displays some
//text, so it must not be called unless the
//progressBar was started).
if (opener.get())
{
Main.getStatusBar().endOpen(false);
}
}

catch (InterruptedException | ExecutionException e)
{
//TODO error something went wrong
}
}
}
}
}
});

opener.execute();
}

最佳答案

"In order to fix the problem, I would have to call makeALongCalcualtion(file) within a SwingWorker. I could move that part of the code into the SwingWorker without any problems, but then I would have to (due to my code logic) move super.approveSelection() along with it."

不,完全不是这样。 super.approveSelection() 不必在 SwingWorker 内部调用。

为什么不简单地创建一个 SwingWorker,向其添加一个 PropertyChangeListener,并在 SwingWorker 的状态完成时调用 super.approveSelection()(如果有指示)?

好的,下面是我的示例。解释如下:

import java.awt.*;
import java.awt.Dialog.ModalityType;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.Scanner;
import java.util.concurrent.ExecutionException;

import javax.swing.*;
import javax.swing.text.*;

@SuppressWarnings("serial")
public class ApproveSelectionTest extends JPanel {
private JTextArea textArea = new JTextArea(30, 60);

public ApproveSelectionTest() {
textArea.setEditable(false);
textArea.setFocusable(false);

JPanel btnPanel = new JPanel();
btnPanel.add(new JButton(new MyGetFileAction("Get Text File Text")));

setLayout(new BorderLayout());
add(new JScrollPane(textArea), BorderLayout.CENTER);
add(btnPanel, BorderLayout.PAGE_END);
}

private class MyGetFileAction extends AbstractAction {
public MyGetFileAction(String text) {
super(text);
}

public void actionPerformed(java.awt.event.ActionEvent arg0) {
MyFileChooser myFileChooser = new MyFileChooser();
int result = myFileChooser.showOpenDialog(ApproveSelectionTest.this);
if (result == JFileChooser.APPROVE_OPTION) {
Document doc = myFileChooser.getDocument();
textArea.setDocument(doc);
}
};
}

private static void createAndShowGui() {
ApproveSelectionTest mainPanel = new ApproveSelectionTest();

JFrame frame = new JFrame("ApproveSelectionTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

@SuppressWarnings("serial")
class MyFileChooser extends JFileChooser {
private WorkOpen workOpen = null;
private JDialog progressDialog = null;

public MyFileChooser() {
}

@Override
public void approveSelection() {
JProgressBar progBar = new JProgressBar();
progBar.setIndeterminate(true);
Window win = SwingUtilities.getWindowAncestor(this);
progressDialog = new JDialog(win, "Checking File", ModalityType.APPLICATION_MODAL);
progressDialog.getContentPane().add(progBar);
progressDialog.pack();
progressDialog.setLocationRelativeTo(null);


File file = getSelectedFile();

workOpen = new WorkOpen(file);

workOpen.addPropertyChangeListener(new PropertyChangeListener() {

@Override
public void propertyChange(PropertyChangeEvent pcEvt) {
if (SwingWorker.StateValue.DONE == pcEvt.getNewValue()) {
if (progressDialog != null) {
progressDialog.dispose();
}

try {
boolean bool = workOpen.get().booleanValue();
if (bool) {
superApproveSelection();
} else {
JOptionPane.showMessageDialog(MyFileChooser.this, "Invalid File Chosen");
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
});

workOpen.execute();
progressDialog.setVisible(true);

}

// ****** this is key *****
private void superApproveSelection() {
super.approveSelection();
}

public Document getDocument() {
if (workOpen == null) {
return null;
} else {
return workOpen.getDocument();
}
}
}

class WorkOpen extends SwingWorker<Boolean, Void> {
private static final long SLEEP_TIME = 4 * 1000;
private Document document = null;
private File file = null;

public WorkOpen(File file) {
this.file = file;
}

@Override
protected Boolean doInBackground() throws Exception {
if (file == null || !file.exists()) {
return Boolean.FALSE;
}
Thread.sleep(SLEEP_TIME);
String fileName = file.getName();
if (fileName.contains(".txt")) {
Scanner scan = new Scanner(file);
StringBuilder stringBuilder = new StringBuilder();
while (scan.hasNextLine()) {
stringBuilder.append(scan.nextLine() + "\n");
}

document = new PlainDocument();
document.insertString(0, stringBuilder.toString(), null);
return Boolean.TRUE;
}
return Boolean.FALSE;
}

public Document getDocument() {
return document;
}

}

示例中的解释和要点:

  • 这个例子的表现非常简单。您选择一个文件,如果该文件存在并且名称中包含“.txt”,那么它会读入文档并将文本显示在 JTextField 中。
  • 否则它会显示警告消息但会显示 JFileChooser
  • 可能是关键点:我已经为我的 MyFileChooser 类提供了一个私有(private)的 superApproveSelection() 方法,我的 PropertyChangeListener 可以调用该方法。这会将 super 的 approveSelection() 方法暴露给内部类,这是您遇到的问题之一。
  • 调用代码的顺序在我的 approveSelection() 覆盖中很重要。
  • 在这个方法中,我首先创建了我的 JProgressBar 及其对话框,但还没有立即显示它。它确实不必先创建,但肯定需要最后显示。
  • 我创建了我的 SwingWorker workOpen,但尚未执行它。
  • 我在执行 SwingWorker 之前将我的 PropertyChangeListener 添加到 SwingWorker。
  • 然后我执行我的 SwingWorker
  • 然后我用不确定的 JProgressBar 显示我的模态 JDialog。
  • 我的 SwingWorker 的结构使其 doInBackground 返回 boolean 值,而不是文档。
  • 我让它创建一个(非常简单的)Document if all works OK 保存文本文件的内容,并设置一个可通过 getter 方法获取的私有(private)“doc”字段,然后让 doInBackground 返回 Boolean.TRUE,如果一切正常。
  • 我已经为我的 doInBackground 提供了一个 Thread.sleep(4000) 只是为了假装它的 Action 需要很多时间。你的当然不会有这个。
  • 在 PropertyChangeListener 中,如果 SwingWorker 已完成,我将处理进度条对话框,然后在 SW 上调用 get() 以获得 boolean 结果。
  • 如果为 Boolean.TRUE,则调用上述 superApproveSelection() 方法。
  • 否则显示错误信息。请注意,由于未调用 super 的 approveSelection(),文件选择器对话框仍然显示。
  • 如果调用 approveSelection,则显示我的文件选择器对话框的代码将获得适当的返回值,将从文件选择器中提取文档并将文档显示在 JTextArea 中。

关于java - 在 SwingWorker 中调用 super.approveSelection(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15672905/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com