java garbage collecting in dialog - java

*I'm now encountering a very strange java GC problem when I trying to make a button in a JFrame, and when I click the button, it display a JDialog which need to deal with and show some images and need nearly 200M memory. But the problem is when I close the dialog and reopen it, sometimes it cause java.lang.OutOfMemoryError. (not every times)
Trying to solve the problem, I simplify this problem and make some experiment, which cause me more confused.
The Code I used in my " experiment " is showed below.
When I click a button in a frame, I allocate 160M memory for an integer array, and display a dialog, But If I close the dialog and reopen it, OutOfMemoryError appears. I adjusting the code and the result is:
If I don’t create the dialog and show it, no memory problem.
If I add a windowsCloseListener which invoke System.gc() to the dialog, no memory problem.
If I invoke System.gc() in the run() method, memory problem shows.
public class TestController {
int[] tmp;
class TDialog extends JDialog {
public TDialog() {
super();
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
// If I uncommment this code, OutOfMemoryError seems to dispear in this situation
// But I'm sure it not a acceptable solution
/*
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.out.println("windowsclose");
TDialog.this.dispose();
System.gc();
}
});
*/
}
}
TDialog dia;
public void run() {
// If I do System.gc() here, OutOfMemoryError still exist
// System.gc();
tmp = new int[40000000];
for (int i = 0; i < tmp.length; i += 10)
tmp[i] = new Random().nextInt();
dia = new TDialog();
dia.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
final JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(200, 200);
JButton button = new JButton("button");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
TestController controller = new TestController();
controller.run();
controller = null;
}
});
frame.add(button);
frame.setVisible(true);
}
});
}
}
I’ve read about a lot articles which describe how java’s GC work. I think if java trying to allocate some space in the heap and it do not have enough free space, java will do gc, and if a object can’t be accessed from the gc root through “GC graph”, in which a edge from u to v represent u have a reference to v, root is something in the a thread working stack, or native resources, It’s useless and qualified to be collected by java’s GC.
Now the problem is When I click the button and trying to create an Integer array, the Integer array I create last time is certainly qualified to be collected by java’s GC. So why it caused Error.
Apologize for Such A Long Description…I don’t have much tactics in asking problem, so just trying to make it clear.
Besides, The parameter I used to start jvm is “ java –Xmx256m”

You're allocating new int[40000000] before while tmp still holds the reference to the last int[40000000].
The order of operation in an expression like tmp = new int[40000] is:
new int[40000]
Assign the reference to the array to tmp
So in 1. tmp is still holding the reference to it's last value.
Try doing:
tmp = null;
tmp = new int[40000000];

Try this:
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
public class TestController {
private JFrame frame;
int[] tmp;
public TestController(JFrame frame) {
this.frame = frame;
}
public void finish() {
if (dia != null) {
dia.dispose();
}
tmp = null;
}
class TDialog extends JDialog {
public TDialog() {
super(frame, "Dialog", true);
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
}
}
TDialog dia;
public void run() {
tmp = new int[40000000];
for (int i = 0; i < tmp.length; i += 10)
tmp[i] = new Random().nextInt();
dia = new TDialog();
dia.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
final JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(200, 200);
JButton button = new JButton("button");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
TestController controller = new TestController(frame);
controller.run();
// controller = null;
System.out.println("here");
controller.finish();
}
});
frame.add(button);
frame.setVisible(true);
}
});
}
}
where you clean out both the dialog and its data in the finish() method. The dialog again should be modal for this to work, else you'll need a WindowListener.
You state in comment:
But would you tell me what's wrong in my code? and what's the meaning of "be modal". I've read the api of Dialog's setModal method in java doc. it means " whether dialog blocks input to other windows when shown", seems not the same thing as you referred.
A modal dialog is in fact one that blocks input from the calling window, and in fact freezes code flow from the calling code as soon as the dialog is visible. Code then resumes once the dialog is no longer visible.
There's no magical solution to your problem with the dialog being modal per se, but it allows us to know exactly when the dialog is no longer visible -- the code resumes from where the dialog was set visible, and thus allows us to call clean-up code at this point. Here I call the finish() method.
If you don't want the dialog to be modal, then you'd need a WindowListener and listen for the dialog being closed, and then do your finish method call there.
All my code does is make sure that the int array is available for GC'ing before you create a new int array.

