gpt4 book ai didi

带有 JDialog 的 Java SwingWorker 在 JDBC 网络操作期间显示 JProgressBar

转载 作者:行者123 更新时间:2023-11-30 07:14:39 27 4
gpt4 key购买 nike

我有一个带有按钮的框架,当它被按下时,会显示一个带有进度条的 JDialog 并且正在使用 jdbc 驱动程序获取一些数据(正在更新进度条)。我需要一个取消按钮,所以我花了一些时间弄清楚如何连接所有东西。它似乎工作,但我真诚地不确定这种方式是否有任何好处。如果有人有空闲时间,请检查此代码并告诉我它是否有任何问题 - 主要是整个 SwingWorker 和取消的东西。

在我的电脑 (linux) 上,不成功的网络连接尝试(someNetworkDataFetching 方法)需要整整一分钟才能超时,当我尝试创建新的?

注意:运行这段代码需要mysql jdbc驱动库。

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class Test extends JFrame {

private JProgressBar progressBar = new JProgressBar();
private JLabel label = new JLabel();
private DataFetcherProgress dfp;

/**
* This class holds retrieved data.
*/
class ImportantData {

ArrayList<String> chunks = new ArrayList<>();

void addChunk(String chunk) {
// Add this data
chunks.add(chunk);
}
}

/**
* This is the JDialog which shows data retrieval progress.
*/
class DataFetcherProgress extends JDialog {

JButton cancelButton = new JButton("Cancel");
DataFetcher df;

/**
* Sets up data fetcher dialog.
*/
public DataFetcherProgress(Test owner) {
super(owner, true);
getContentPane().add(progressBar, BorderLayout.CENTER);
// This button cancels the data fetching worker.
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
df.cancel(true);

}
});
getContentPane().add(cancelButton, BorderLayout.EAST);
setLocationRelativeTo(owner);
setSize(200, 50);
df = new DataFetcher(this);
}

/**
* This executes data fetching worker.
*/
public void fetchData() {
df.execute();
}
}

class DataFetcher extends SwingWorker<ImportantData, Integer> {

DataFetcherProgress progressDialog;

public DataFetcher(DataFetcherProgress progressDialog) {
this.progressDialog = progressDialog;
}

/**
* Update the progress bar.
*/
@Override
protected void process(List<Integer> chunks) {
if (chunks.size() > 0) {
int step = chunks.get(chunks.size() - 1);
progressBar.setValue(step);
}
}

/**
* Called when worker finishes (or is cancelled).
*/
@Override
protected void done() {
System.out.println("done()");
ImportantData data = null;
try {
data = get();
} catch (InterruptedException | ExecutionException | CancellationException ex) {
System.err.println("done() exception: " + ex);
}
label.setText(data != null ? "Retrieved data!" : "Did not retrieve data.");
progressDialog.setVisible(false);
}

/**
* This pretends to do some data fetching.
*/
private String someNetworkDataFetching() throws SQLException {
DriverManager.getConnection("jdbc:mysql://1.1.1.1/db", "user", "pass");
// Retrieve data...
return "data chunk";
}

/**
* This tries to create ImportantData object.
*/
@Override
protected ImportantData doInBackground() throws Exception {
// Show the progress bar dialog.
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
dfp.setVisible(true);
}
});

ImportantData data = new ImportantData();
try {
int i = 0;
// There is a network operation here (JDBC data retrieval)
String chunk1 = someNetworkDataFetching();
if (isCancelled()) {
System.out.println("DataFetcher cancelled.");
return null;
}
data.addChunk(chunk1);
publish(++i);

// And another jdbc data operation....
String chunk2 = someNetworkDataFetching();
if (isCancelled()) {
System.out.println("DataFetcher cancelled.");
return null;
}
data.addChunk(chunk2);
publish(++i);
} catch (Exception ex) {
System.err.println("doInBackground() exception: " + ex);
return null;
}
System.out.println("doInBackground() finished");
return data;
}
}

/**
* Set up the main window.
*/
public Test() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
label.setHorizontalAlignment(SwingConstants.CENTER);
getContentPane().add(label, BorderLayout.CENTER);
// Add a button starting data fetch.
JButton retrieveButton = new JButton("Do it!");
retrieveButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
fetchData();
}
});
getContentPane().add(retrieveButton, BorderLayout.EAST);
setSize(400, 75);
setLocationRelativeTo(null);
progressBar.setMaximum(2);
}

// Shows new JDialog with a JProgressBar and calls its fetchData()
public void fetchData() {
label.setText("Retrieving data...");
dfp = new DataFetcherProgress(this);
dfp.fetchData();
}

public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
// Use jdbc mysql driver
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
return;
}

// Show the Frame
new Test().setVisible(true);
}
});

}
}

最佳答案

我可能做的唯一不同的事情是不在 doInBackground 方法中使用 SwingUtilities.invokeLater 来显示对话框,而是可能使用 PropertyChangeListener 以监视对 state 属性 worker 的更改。

我还会使用 PropertyChangeListener 来监视对 worker 的 progress 属性的更改。我不使用 publish 来指示进度更改,而是使用 setProgress 方法(以及 PropertyChangeListener 中的 getProgress)

例如... java swingworker thread to update main Gui

我可能还会考虑在 JPanel 上创建 UI 并将其添加到 JDialog 而不是从 JDialog 扩展目录,因为它会提供以其他方式重新使用面板的机会,如果您愿意...

关于带有 JDialog 的 Java SwingWorker 在 JDBC 网络操作期间显示 JProgressBar,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18370267/

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