我的GUI锁定,因为我需要通过EDT更新它,但是,我还需要通过GUI传递一个正在更新的变量:
while ((message = this.in.readLine()).startsWith("NUMPLAYERS"))
{
numOfPlayers = Integer.parseInt(message.split(":")[1]);
numPlayers.setText("There are currently " + numOfPlayers + " players in this game");
}
Run Code Online (Sandbox Code Playgroud)
这不起作用.我需要在EDT中设置文本,但我不能将numOfPlayers传递给它而不将其声明为final(我不想这样做,因为它随着新玩家加入服务器而改变)
我有这个ActionListener在EDT中被调用.我的plot()函数计算量很大,很容易花费五秒钟.它使GUI按预期挂起.我添加了SwingUtilities.invokeLater代码,它仍然挂起.由于我正在为我的升沉计算产生一个单独的线程,GUI不应该响应吗?
final ActionListener applyListener = new ActionListener()
{
@CommitingFunction
public void actionPerformed(ActionEvent arg0)
{
/*Don't do plotting in the EDT :)*/
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
plot();
}
});
}
};
Run Code Online (Sandbox Code Playgroud) 我SwingUtilities.invokeLater()经常使用.但是,这样做会使某些情况下的调试变得困难:您无法看到调用的代码的堆栈跟踪SwingUtilities.invokeLater(),因为该代码已经结束了它的执行.
在调用时是否有关于如何设置某种上下文(仅用于调试目的)的建议SwingUtilities.invokeLater(),以便您可以找出导致相关UI事件的原因?
有人可以向我解释为什么我放弃了选择(设置setSelected())JCheckBox时我放入JOptionPane了ItemListener?这是一个错误吗?
很奇怪,如果这个过程延迟invokeLater(),setSelected()正如我预期的那样正常工作.

