经过多年的Java编程,我总是习惯于创建main()这样的方法:
public static void main(String[] args)
{
runProgram();
}
Run Code Online (Sandbox Code Playgroud)
但是最近我从Web上学习了一些代码并且有时看到这个代码而不是main()上面的常规用法:
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
runProgram();
}
});
}
Run Code Online (Sandbox Code Playgroud)
我只是想知道:
main()方式?当我试一试时,我看不出有任何区别.感谢您阅读我和您的答案.
可能重复:
SwingUtilities.invokeLater做什么?
SwingUtilities.invokeLater
我已经看过几百次这段代码了:
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
Run Code Online (Sandbox Code Playgroud)
现在我的问题是:做invokeLater()什么?如果我只是在主线程中创建并显示我的GUI,会发生什么样的坏事?
我无法理解这个简单的代码:
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
Run Code Online (Sandbox Code Playgroud)
任何人都可以解释一下它是如何工作的(简单来说因为我是新手)?这个简短的代码是这个更大的代码的一部分.
更具体地说,我有以下问题:
我想再强调一次,我是一个新手,使用"特殊"和"技术"词语会产生更多问题.
如果您决定帮助我,请提前感谢您!
我试图看看今天早些时候是否可以回答这个问题.我意识到我并不完全理解Event Dispatch Thread(EDT).谷歌搜索确认并帮助了这一点,并澄清了为什么我没有.(这也可能与理解有关.)
代码设置GUI,稍后(如前面的问题中所述)更新文本字段,直到取消设置标志.
我有几个问题/要求.
请解释为什么如果两个调用(to swingInit和doIt)都在invokeLater块之外(如图所示),下面的代码运行正常,因为这两个调用都影响或查询GUI但是它们都没有在EDT上执行(是吗?).这不是诱人的失败吗?
如果呼叫在swingInit内部和doIt外部,代码也会运行invokeLater.所以swingInit在EDT上执行,但不应该doIt在EDT上执行是一个问题吗?(我觉得这很有效.我应该去过吗?)
我想我明白为什么它会挂起,如果doIt它在里面invokeLater而不管它在哪里swingInit:目的invokeLater只是初始化 GUI(对吧?).
如果doIt只启动(可能发生的事件)在美国东部时间,但肯定不是里面invokeLater块?
(EDT概念的历史很有意思.它并不总是如此.请参阅上面的链接"我为什么不"理解它.)
import static java.awt.EventQueue.invokeLater;
import java.awt.event.*;
import javax.swing.*;
public class Whatever
{
static boolean flag = true;
static JTextField tf = new JTextField("Hi",20);
static JPanel …Run Code Online (Sandbox Code Playgroud) 好的,我已经在网上阅读了一个搜索过的内容,但我还没有找到问题的解决方案,也许我错过了一些简单的东西,因此我在这里......
我有一个相当大的项目,处理维修业务的工单.这是所有数据库连接,许多页面的代码和类.但我只是在前端添加了一小段代码,实质上是在我们的笔记区域中检查新消息.
无论如何,我显示一个带有两个JLabel的简单JFrame,而一个单独的线程查询数据库.这一切都发生在程序的开始.问题是我的小"请等待" JFrame提出了它的框架,但没有胆量,没有背景,没有JLabel,在等待期间(这是程序加载的其余部分,而不是数据库线程),显示后,但到那时它错过了它的观点.
我写了以下示例程序.它显示一个简单的JFrame(CheckingMessagesGUI:一个带有两个JLabel的JFrame,仅此而已)休眠5秒然后显示Example(主程序)JFrame,然后立即关闭()在这个例子中,当然我真正的程序继续做多很多.我发现这似乎是导致问题的原因.一旦睡眠定时器用完,窗口就会显示,但显示它的代码是在命令之前给出的,应该按照那个顺序完成吗?System.exit(0)invokeLaterThread.sleep
我的问题是为什么invokeLater导致我的JFrame无法正确显示?
我的理解是,目的invokeLater是让项目在正确的AWT事件线程上运行,这会让我觉得这个窗口会被正确绘制.无论如何,我确定我错过了一些明显的东西.我invokeLater在下面的代码中注释了该部分,并且它正确运行,如果你把它放回去它不...
提前谢谢了.
package javaapplication6;
public class Example extends javax.swing.JFrame {
public Example() {
System.out.println("Example started");
setBounds(100,100,200,200);
System.out.println("cmGUI instantiated");
CheckingMessagesGUI cmGUI = new CheckingMessagesGUI();
System.out.println("Set cmGUI visible");
cmGUI.setVisible(true);
cmGUI.validate();
try {
System.out.println("timer started");
Thread.sleep(5000);
System.out.println("timer done");
} catch(InterruptedException e){
}
System.exit(0);
}
public static void main(String[] args) {
/*java.awt.EventQueue.invokeLater(new …Run Code Online (Sandbox Code Playgroud) 这是我的启动画面代码,
public class SplashScreen extends JWindow {
private static final long serialVersionUID = 1L;
private BorderLayout borderLayout = new BorderLayout();
private JLabel imageLabel = new JLabel();
private JProgressBar progressBar = new JProgressBar(0, 100);
public SplashScreen(ImageIcon imageIcon) {
imageLabel.setIcon(imageIcon);
setLayout(borderLayout);
add(imageLabel, BorderLayout.CENTER);
add(progressBar, BorderLayout.SOUTH);
pack();
setLocationRelativeTo(null);
}
public void showScreen() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
setVisible(true);
}
});
}
public void close() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
setVisible(false);
dispose();
}
});
}
public void setProgress(final …Run Code Online (Sandbox Code Playgroud) 我喜欢将invokeLater()工作单元发送到AWT EDT 的简单性.有一个类似的机制可以将工作请求发送到后台线程(例如SwingWorker),但据我所知,这些机制没有任何类型的事件排队和调度机制,这是invokeLater()所依赖的.
所以相反,我最终给我的后台线程一个阻塞队列,其他线程向其发送消息,并且该线程实际上运行一个接收循环,阻塞直到消息到达.
事实上,这可能正是人们如何在后台线程中实现类似EDT的行为(或者它会是什么?).另一方面,我喜欢简单地悬挂在那里的线程的简单性,只要碰巧从天空中的一些看不见的事件调度队列发送到它就处理"工作水滴".Java是否提供了创建这种"事件驱动的工作线程"的方法?或者是消息排队正确的方法来执行此操作吗?而且相关的是invokeLater(),消息传递技术有缺点吗?
从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) 很确定它是这样的 - 但我想确定地知道 - 在 invokeLater() 或 invokeAndWait() 的情况下给出的关系是发生在之前吗?
这些方法在(分别为 SwingUtilities)AWT.EventQueue 中定义。我想当在 EventQueue 中输入一些东西时会涉及同步,因此作为同步的结果,发生了关系,最后给出了可见性。
但真的是这样吗?(我在哪里可以找到这些信息?)
例如在一些工作线程内
...
*<1> heavy computation modifying lots of DATA*
...
SwingUtilities.invokeLater(
new Runnable() {
@Override
public void run() {
*<2> is visibility of modified DATA guaranteed?*
}
}
);
Run Code Online (Sandbox Code Playgroud)
例如在一些线程内
...
SwingUtilities.invokeAndWait(
new Runnable() {
@Override
public void run() {
...
*<1> change some DATA*
}
}
);
*<2> is visibility of modified DATA guaranteed?*
Run Code Online (Sandbox Code Playgroud) invokelater ×10
java ×10
swing ×7
swingworker ×2
awt ×1
concurrency ×1
jprogressbar ×1
worker ×1