我只是想知道是否仍然需要确保invokeLater()Runnable的同步性.
我遇到了死锁,需要在保持并发性的同时克服它.
这是一个好代码的例子吗?:
private String text;
private void updateText()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
synchronized(FrameImpl.this)
{
someLabel.setText(text);
}
}
});
}
Run Code Online (Sandbox Code Playgroud)
对于相当糟糕的示例感到抱歉,但我们必须假设它text被不同的线程修改,无法注入,并且依赖于正确的值.
这是正确的解决方案,还是通过将同步代码发送到未知的上下文中而无意中造成死锁问题?
谢谢.
这个简单的问题让我很困惑.您可以通过设置frames的setVisible属性来显示JAVA GUI应用程序true.但在我在互联网上发现的几乎所有例子中,他们都使用一个单独的线程来做同样的事情.
他们这样做,
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Frame().setvisible(true); //just take the idea of this line
}
});
Run Code Online (Sandbox Code Playgroud)
我发现这两种方法没有区别.但必须有一些特殊的原因,这就是每个人都这样做的原因.
有人可以解释一下......谢谢!
我通过这样做来设定我的外观和感觉
private void setSubstanceSkin(String theme) {
try {
UIManager.setLookAndFeel(new SubstanceBusinessBlackSteelLookAndFeel());
JFrame.setDefaultLookAndFeelDecorated(true);
JDialog.setDefaultLookAndFeelDecorated(true);
} catch (Exception e) {
e.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
但是我得到了这个堆栈跟踪:
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: javax.swing.plaf.metal.MetalRootPaneUI cannot be cast to org.jvnet.substance.SubstanceRootPaneUI
at org.jvnet.substance.utils.SubstanceCoreUtilities.getTitlePane(SubstanceCoreUtilities.java:3590)
at org.jvnet.substance.title.ImageWrapperHeaderPainter.paintExtraBackground(ImageWrapperHeaderPainter.java:172)
at org.jvnet.substance.SubstanceFillBackgroundDelegate.update(SubstanceFillBackgroundDelegate.java:198)
at org.jvnet.substance.SubstanceMenuBarUI.__org__jvnet__substance__SubstanceMenuBarUI__container__update(SubstanceMenuBarUI.java:251)
at org.jvnet.substance.SubstanceMenuBarUI.update(SubstanceMenuBarUI.java)
at javax.swing.JComponent.paintComponent(JComponent.java:778)
at javax.swing.JComponent.paint(JComponent.java:1054)
at javax.swing.JComponent.paintChildren(JComponent.java:887)
at javax.swing.JComponent.paint(JComponent.java:1063)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:585)
at javax.swing.JComponent.paintChildren(JComponent.java:887)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5228)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1482)
at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1413)
at javax.swing.RepaintManager.paint(RepaintManager.java:1206)
at javax.swing.JComponent.paint(JComponent.java:1040)
at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:39)
at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:78)
at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:115)
at java.awt.Container.paint(Container.java:1967)
at java.awt.Window.paint(Window.java:3877)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:781)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:728)
at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:677) …Run Code Online (Sandbox Code Playgroud) 我读了几本关于Java的书.在所有这些中,至少有一章教授GUI编程.在所有这些中,创建一个简单的表单应用程序遵循以下逻辑:
MyFrame.java
public class MyFrame extends JFrame
{
JButton button1;
public MyFrame()
{
button1 = new JButton("Click here.");
}
}
Run Code Online (Sandbox Code Playgroud)
FrameTest.java:
public class FrameTest
{
public static void main(String[] args)
{
MyFrame myFrame = new MyFrame();
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setSize(600, 600);
myFrame.setVisible(true);
}
}
Run Code Online (Sandbox Code Playgroud)
基本上,只是将JFrame子类化为创建表单并将其他组件声明为实例变量,并在构造函数中初始化这些组件.然后创建另一个测试类,在该类中实例化框架子类并调用它的一些方法使其可见.
但在并发课程中,我了解到我们有一个主线程,它在我们创建的每个应用程序中运行main().据我所知,当我们使用Swing创建GUI应用程序时,我们有另一个线程(Event Dispatcher Thread).因此,如果我没有记错,在每个基于Swing的GUI应用程序中至少有两个线程.这使得每个GUI应用程序都是多线程的.在我读过的一些文章和教程中,它说Swing不支持多线程,因此只能在Event Dispatcher Thread中创建和修改所有GUI组件,否则可能会出现线程干扰和内存不一致错误.
即使在维基百科(http://en.wikipedia.org/wiki/Swing_%28Java%29)中最简单的例子中,它也是通过invokeLater方法制作的.
那么哪一个是真正的方法?我哪里错了?
我最近发现了一个示例代码:
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
Run Code Online (Sandbox Code Playgroud)
该createAndShowGUI()方法打开用户界面窗口.然后我尝试修改代码如下:
public static void main(String[] args) {
createAndShowGUI();
}
Run Code Online (Sandbox Code Playgroud)
两个版本都同样有效.有什么不同?
有什么区别:
//Some code, takes a bit of time to process
(new SomeJFrame()).setVisible(true);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
(new SomeJWindow()).start();//Start a new thread
}
});
Run Code Online (Sandbox Code Playgroud)
和:
class doGraphics extends SwingWorker<Void, Object> {
@Override
public Void doInBackground() {
//Some code, takes a bit of time to process
(new SomeJFrame()).setVisible(true);
return null;
}
@Override
protected void done() {
(new SomeJWindow()).start();//Start a new thread
}
}
(new doGraphics()).execute();
Run Code Online (Sandbox Code Playgroud)
哪种方法更好用?
我知道应该使用invokeLater在事件调度线程(EDT)上安全地创建JFrame,并且我试图在我的main方法中创建它们中的两个.
public void run() {
// Handle Menu When Open
menu.setVisible(true);
while(menu.isVisible())
{
if(menu.isShowing() == false) {
showMenu = false;
showSimulation = true;
}
}
menu.setVisible(false);
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
int[] dims = menu.SizeSetting();
simulation = new Simulation(dims[0], dims[1]);
}
});
simulation.run();
}
Run Code Online (Sandbox Code Playgroud)
因此,菜单被创建(这似乎工作正常,因为这里所需的处理非常少).在此之后,使用菜单,点击一个按钮menu.setVisible(false)被调用.之后,我在EDT上排队一个方法,Simulation是一个派生自的类JFrame.它的构造函数如下:
public Simulation(int width, int height) {
this.setVisible(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Traffic Light System - Simulation");
grid = new Grid(0, 0);
ready = false;
grid = new Grid(width, height);
addComponentsToPane(); // …Run Code Online (Sandbox Code Playgroud) 所以如果 Event Dispatch Thread 是一个独立于主线程的线程,那让我觉得下一个代码会输出
Before
Runnable
true
After
Run Code Online (Sandbox Code Playgroud)
但是当我运行它时,就好像 EDT 在运行invokeLater(..)方法内的代码块之前等待主线程完成。输出是:
Before
After
Runnable
true
Run Code Online (Sandbox Code Playgroud)
编码:
Before
Runnable
true
After
Run Code Online (Sandbox Code Playgroud)
但是,如果我替换invokeLater(..)为invokeAndWait(..),那么我得到
Before
Runnable
true
After
Run Code Online (Sandbox Code Playgroud)
这让我觉得 EDT 并不是一个真正的独立线程,或者至少在这个例子中它的行为或只是在我看来不是。你怎么解释这个?
我永远不明白SwingUtilities.invokeLater,这就是我一直避免它的原因.但是让Swing Thread安全是非常重要的.好吧请原谅,因为这是我第一次这样做.我试图在一些数据库查询后关闭窗口.所以,据我所知,任何更新UI必须由.处理.这SwingUtilities.invokeLater是我的工作:
主要:
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new forminsert().setVisible(true);
forminsert f=new forminsert();
}
});
}
public forminsert() {
initComponents();
}
public class forminsert extends javax.swing.JFrame {
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
jTextField1 = new javax.swing.JTextField();
jButton1 = new javax.swing.JButton();
jButton2 = new javax.swing.JButton();
jButton3 = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setUndecorated(true);
jPanel1.setBackground(new java.awt.Color(0, 0, 0));
jPanel1.setBorder(javax.swing.BorderFactory.createMatteBorder(3, 3, 3, 3, new java.awt.Color(0, 204, 204)));
/////***REST …Run Code Online (Sandbox Code Playgroud) 以下代码执行正常:
public static void main(String [] args) {
Runnable r = new Runnable() {
public void run() {
createGUI();
}
} ;
javax.swing.SwingUtilities.invokeLater(r);
}
Run Code Online (Sandbox Code Playgroud)
我很好奇为什么以下代码无法编译:
import javax.swing.SwingUtilities;
public static void main(String [] args) {
Runnable r = new Runnable() {
public void run() {
createGUI();
}
} ;
invokeLater(r);
}
Run Code Online (Sandbox Code Playgroud)
之间有什么differenc javax.swing.SwingUtilities.invokeLater(r);和import javax.swing.SwingUtilities; invokeLater(r);
invokelater ×10
java ×10
swing ×10
concurrency ×1
jframe ×1
runnable ×1
substance ×1
swingworker ×1