来自SSCCE
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ComponentEventDemo extends JPanel
implements ComponentListener, ItemListener {
private static final long serialVersionUID = 1L;
private JFrame frame;
private JTextArea display;
private String newline = "\n";
private JTextField field1;
public ComponentEventDemo() {
super(new BorderLayout());
display = new JTextArea(10, 25);
display.setEditable(false);
JPanel panel = new JPanel(new GridLayout(0, 2));
field1 = new JTextField();
field1.setDisabledTextColor(Color.red);
JCheckBox checkbox = new JCheckBox("Label visible", …Run Code Online (Sandbox Code Playgroud) 这个问题与我在这里问的问题有些关系.现在,我有一个类"Controller",它由main方法和所有swing组件组成.有一个名为"VTOL"的类,它由一个名为"altitude"的变量组成(我现在声明这个变量是volatile).
这是一个由在后台运行的线程组成的类:
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author Vineet
*/
public class Gravity extends Thread {
String altStr;
double alt;
Controller ctrl = new Controller();
@Override
public void run() {
while (true) {
alt=VTOL.altitude;
System.out.println(alt);
alt = alt-0.01;
VTOL.altitude= (int) alt;
altStr=new Integer(VTOL.altitude).toString();
ctrl.lblAltitude.setText(altStr);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
首先,我最初面临的问题是我无法更新"高度"的值,它在整个程序执行过程中保持为0.所以我宣称它是不稳定的(我不知道它是否是一个好习惯)
其次,在Controller类中有一个名为"lblAltitude"的jLabel,我希望将其值更新为此线程中的更改,但不知何故那不会发生.我怎样才能做到这一点?
从swing工作者与EDT交互的常用方法是使用get()方法.但我有一个很长的任务和代码,如下所示:
public Void doInBackground() {
for(Object o : objects) {
doSomething();
MyGlobalGUIConsole.addMessage("Done for " + o);
}
}
Run Code Online (Sandbox Code Playgroud)
在大多数tutotials中,建议使用返回值从SwingWorker返回到EDT,但我可以:
public Void doInBackground() {
for(Object o : objects) {
doSomething();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
MyGlobalGUIConsole.addMessage("Done for " + o);
}
});
}
}
Run Code Online (Sandbox Code Playgroud) 我创建了应用程序,它的表现非常符合预期.只要数据库查询正在运行,gui就会保持响应.使用SwingUtilities.invokeLater()创建自定义面板时,gui会冻结很短的时间.
当我使用SwingUtilities.invokeAndWait()时,它在高端游戏PC上运行非常流畅.(可能不是代码最好的机器...)但是在相对较慢的机器(双核,2GB RAM)上,gui"滞后"
我创建了一个非常小的程序版本来重现行为.测试时增加TEST_NUMBER_OF_PANELS的值.
它将它设置为一个非常大的值,以重现我当前的电脑上的行为,没有任何花哨的外观和感觉和其他组件.但我不想这样张贴.所以我减少到100
package test;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.event.TableModelEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
//import org.pushingpixels.substance.api.SubstanceLookAndFeel;
//import org.pushingpixels.substance.api.skin.BusinessBlackSteelSkin;
//import org.pushingpixels.substance.api.skin.SubstanceBusinessBlackSteelLookAndFeel;
public class Test extends JFrame {
private static final int TEST_NUMBER_OF_PANELS = 100; …Run Code Online (Sandbox Code Playgroud) 我仍然是Java的初学者,所以我没有学到很多关于线程和并发的知识.但是,我希望能够使用ScheduledThreadPoolExecutor作为计时器,因为我遇到了java.util.Timer和TimerTask的问题.我对线程的创建非常感兴趣,并且知道我将在几周内学习它们.但是,如果有可能,有人可以给我一个基本的例子,说明如何使用util.timer将当前的迷你测试程序转换为使用ScheduledThreadPoolExecutor?
我想尽快完成这个例子,所以我没有太多时间去学习线程 - 不管我想要多少.说完这些之后,请包含您认为Java初学者应该了解的有关ScheduledThreadPoolExecutor的重要信息.
示例程序
我已经做了一个快速的小例子来表示我在一个更大的程序中遇到的问题.该程序应该做的是允许用户按下按钮来启动计数器.然后,用户必须能够在他/她想要时停止并重新启动计数器.在较大的程序中,此计数器保持相等至关重要,因此我使用了scheduleAtFixRate()方法.初始延迟始终相同(在这种情况下为0)也很重要.问题(我相信你会看到)是一旦取消定时器就无法重启 - 我希望ScheduledThreadPoolExecutor能解决这个问题.
码:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.TimerTask;
import java.util.Timer;
public class Tester extends JFrame {
JButton push = new JButton("Push");
static JTextArea textOut = new JTextArea();
Timer timer = new Timer();
boolean pushed = false;
static int i = 1;
public Tester() {
super();
add(push, BorderLayout.NORTH);
add(textOut);
push.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!pushed) {
timer.scheduleAtFixedRate(new Task(), 0, 1000);
pushed = true;
} else {
timer.cancel();
pushed …Run Code Online (Sandbox Code Playgroud) java swing multithreading executorservice event-dispatch-thread
我的问题是基于理论的问题,但它确实满足了我的特定需求.
当你的SwingWorker抛出a)你可以预料到并且b)需要从中恢复并继续的异常时,你会怎么做,但是你想通知用户这个错误已经发生了?如何获取预期的异常并通知用户而不违反"No Swing code from doInBackground()"规则?
考虑到这个问题,我已经开发了一个SSCCE,我想提出下面的问题.
SSCCE:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutionException;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class Test {
public static void main(String args[]) {
final JFrame frame = new JFrame();
JButton go = new JButton("Go.");
go.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new Task(frame);
}
});
frame.add(go);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
static class Task extends SwingWorker<Void, Void> {
JFrame …Run Code Online (Sandbox Code Playgroud) 请向我解释为什么我会遇到这次崩溃?
线程1:EXC_BAD_INSTRUCTION(代码= EXC_I386_INVOP,子代码= 0x0)
在这
DispatchQueue.main.sync {print("sync")}
这是我的代码.
override func viewDidLoad() {
super.viewDidLoad()
print("Start")
DispatchQueue.main.async {
print("async")
}
DispatchQueue.main.sync {
print("sync")
}
print("Finish")
}
Run Code Online (Sandbox Code Playgroud) java ×9
swing ×8
swingworker ×3
invokelater ×2
asynchronous ×1
blocking ×1
debugging ×1
ios ×1
jcheckbox ×1
joptionpane ×1
swift ×1