我是Java的新手(仅使用它大约一周),我正在商店模拟器上工作.基本上我只是希望现在能够完成基本的事情,比如有一段时间直到关闭以及屏幕上显示打开变量的时间.
我在我的Simulation扩展javax.swing.JFrame类中做了以下函数:
public void incOpenTime() {
timeOpen++;
int hours = timeOpen / 3600;
int minutes = (timeOpen % 3600) / 60;
int seconds = (timeOpen % 3600) % 60;
this.openTime.setText((hours < 10 ? "0" : "") + hours
+ ":" + (minutes < 10 ? "0" : "") + minutes
+ ":" + (seconds < 10 ? "0" : "") + seconds);
decTimeLeft();
}
public void decTimeLeft() {
int remainingTime = 28800 - timeOpen;
int hours = remainingTime / 3600; …Run Code Online (Sandbox Code Playgroud) 我正在使用此代码从actionPerformed上的按钮直接调用invokeLater:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
int temp = (jComboBox1.getSelectedIndex() + 1);
heavyProccesingFunction();
}
});
}
Run Code Online (Sandbox Code Playgroud)
这仍然冻结了GUI.为什么?我没有使用invokelater函数得到相同的结果.
我应该用
Thread queryThread = new Thread() {
public void run() {
Run Code Online (Sandbox Code Playgroud)
代替?
编辑:
谢谢,应该使用新的线程.
我开发了一个用于创建和提取存档的Java应用程序 - 比如WinRAR.您可以使用多线程同时创建多个归档.最近,我希望在每个创建时在新的JFrame中以JProgressBar的形式在存档创建期间添加信息状态.
但我的问题是在新的状态框架和创建存档的线程中生成信息.这就是我在存档线程中创建JFrame以更新当前进度条的原因.
但就像我可以在各种信息源和你的答案/评论中阅读它一样,它反对Java Swing和性能; 我无法在EDT的其他地方创建摆动对象.
但那么,我该如何解决我的问题呢?如何在存档的写入和状态JFrame(使用JProgressBar)之间建立通信?
编辑:
我实现了SwingWorker来管理我的应用程序中的GUI.现在已经完成了,我还有一个问题:
使用SwingWorker,如何使用状态框架按钮上的事件对后台任务执行操作?(示例:暂停压缩或停止压缩.)
java user-interface swing multithreading event-dispatch-thread
我正处于学习Java的初级阶段.在我读过的所有文档中,它都提到Java使用安全引用来访问对象而不是内存指针.而且当方法返回时,其本地范围的变量符合垃圾收集的条件.
那么为什么在下面的代码中,在createFrame方法返回后,JFrame对象不会随窗口一起被销毁?
import javax.swing.*;
public class HelloJava {
public static void main( String[] args ) {
createFrame();
}
private static void createFrame() {
JFrame frame = new JFrame( "Hello, Java!" );
JLabel label = new JLabel( "Hello, Java!", JLabel.CENTER );
frame.getContentPane().add( label );
frame.setSize( 300, 300 );
frame.setVisible( true );
}
}
Run Code Online (Sandbox Code Playgroud)
不仅窗口是可见的,我可以在该窗口上执行所有操作,如拖动,最大化,最小化等.
java concurrency swing garbage-collection event-dispatch-thread
嗨,我已经google了,无法弄清楚为什么我的paintComp方法没有被调用
我有以下代码包com.vf.zepto.view;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import javax.imageio.ImageIO;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import com.vf.zepto.view.interfaces.ProcessorPanel;
public class CountryDetailsPanel extends JPanel implements ProcessorPanel, Runnable {
private GridBagConstraints c = new GridBagConstraints();
private String countryName;
private Properties prop = new Properties();
private BufferedImage image;
public CountryDetailsPanel() {
try {
prop.load(new FileInputStream("country.props"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace(); …Run Code Online (Sandbox Code Playgroud) 这是我的示例代码...我面临的问题是我的swingWorker扩展类只向我显示doInBackground()作为重叠方法.我也想使用done()和process()方法,但我的类没有显示它@overided,也没有调用done/process方法,需要调用离开while循环的东西等因为我知道它是无限循环但是为什么不是在publish()上调用process方法?
public class getChatSwingWorkerThread extends SwingWorker<String , String> {
private final JTextArea chat_text_area;
private PostDataConnection post = null;
private BasicUserInterface chatWindow = null;
public getChatSwingWorkerThread(JTextArea text_area){
chatWindow = new BasicUserInterface();
this.chat_text_area = text_area;
post = new PostDataConnection();
}
@Override
protected String doInBackground() throws Exception {
String returnData = "";
while(true){
returnData = post.getAvailableChat();
if(!returnData.equals("")){
publish(returnData);
}
}
}
protected void process(String returnData) {
chat_text_area.append(returnData);
}
public void done(String returnData) throws InterruptedException, ExecutionException{
chat_text_area.append(get());
}
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方法制作的.
那么哪一个是真正的方法?我哪里错了?
有这篇文章:
有人跳了队!偶尔看来,一些挥杆事件在事件队列中以不正确的顺序处理(并且当有人切入队列时没有任何东西让我的血液沸腾)导致奇怪的行为.最好用小代码片段来说明这一点.阅读下面的代码段,仔细考虑您想象的事件发生的顺序.
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
repaint();
doSomething();
}
});
Run Code Online (Sandbox Code Playgroud)
大多数开发人员都认为repaint()方法将导致在doSomething()方法调用之前进行绘制操作.但事实并非如此,对repaint()的调用将创建一个新的绘制事件,该事件将添加到事件队列的末尾.只有当前的Action Event完成后才会处理(调度)此新的paint事件.这意味着将在调度队列上的新Paint Event之前执行doSomething()方法.
这里的关键点是调用repaint()将创建一个新的绘制事件,该事件将被添加到结束事件队列中而不会立即处理.这意味着没有事件跳过队列(我的血液可以保持在正确的温度).
我的问题是,我怎么能强迫的Swing做repaint();之前doSomething();?
此外,如果有方法调用repaint()WITHIN,doSomething();它们将仅在doSomething();完成后执行.有没有办法可以暂停doSomething();中间执行,然后投入reapaint();,完成它,然后恢复doSomething();?
到目前为止我找到的解决方案只有这个(链接),但它并不实用......
我知道应该使用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) 我有三个问题密切相关,因为它们是彼此诞生的,代表了一个思路,所以我在一个问题下发布它们.如果我单独发布它,我无法帮助我构建我的问题的大局.
1)你能用简单的语言解释一下SwingUtilities.invokeLater吗?我理解线程,我敢说了很多,但文档的语言仍然让我感到困惑.它说:
导致doRun.run()在AWT事件派发线程上异步执行.这将在处理完所有挂起的AWT事件后发生.当应用程序线程需要更新GUI时,应使用此方法.在以下示例中,
invokeLater调用将Runnable对象排队到doHelloWorld事件调度线程上,然后打印消息.
如果我付出一些努力来理解所说的内容,我认为这就是它所说的,但我不能确定它.我想它说:
该invokeLater方法仅在应用程序的主线程上调度主窗口创建和调度程序/消息泵的设置,而不是在单独的线程上.它通过发布消息来创建窗口并在主/主应用程序线程上设置它.换句话说,主要话题是对我们说:"你要我创建的窗口将在我完成其他现在的工作之后创建."
但后来有两件事让我感到困惑,我将其列为下面的两个问题.
2)那么为什么我需要将新窗口的消息循环实现为Runnable.这意味着我想要一个单独的线程来执行该消息循环.
3)我在创建窗口的函数和窗口的消息循环函数中打印出当前线程Id,它们都是不同的线程.那么,Swing中的每个窗口都在自己的线程上运行?那太疯狂了.你能告诉我这里发生了什么吗?如果你能在一段或两段中解释在Swing中创建的GUI应用程序的线程模型?
public static void main(String[] args) {
SwingUtilities.invokeLater(new MainWindowEventLoop());
System.out.println(String.format("Main thread %1$d started.",
Thread.currentThread().getId()));
}
public class MainWindowEventLoop implements Runnable {
@Override
public void run() {
JFrame mainWindow = new MainWindow("Main Window");
System.out.println(String.format("Main window loop running on thread %1$d.",
Thread.currentThread().getId()));
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
主线程1开始了.
主窗口循环在线程14上运行.
java ×10
swing ×10
concurrency ×2
invokelater ×2
jframe ×2
jvm ×1
repaint ×1
swingworker ×1
timer ×1