Related

Why is my boolean value preemptively being returned?

I am working on a login validator and have a class that checks username and password validity. After checking, a boolean variable (isValidLoginCredentials) is updated in the LoginProxy class, which can be fetched by a get method and used for another purpose. However, the value that is returned by the get method is always the default value that I assigned to isValidLoginCredentials when the class was created. I think the issue is that I am calling the getter method in main() before I have a chance to update isValidLoginCredentials, but I don't understand what changes I should make to stop this. Here is the relevant part of the class and main program.
public class LoginProxy implements ActionListener
{
private JLabel usernameLabel;
private JTextField usernameText;
private JLabel passwordLabel;
private JPasswordField passwordText;
private JButton loginButton;
private boolean isValidLoginCredentials = false;
public void createLogin()
{
/*Here was code irrelevant to the problem I removed*/
loginButton.addActionListener(new LoginProxy());
loginButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String user = usernameText.getText();//get the username
String pass = passwordText.getText();//get the password
String credentials = user +":"+pass;//creates the string I compare to other valid
//credentials
ConcreteLoginValidator validator = new ConcreteLoginValidator(credentials);
try
{
isValidLoginCredentials = validator.checkLogin();
System.out.println("The credentials are "+isValidLoginCredentials);
}
catch (FileNotFoundException e1)
{
e1.printStackTrace();
}
}
});
}
public void actionPerformed(ActionEvent e)
{
// TODO Auto-generated method stub
}
public boolean getValidity()
{
return isValidLoginCredentials;
}
And here is the main method
public static void main(String[] args)
{
boolean isValidLogin = false;
LoginProxy proxy = new LoginProxy();
proxy.createLogin();
isValidLogin = proxy.getValidity();
if(isValidLogin == true)
{
JFrame frame = MainUI.getInstance();
frame.setSize(900, 600);
frame.pack();
frame.setVisible(true);
}
}
What should I add so that isValidLogin=proxy.getValidity(); returns a value only after I have already entered and checked whether the login credentials are correct?
Going straight to the point, a quick fix is to put the code below:
if(isValidLoginCredentials) {
JFrame frame = MainUI.getInstance();
frame.setSize(900, 600);
frame.pack();
frame.setVisible(true);
}
After this part:
System.out.println("The credentials are "+isValidLoginCredentials);
The code you call on createLogin() just sets the action listener to the button in the UI, hence the code will be executed just when you click on the button.
On the top of that, when you open a window, it starts a separated thread. I don't know the rest of the code, but assuming that when you instantiate the LoginProxy, it opens the login window. But the way you wrote, it will open the window and check the isValidLogin straight away (it doesn't wait you to click the button).
If you want to prove that, you can simply put a System.out.println before and after the proxy.createLogin(). You will realise that both lines will be reached while the UI is rendered.
Using a modal dialog that blocks until it is closed.
Very simplified example:
public class Dialog { // LoginProxy in questions code
private String value = null;
public void show(Window owner) {
var dialog = new JDialog(owner, JDialog.DEFAULT_MODALITY_TYPE);
var field = new JTextField(40);
var okButton = new JButton("OK");
okButton.addActionListener(ev -> {
value = field.getText();
dialog.dispose();
});
var panel = new JPanel();
panel.add(field);
panel.add(okButton);
dialog.add(panel);
dialog.pack();
dialog.setLocationRelativeTo(owner);
dialog.setVisible(true); // this will be blocked until JDialog is closed
}
public String getValue() {
return value;
}
}
called like
public static void main(String[] args) {
var dialog = new Dialog();
dialog.show(null);
System.out.println(dialog.getValue()); // check if valid and open JFrame in questions code
}
Advantage of this solution IMHO: the dialog class (LoginProxy) does not need to know about the main class and main JFrame. It has a clear single function: ask for user input.
the dialog creation is even easier using JOptionPane
In order to guarantee reading a value written in another thread, you must make the field volatile:
private volatile boolean isValidLoginCredentials;
You must also wait until the other completes before reading it. That aspect I leave to the reader.

