我第一次使用Swing来创建一个简单的GUI.它包含一个JFrame我放置了一个单独的JButton,当点击它时,调用一些其他代码,大约需要.3秒钟返回.
就在调用此代码之前actionPerformed(),我想更新按钮上的文本以通知用户正在进行处理.我的问题是,直到3秒钟的呼叫返回后,按钮上的文字才会更新.我希望在通话过程中出现更新的文本,然后我会将其更改回来.
当我点击按钮时,调用repaint()on JButton不会执行任何操作并在JFrame结果中调用它Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException.
我正在使用这个练习作为教学工具来帮助我学习一些Java GUI编程概念.我正在寻找的是一般性的理解,而不是一个特定问题的详细解决方案.我希望编码这个"正确"将教会我如何处理未来的多线程问题.如果这对于这个论坛来说太笼统了,那么它可能属于程序员吗?
我正在模拟读卡器.它有一个GUI,允许我们将卡加载到料斗中并按下Start等,但它的主要"客户端"是CPU,在单独的线程上运行并请求卡.
读卡器保持单个缓冲区.如果卡片请求进入且缓冲区为空,读卡器必须从料斗读取卡片(需要1/4秒,这是1962年).在将卡读入缓冲区后,读卡器将缓冲区发送到CPU,并在下一个请求之前立即启动另一个缓冲区加载操作.
如果不仅缓冲器是空的,而且料斗中没有卡,那么我们必须等到操作员将料斗放入料斗并按下Start(它始终启动缓冲加载操作).
在我的实现中,卡请求以invokeLater() Runnables在EDT上排队的形式发送到读卡器.在myRunnable.run()时间,无论是一个缓冲器将可用(在这种情况下,我们可以将其发送到CPU和开球另一个缓冲器负载操作),或缓冲区将是空的.如果它是空的怎么办?
两种可能性:(a)飞行中已经有缓冲加载操作,或(b)卡漏斗是空的(或尚未启动).在任何一种情况下,让EDT等待是不可接受的.工作(和等待)必须在后台线程上完成.
为了简单起见,我尝试生成一个SwingWorker来响应每个卡请求,而不管缓冲区的状态如何.伪代码是:
SwingWorker worker = new SwingWorker<Void, Void>() {
public Void doInBackground() throws Exception {
if (buffer.isEmpty()) {
/*
* fill() takes 1/4 second (simulated by Thread.sleep)
* or possibly minutes if we need to have another
* card deck mounted by operator.
*/
buffer.fill();
}
Card card = buffer.get(); // empties buffer
/*
* Send card to CPU
*/
CPU.sendMessage(card); // <== (A) put card in msg queue …Run Code Online (Sandbox Code Playgroud) 我想等待我的SwingWorker完成工作,然后我想执行另一个SwingWorker.在这种情况下,Encrypteer3是一个扩展SwingWorker的类.
我的代码:
input = txtTekst.getText();
key = txtKey.getText();
System.out.println("thread1 start");
Encrypteer3 a = new Encrypteer3();
a.execute();
while(a.isDone()==false){
// do nothing
}
input = output;
key = txtKey1.getText();
System.out.println("thread2 start");
Encrypteer3 b = new Encrypteer3();
b.execute();
while(b.isDone()==false){
// do nothing
}
Run Code Online (Sandbox Code Playgroud)
这使我的GUI冻结并使用了大量的CPU(java在执行时使用了大约95%的CPU).我认为问题是它不断检查线程是否已完成,这是什么使它如此CPU密集.
SwingWorker类上没有join()方法.如何减少CPU占用?
可能这是微不足道的,我很难理解SwingWorker上的简单文档.
这是复制粘贴的内容
工作流程
SwingWorker的生命周期涉及三个线程:
当前线程:在此线程上调用execute()方法.它安排SwingWorker在工作线程上执行并立即返回.可以等待SwingWorker使用get方法完成.
工作线程:在此线程上调用doInBackground()方法.这是所有背景活动应该发生的地方.要通知PropertyChangeListeners有关绑定属性的更改,请使用firePropertyChange和getPropertyChangeSupport()方法.默认情况下,有两个绑定属性:状态和进度.
事件调度线程:此线程上发生所有与Swing相关的活动.SwingWorker调用process和done()方法并通知此线程上的任何PropertyChangeListeners.
通常,Current线程是Event Dispatch Thread.
-
工作线程不是EDT,因此doInBackground()中的代码不能访问GUI元素.我的理解是否正确?
背景:我们有使用SwingWorker的小代码,但有doInBackground()创建FileChooser并调用setCurrentDirectory().我怀疑这导致我异常几乎与 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6637181(11-Closed,not a defect)相同
我正在设计一个Java GUI驱动的应用程序,该应用程序运行许多单独的任务,每个任务都在自己的SwingWorker扩展类中.这是我使用的正常设计,以便在自己的线程上运行任务,并且仍然可以让EDT免费更新GUI.每个SwingWorker都使用Executors.newCachedThreadPool在自己的线程上启动.
但是,在一个特定的类中,有一个任务需要相当长的时间来处理.该任务包含一个for循环,最多可执行六次计算.
我已经考虑过在自己的线程中实现六个计算中的每一个以加快处理时间,但我不确定实现它的最佳方法.
是否可以扩展SwingWorker并实现Runnable,然后在for循环中使用void Run()方法,每次启动一个新的Thread,或者使用cachedThreadPool.
或者我最好只使用标准的Thread()实现?
任何建议或意见将不胜感激.
提前致谢
玩笑
我想创建一个SwingWorker具有最终和中间结果类型的具体类void.我写了以下代码:
class AnswerWorker extends SwingWorker<void, void> {
protected void doInBackGround() {
System.out.println("what is your problem!!");
}
}
Run Code Online (Sandbox Code Playgroud)
这给了我以下错误:
Multiple markers at this line-
Syntax error on token "void", Dimensions expected after this token.
Syntax error on token "void", Dimensions expected after this token.
Run Code Online (Sandbox Code Playgroud)
然而,当我将代码更改void为Void(即小v到大写V)时,它工作正常,尽管我仍然被迫return null;在doInBackground()方法结束时.
为什么是这样?我知道Void是一个java.lang包中的类,但是文档没有说太多关于它的内容(至少我不能遵循它:p)
Thanx提前!!
假设我有一个类定义了要完成的大块工作,可以产生几个已检查的异常.
class WorkerClass{
public Output work(Input input) throws InvalidInputException, MiscalculationException {
...
}
}
Run Code Online (Sandbox Code Playgroud)
现在假设我有一个可以调用这个类的GUI.我使用SwingWorker委派任务.
Final Input input = getInput();
SwingWorker<Output, Void> worker = new SwingWorker<Output, Void>() {
@Override
protected Output doInBackground() throws Exception {
return new WorkerClass().work(input);
}
};
Run Code Online (Sandbox Code Playgroud)
如何处理从SwingWorker抛出的可能异常?我想区分我的worker类的异常(InvalidInputException和MiscalculationException),但ExecutionException包装器使事情变得复杂.我只想处理这些异常 - 不应该捕获OutOfMemoryError.
try{
worker.execute();
worker.get();
} catch(InterruptedException e){
//Not relevant
} catch(ExecutionException e){
try{
throw e.getCause(); //is a Throwable!
} catch(InvalidInputException e){
//error handling 1
} catch(MiscalculationException e){
//error handling 2
}
}
//Problem: Since a Throwable is thrown, …Run Code Online (Sandbox Code Playgroud) 对于我可以阅读的内容,它用于在swing应用程序中调度新线程以执行某些"后台"工作,但使用此而不是"普通"线程有什么好处?
使用新的Thread是不一样的,当它完成时使用SwingUtilities.invokeLater调用一些GUI方法?...
我在这里错过了什么?
http://en.wikipedia.org/wiki/SwingWorker
http://java.sun.com/products/jfc/tsc/articles/threads/threads2.html
我只是想在进行长时间下载时在框架的左下角设置一个不确定的JProgressBar动画.
我看了很多教程,其中没有一个对我很清楚.我只是想在后台下载文件时让它具有动画效果.每个我试过这种方式,它不会动画进度条,直到后下载完成.
我需要帮助知道下载()调用的位置.
class MyFunClass extends JFrame {
JProgressBar progressBar = new JProgressBar();
public void buttonClicked() {
progressBar.setVisible(true);
progressBar.setIndeterminate(true);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
progressBar.setIndeterminate(true);
progressBar.setVisible(true);
// Do I do my download() in here??
}});
// Do download() here???
progressBar.setVisible(false);
}
}
Run Code Online (Sandbox Code Playgroud)
提前致谢!
编辑:对于那些将来遇到类似问题的人来说,这是基本问题的基本解决方案.这不是我的代码,而是一般草图.内部buttonClicked():
public void buttonClicked() {
class MyWorker extends SwingWorker(String, Object) {
protected String doInBackground() {
progressBar.setVisible(true);
progressBar.setIndeterminate(true);
// Do my downloading code
return "Done."
}
protected void done() { …Run Code Online (Sandbox Code Playgroud) 在测试使用Swingworker的一些实时仿真代码时,我注意到我的GUI似乎总是以30 fps运行,不多也不少.每次用户与应用程序交互时(如鼠标移动)或调用Swingworker的process()方法时,我都会更新GUI.Swingworker现在没有做任何事情,它只是从GUI抓取鼠标位置并通过publish()和process()方法将其作为克隆发回(我只是这样做,看看我能做什么和能做什么在线程之间进行通信时要做,因为多线程对我来说仍然是一个新手.我在任何地方都没有定时器,Swingworker的process()方法在GUI上调用repaint(),所以我想知道是什么原因导致GUI以30 fps更新?是否可能默认情况下GUI中的vsync处于活动状态,或者它是Swingworker中process()方法的某些行为?最后:有没有办法获得更高的帧速率?
这是一个表现出这种行为的sscce:
public class SimGameTest implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new SimGameTest());
}
@Override
public void run() {
MainWindow mainWindow = new MainWindow(new Game());
mainWindow.setLocationRelativeTo(null);
mainWindow.setVisible(true);
}
}
public class MainWindow extends JFrame {
private Game game;
private GamePanel gamePanel;
public MainWindow(Game game) {
this.game = game;
createAndShowGUI();
startGame();
}
private void startGame() {
GameSim gameSim = new GameSim(game, gamePanel);
gameSim.execute();
}
private void createAndShowGUI() {
setTitle("Sim game test");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
JPanel contentPane = …Run Code Online (Sandbox Code Playgroud) java ×10
swingworker ×10
swing ×9
concurrency ×2
buffering ×1
frame-rate ×1
generics ×1
jprogressbar ×1
progress-bar ×1
repaint ×1
void ×1