我一直在将Substance的外观和感觉整合到我的应用程序中,并遇到了几个关于它的内部EDT(事件调度线程)检查例程的问题.Substance绝对拒绝在EDT之外构建UI类.我已经做了很多Swing/AWT,我知道关于EDT的大部分规则.我使用SwingWorker,SwingUtilties.invokeLater来修改组件.我总是认为组件可以在EDT之外构建,但必须在EDT上实现和操作.换句话说,您可以在后台构造和设置默认值,但对pack/setVisible的调用必须是EDT以及操作组件的任何后续调用.
我问的原因是我有一个特别"强大"的窗口来构建,涉及许多小部件,状态和资源(许多图标).以前,我在SwingWorker的背景方法上构建了窗口,并在done方法中使窗口可见.从来没有一个问题.切换到Substance后,内部EDT检查会让我感到困惑.
我已经能够重构代码来解决这个问题.我可以在EDT上构建这不是一个好的解决方案,因为整个应用程序将阻止.我还可以进行更多的重构,并尽力在EDT之外加载所有额外的资源.
把它包装起来...... 构建 Swing/AWT小部件不是在Event Dispatch Thread上安全吗?
根据Swing教程:
一些Swing组件方法在API规范中标记为"线程安全"; 这些可以从任何线程安全地调用.必须从事件派发线程调用所有其他Swing组件方法.忽略此规则的程序可能在大多数情况下正常运行,但会遇到难以重现的不可预测的错误.
但是这些标记为"线程安全"的Swing组件方法是什么?实际上有吗?
是否有完整的线程安全摆动方法列表?(线程安全的Swing方法似乎很少见,所以这样的列表不能太长......)
我多次听说Java Swing线程模型是错误的.我不完全理解为什么,我知道问题与你可以Drawable从主UI线程以外的另一个线程上绘制的事实有关.我知道有一些实用功能SwingUtilities.invokeAndWait,SwingUtilities.invokeLater可以让你在a中进行绘制Runnable,然后由Event Dispatcher线程运行.我猜这种方式可以确保绘画是同步完成的,这不会使缓冲区处于不连续状态.
我的问题是:"好"的UI工具包如何表现?采用了哪些解决方案?
我有一个JFrame,其中包含2个JPanel子类和BorderLayout中的2个JLabel.其中一个JPanel包含JButtons,另一个用于显示图形.JLabels位于北部和南部,西部是JPanel按钮,中间是JPanel.
显示JPanel需要不断刷新,所以我通过swing计时器生成的动作事件调用它的repaint()方法.我也覆盖它的paintComponent()方法来做我的绘图.
而不是显示我绘制的内容,"JFrame的内容"被绘制到显示JPanel上.我知道在完成绘图之前,我可以通过使用g.fillRect()或super.paintComponent()简单地"清除"显示JPanel.
我只是好奇为什么会这样.
我正在使用jdk 1.6u27.下面是我的代码:
package test;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class Main {
public static void main(String[] args) {
Simulation sim = new Simulation();
}
}
class Simulation extends JFrame {
public JLabel state;
private JLabel id;
private ButtonPanel control;
private Display display;
public Simulation() {
id = new JLabel("Test");
state = new JLabel("Test");
control = new ButtonPanel();
display = new Display(this);
this.setLayout(new BorderLayout());
this.add(id, BorderLayout.NORTH);
this.add(control, BorderLayout.WEST);
this.add(display, BorderLayout.CENTER);
this.add(state, BorderLayout.SOUTH);
this.setSize(500, …Run Code Online (Sandbox Code Playgroud) 关于我的问题(可能),我发现了另一种异常类型,我无法从SwingWorker线程中捕获和打印出来.
如何生成RepaintManager异常?
我读这CheckThreadViolationRepaintManager和该方法通过Alexander Potochkin,但似乎没有解决我的问题.
我使用最新的Eclipse和GWT Designer来用Java创建swing应用程序.我的应用程序窗口中的主要功能(这是一个javax.swing.JFrame)在工具生成的auto中如下所示:
/* launch the application */
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
AppWindow window = new AppWindow();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
Run Code Online (Sandbox Code Playgroud)
这似乎是围绕着这可能是一个很大的噪音:
public static void main(String[] args) {
try {
AppWindow window = new AppWindow();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
我已经读过在某些情况下需要EventQueue.InvokeLater技术,另一个问题是在这里询问使用它的位置.
我的问题更简单; 为什么在代码生成器中会自动执行此操作?为什么main应该快速返回并让事件队列稍后创建应用程序窗口?难道不会阻止这一点吗?为什么JFrame自动生成的设计器会执行此EventQueue?我试图在启动和显示表单方面看到一些不同,无论这个代码是以更简单的方式还是更难的方式完成,我只能暂时断定这有一些好处,这些好处在初学者制作的小型演示应用程序中不可见像我一样,也许在现实世界的大型复杂Jframe类中,这种延迟/排队策略有一些好处吗?
我正在开发一个简单的Java swing项目.这是主类的代码(名称已更改):
public class MainProg
{
private static MainProg program;
//mainWin is a JFrame
private MainWindow mainWin;
//Event handler class which extends MouseAdapter
private TrayManager trayMgr;
public static void main(String[] args)
{
program = new MainProg();
}
public MainProg()
{
mainWin = new MainWindow();
trayMgr = new TrayManager();
mainWin.startBtn.addMouseListener(trayMgr);
mainWin.setVisible(true);
}
}
Run Code Online (Sandbox Code Playgroud)
很明显,当程序启动时,main()它会创建一个新的MainProg类实例,然后调用构造函数.在构造函数中,它创建JFrame的新实例mainWin.然后它将事件处理程序附加到按钮上mainWin.
在事件处理程序类中trayMgr,唯一的方法是mouseClicked()除了a之外什么都不做System.out.println('Clicked');
问题是,当我在Netbeans中运行此程序时,JFrame立即显示,但我似乎必须在控制台中打印消息之前单击按钮2-3次.
这只是Netbeans的特定内容,还是我必须更改某些内容才能在窗口可见之前设置事件处理程序?
我正在尝试使用Swing创建一个测试互斥算法的平台.我的目的是在GUI中显示它们之间发送的服务器和消息.我还想显示一个关键部分,显示当前正在访问它的服务器.我正在使用一个执行SwingWorker线程的线程池来部署加载用户选择的互斥算法的服务器.
程序按预期运行,直到我尝试实现消息显示.为了显示每条消息的箭头,我扩展了SwingWorker,UIArrowThread,以添加一个从源服务器向目标绘制箭头的JLabel.在删除JLabel之前,此线程等待1秒.当我明确地创建一个或多个这些消息时,这似乎工作正常(我还创建了一个可以创建特定消息的测试平台).
当我尝试将此SwingWorker线程集成到程序中时,问题就出现了.启动算法时,每个服务器都会尝试访问关键部分并将其请求发送到每个其他服务器.这应该调用UIArrowThread,但似乎只有一些服务器实际上创建了该线程.
public void sendMsg(int destId, Object ... objects) {
comm.sendMsg(destId, objects);
try{
UIArrowThread a = new UIArrowThread(AlgorithmSimulatorUI.jlp,
objects[0].toString(),
comm.getMyId(),
destId);
AlgorithmSimulatorUI.threadPool.execute(a);
} catch (Exception exc){
System.err.println(exc);
}
}
Run Code Online (Sandbox Code Playgroud)
有些服务器似乎在实例化UIArrowThread之前就停止执行,最终导致死锁.任何使它通过该点的服务器都能正常工作,GUI显示应该是正常的.我在调用UIArrowThread之前和它的构造函数中测试了日志.看起来停止执行的线程永远不会在构造函数中进行日志调用.我很难理解为什么会发生这种情况.
public class UIArrowThread extends SwingWorker<Integer, String>{
JLayeredPane jlp;
String type;
int source;
int target;
Point start;
Point end;
Point[] points;
int quadrant;
public UIArrowThread(JLayeredPane jlp, String msg_type, int source,
int target){
this.jlp = jlp;
this.type = msg_type;
this.source = source;
this.target = target;
this.points = getPoints();
this.start = points[0]; …Run Code Online (Sandbox Code Playgroud)