Prevent more than one DialogBox to appear

import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
class Demo implements ActionListener
{
JFrame f;
JButton b;
DisplayDialog dialog;
public Demo()
{
f = new JFrame();
f.setSize(200,200);
b = new JButton("Click me");
f.add(b);
dialog = new DisplayDialog();
b.addActionListener(this);
f.setVisible(true);
}
public void actionPerformed(ActionEvent e)
{
Object o = e.getSource();
if(o==b)
{
dialog.display("Hello");
dialog.display("Hello");
dialog.display("Hello");
dialog.display("Hello");
dialog.display("Hello");
}
}
public static void main(String args[])
{
Demo d = new Demo();
}
class DisplayDialog implements ActionListener
{
JDialog dg;
JLabel l;
JButton b;
Font myfont;
public DisplayDialog()
{
dg = new JDialog(f,"Alert!",true);
dg.setSize(300,150);
l = new JLabel("Message");
b = new JButton("OK");
myfont = new Font("Serif",Font.BOLD,12);
l.setFont(myfont);
dg.add(l);
dg.add(b,"South");
dg.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
b.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
Object o = e.getSource();
if(o==b)
{
dg.setVisible(false);
}
}
public void display(String str)
{
if(dg.isVisible())
dg.setVisible(false);
l.setText(str);
dg.setVisible(true);
}
}
}
When the button is clicked, 5 Dialog box appears. Now I want to make such a change in the DisplayDialog class so that every time display method is called,the previously opened dialogs are closed and the latest one is the only one that is visible.
I tried doing this :
public void display(String str)
{
if(dg.isVisible())
dg.setVisible(false);
l.setText(str);
dg.setVisible(true);
}
but it didn't do anything.
Also,I am very surprised that multiple dialog boxes are appearing even though there is only one instance of the object. From my understanding, setVisible(true) should not do anything if the dialog is already visible.
This whole situation is very confusing to me.
The thing is that you cannot do this in single thread (like you are preseting it in your demo) - setVisible will always block (wait till dialog closes) and another display call will not be invoked till then.
Try to run it in multi frame env (like you have stated that your app is) but change display to
public void display(String str){
l.setText(str);
if(dg.isVisible()){
dg.setVisible(true);
}
}
This way dialog will not be displayed if it is already visible, but text will be changed. The condition for it to work is that is is not consecutinve calls to display like in demo, but from different threads. There is no other way around. setVisible will alwys block.

How do I change the size and location of JOptionPane.showOptionDialog()

Okay, so here's the deal. Currently, I am using this:
String[] choices = {"Rock", "Paper", "Scissors"};
String input = (String) JOptionPane.showInputDialog(null, "Please, make your choice", "Rock Paper Scissors!", JOptionPane.QUESTION_MESSAGE, null, choices, choices[0]);
Which is what I need. It creates a drop down menu that allows the user to select Rock, Paper, or Scissors and then outputs it into a String. The problem is, the window that it pops in is REALLY small, and is in the center of the screen. I want to re-size it to be 970 pixels by 300 pixels, and to appear at the location of 950 pixels and 0 pixels.
Now, before you say it, I HAVE tried to use JFrames for this, because I know how to get it the size and at the location I want it. However, I can't get the ActionListener to behave in the way that I want it to.
public static void main(String args[]) throws IOException
{
JFrame hi = new JFrame("Hi");
hi.setSize(970, 300);
hi.setLocation(950, 0);
System.out.println("Hi");
Picture Hi = new Picture("c:/The Game/Cool.png");
Hi.display();
JButton B = new JButton("Hey There!");
hi.add(B);
int c = Output(hi);
}
public int Output(JFrame b)
{
int j = 0;
j = //CODE NEEDED HERE
return j;
}
#Override
public void actionPerformed(ActionEvent arg0) {
}
So, the problem with this is that I need the JFrame to pop up in then "CODE NEEDED HERE" section, and then, upon clicking the button, to return a certain value, and then to close out of the JFrame. However, the JFrame doesn't wait for the Output() function, and it immediately returns j, which is equal to 0. Instead, it just does whatever is in the actionPerformed function.
So, I am asking for a solution to either one of these problems. How to either re-size the JOptionPane.showInputDialog() or to get the JFrame to return an int value upon clicking a button.
Sorry if this is really poorly explained, I'm really new to JOptionPane and JFrames.
JOptionPane is quite configurable, it's also nicely self contained, taking a lot of the repetitive, boil plate code and hiding it away in an easy to use package.
But that doesn't mean you have to use it that way, you can simply create an instance of JOptionPane, which is just an ancestor of JComponent and add it to what ever you want.
The difficulty is plumbing all the functionality back together, so you can respond to the buttons, for example.
Just beware, your example places the dialog under my task bar (yes, mine is at the top of the screen), so I can tell you, as a user, that will annoy me!
So, this example basically wraps up all the boiler plate code into a simple class/method, which makes it easy to repeatedly prompt the user the same question, over and over again...
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import static javax.swing.JOptionPane.OK_CANCEL_OPTION;
import static javax.swing.JOptionPane.UNINITIALIZED_VALUE;
import static javax.swing.JOptionPane.VALUE_PROPERTY;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
String pick = Picker.pick();
System.out.println("You picked " + pick);
System.exit(0);
}
public static class Picker {
public static String pick() {
String[] choices = {"Rock", "Paper", "Scissors"};
JOptionPane pane = new JOptionPane("Please, make your choice", JOptionPane.QUESTION_MESSAGE,
OK_CANCEL_OPTION, null, null, null);
pane.setWantsInput(true);
pane.setSelectionValues(choices);
pane.setInitialSelectionValue(choices[0]);
JDialog dialog = new JDialog();
dialog.setModal(true);
PropertyChangeListener listener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
// Let the defaultCloseOperation handle the closing
// if the user closed the window without selecting a button
// (newValue = null in that case). Otherwise, close the dialog.
if (dialog.isVisible()
&& (event.getPropertyName().equals(VALUE_PROPERTY))
&& event.getNewValue() != null
&& event.getNewValue() != JOptionPane.UNINITIALIZED_VALUE) {
dialog.setVisible(false);
}
}
};
WindowAdapter adapter = new WindowAdapter() {
private boolean gotFocus = false;
public void windowClosing(WindowEvent we) {
pane.setValue(null);
}
public void windowClosed(WindowEvent e) {
dialog.removePropertyChangeListener(listener);
dialog.getContentPane().removeAll();
}
public void windowGainedFocus(WindowEvent we) {
// Once window gets focus, set initial focus
if (!gotFocus) {
pane.selectInitialValue();
gotFocus = true;
}
}
};
dialog.addWindowListener(adapter);
dialog.addWindowFocusListener(adapter);
dialog.addComponentListener(new ComponentAdapter() {
public void componentShown(ComponentEvent ce) {
// reset value to ensure closing works properly
pane.setValue(JOptionPane.UNINITIALIZED_VALUE);
}
});
pane.addPropertyChangeListener(listener);
dialog.add(pane);
//dialog.pack();
//dialog.setLocationRelativeTo(null);
dialog.setSize(970, 300); // This is bad idea, use an EmptyBorder instead
dialog.setLocation(950, 0);
dialog.setVisible(true);
String pick = null;
Object value = pane.getInputValue();
if (value != UNINITIALIZED_VALUE) {
pick = value.toString();
}
return pick;
}
}
}
The reason you're having problems with JFrame is because it's not designed to block the code execution when displayed, a JDialog can, see How to Make Dialogs for more details

Mac OS Java 7 JDialog.dispose Memory leak

I am observing some inconsistent behaviour between OS and Java versions when calling JDialog.dispose to dispose a JDialog (also occurs for JFrame).
The simple sample application, below, can be used to demonstrate the problem. If you run it and profile the application you will notice that any JDialog instances created by clicking on the "New Dialog" and subsequently closed do not get garbage collected as they are still being referenced by instances of sun.lwawt.macosx.CPlatformWindow, causing a memory leak in the application.
I don't believe this is due to any weak references either as I observed this problem in an environment that had experienced an OutOfMemoryError, so I would expect that anything that could have been garbage collected would have been at that point.
The problem occurs in the following environments:
Mac OS X 10.9: Java 1.7.0_5
Mac OS X 10.9: Java 1.7.0_45
The problem does not occur in the following environments:
Mac OS X 10.9: Java 1.6.0_65
Windows 7: Java 1.7.0_45
In these environments the JDialog instances are promptly collected and (obviously) no longer visible in JProfiler.
Note: The problem occurs using DISPOSE_ON_CLOSE or handling the close manually as commented out in the sample.
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.*;
public class Testing extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final JDialog parent = new JDialog((Frame)null, "Parent", false);
JButton add = new JButton("New Dialog");
add.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
final JDialog child = new JDialog(parent, "Child", false);
// child.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
child.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
child.setSize(100, 100);
//child.addWindowListener(new WindowAdapter() {
// #Override
// public void windowClosing(WindowEvent e) {
// child.setVisible(false);
// child.dispose();
// }
//});
child.setVisible(true);
}
});
parent.add(add);
parent.pack();
parent.setVisible(true);
}
});
}
}
Is there something that I am doing incorrectly?
Is my expected behaviour incorrect?
If not, can anyone point me to a Java bug report that covers this (I have had no luck finding one)?
Any suggested workarounds?
I was seeing the same thing and was able to get it to release the window by overriding the dispose method on my window like this:
#SuppressWarnings("deprecation")
#Override
public void dispose()
{
ComponentPeer peer = getPeer();
super.dispose();
if (null != peer)
{
try
{
Class<?> peerClass = Class.forName("sun.lwawt.LWComponentPeer");
Field targetField = peerClass.getDeclaredField("target");
targetField.setAccessible(true);
targetField.set(peer, null);
Field windowField = peer.getClass().getDeclaredField("platformWindow");
windowField.setAccessible(true);
Object platformWindow = windowField.get(peer);
targetField = platformWindow.getClass().getDeclaredField("target");
targetField.setAccessible(true);
targetField.set(platformWindow, null);
Field componentField = peerClass.getDeclaredField("platformComponent");
componentField.setAccessible(true);
Object platformComponent = componentField.get(peer);
targetField = platformComponent.getClass().getDeclaredField("target");
targetField.setAccessible(true);
targetField.set(platformComponent, null);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
This didn't release the CPlatformWindow but it is better than nothing and should help you.
I use the following code to try and minimize the memory leak. There will still be resources uncollected by the garbage collector, but all the Swing components that were children of the JFrame or JDialog will be garbage collected. A shorter title (or no title) can be used to make the footprint even smaller. I kept a meaningful title so that I can more easily track things in the profiler if necessary. The memory footprint of my application with this code is plenty small for long runs and lots of window open and close operations. Without it, memory would run out with a few dozen open and close operations on certain heavy weight windows that some users were using while leaving the application open for days on end.
protected void disposeAndEmptyOnClose(Component c) {
if ( c instanceof JFrame ) {
JFrame frame = (JFrame) c;
if (!frame.getClass().isAssignableFrom(JFrame.class)) {
LOG.warn("potential memory leak. Cannot guarantee memory is freed after frame is disposed because" +
" JFrame has been subclassed to " + frame.getClass().getName());
}
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosed(WindowEvent e) {
frame.removeAll();
frame.setContentPane(new JPanel());
frame.setJMenuBar(null);
frame.removeWindowListener(this);
frame.setTitle("disposed and emptied: "+frame.getTitle());
}
});
} else if ( c instanceof JDialog ) {
JDialog dialog = (JDialog)c;
if (!dialog.getClass().isAssignableFrom(JDialog.class)) {
LOG.warn("potential memory leak. Cannot guarantee memory is freed after dialog is disposed " +
"because JDialog has been subclassed to " + dialog.getClass().getName());
}
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.addWindowListener(new WindowAdapter() {
#Override
public void windowClosed(WindowEvent e) {
dialog.removeAll();
dialog.setContentPane(new JPanel());
dialog.removeWindowListener(this);
dialog.setTitle("disposed and emptied: "+dialog.getTitle());
}
});
} else {
LOG.warn("disposeAndEmptyOnClose not supported for " + c.getClass().getSimpleName());
}
}

Progress bar in Swing (Java) for command tools

I have several C/C++ command line tools that I'm wrapping with Java.Swing as GUI. The command line tools can take minutes to hours. Progress bar seems like a good idea to keep users sane. I'm also thinking it might be nice to wrap a GUI for the progress bar, instead of just using system out. But how?
I'm thinking the command line tools can write percents to stderr and I can somehow read it in java. Not exactly sure what the mechanics for this would be. I'm also not clear on asynchronous display (learned a bit about invokeLater() ). New to Java, and would appreciate general suggestions as well. Thanks.
--- update ---
Thanks everyone for your suggestions. Here's the resulting code.
private void redirectSystemStreams() {
OutputStream out_stderr = new OutputStream() {
#Override
public void write(final int b) throws IOException {
update(String.valueOf((char) b));
}
#Override
public void write(byte[] b, int off, int len) throws IOException {
update(new String(b, off, len));
}
#Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
};
System.setErr(new PrintStream(out_stderr, true));
}
private void update(final String inputText) {
int value = 20; //parse inputText; make sure your executable calls fflush(stderr) after each fprintf().
jProgressBar.setValue(value);
/* Also one can redirect to a textpane
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//update jTextPane with inputText
}
});
*/
}
That's seems very fragile, better would be to communicate via sockets in a well established protocol or with some sort of RCP ( perhaps Google's protobuf ) or even webservices.
If you still insists you can launch a process in Java with ProcessBuilder that will give you a Process reference of which you can get the InputStream to read the standard output, but again, that seems very fragile to me.
I hope this helps.
For the progress bar part of your problem you can do something like the following. Note that this is just an example to illustrate the point.
Basically, a thread is created to do the work. Presumably this Runner thread will be interacting with your C/C++ code to get its progress. It then calls update on the Progress Bars Dialog class.
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
public class Main {
private int value;
private Progress pbar;
public static void main(String args[]) {
new Main();
}
public Main() {
pbar = new Progress();
Thread t = new Thread(new Runner());
t.start();
}
class Progress extends JDialog {
JProgressBar pb;
JLabel label;
public Progress() {
super((JFrame) null, "Task In Progress");
pb = new JProgressBar(0, 100);
pb.setPreferredSize(new Dimension(175, 20));
pb.setString("Working");
pb.setStringPainted(true);
pb.setValue(0);
label = new JLabel("Progress: ");
JPanel panel = new JPanel();
panel.add(label);
panel.add(pb);
add(panel, BorderLayout.CENTER);
pack();
setVisible(true);
}
public void update(){
pb.setValue(value);
if(value >= 100){
this.setVisible(false);
this.dispose();
}
}
}
class Runner implements Runnable {
public void run() {
for (int i = 0; i <= 100; i++) {
value++;
pbar.update();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
}
}
}
}
// Create a window
JFrame frame = new JFrame("Progress");
// Creates a progress bar and add it to the window
JProgressBar prog = new JProgressBar();
frame.add(prog);
// Run C/C++ application
try {
Process p = Runtime.getRuntime().exec(new String[]{"filename","arg1","arg2","..."});
// Get InputStream
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
// Update the progress when recieving output from C/C++
new java.util.Timer().schedule(new TimerTask(){
public void run(){
String str = "";
while ((str=br.readLine()!=null) {
prog.setValue(new Integer(str)); // Set Value of Progress Bar
prog.setString(str+"%"); // Set Value to display (in text) on Progress Bar
}
}
},0,100); // Check every 100 milliseconds
// Fit the window to its contents and display it
frame.pack();
frame.setVisible(true);
} catch (Exception e) {
System.out.println("Failed To Launch Program or Failed To Get Input Stream");
}

Categories