I want to fire a command line executible with the parameters entered in GUI.
Process class can be used to fork my required command line process from the Java application, and I used the getInputStream() method of Process object to get the result and got it displayed in the GUI.
private void confirmActionPerformed(java.awt.event.ActionEvent evt) {
String output;
try {
Process p = Runtime.getRuntime().exec("my command line exe with parameters");
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((output = stdInput.readLine()) != null) {
TextField.setText(TextField.getText()+output+"\n");
}
} catch (IOException e) {
System.out.println("Exception in Process");
e.printStackTrace();
}
}
This is my code which is an event listener of a button pressed event and I attempted to display the result of the process in the text field (java swing component).
This process actually runs for quite a long time and shows some statistics as and when it runs when run in command line, but when i attempt it in GUI with the above code I'm getting the entire consolidated result only after the process finish running. I'm not getting the TextField updated as and when it is executing.
What would be the cause of this issue?
This is because the whole thing is done by the Swing event-handling thread.
Perhaps should you consider creating a separate thread and update the TextField with a SwingUtilities.invokeLater().
As Maurice already pointed out, you shouldn't be doing intensive processing on the UI thread. The SwingWorker class helps with that. It's part of the standard API since 1.6. There is also a backport to 1.5 if you can't use 1.6.
This class makes it easier to put some processing task on another thread and display the result later so that your GUI doesn't block in the meantime. You can also use SwingUtilities.invokeLater() directly, of course, as suggested by Maurice, but for me SwingWorker is the way to go as it is quite easy and apparently the new standard way of doing this kind of thing.
Related
I use a java program for communication between a arduino board and a scratch file. The communication happen well. I use a user interface to start the communication where i have buttons called
connect
close and minimize
When the user clicks the connect button code will check the value in combo box and accordingly it opens the scratch file.
Once the connect button is clicked the control moves to the scratch application. After completing my work when i tried closing the scratch. My scratch application closes as expected but the control does not return to the user interface because of which i am not able to close the application and i close it in net beans forcefully. In the output screen i don't see build successful and instead i get build stopped. That is my process works perfectly until i give connect but once the button is pressed it is hanged up some where.
I tried making it as a jar file and running it in a different machine at that time i use end task in task manager to close the application.
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
if("Disconnect".equals(jButton1.getText()))
{
System.exit(0);
}
if(jComboBox2.getSelectedItem()==null)
{
System.out.println("Select one port");
}
else
{
Runtime r = Runtime.getRuntime();
try {
//this.hide();
//p = r.exec("C:\\Program Files\\Scratch 2\\Scratch 2.exe C:\\Users\\Admin\\Desktop\\fwdbckpwm12.sb2");
p = Runtime.getRuntime().exec("C:\\Program Files\\Scratch 2\\Scratch 2.exe C:\\Users\\Admin\\Desktop\\scratch files new.sb2");
//Runtime.getRuntime().exec("taskkill /F /IM <p>.exe");
//p.destroy();
//r.exec("C:\\Windows\\notepad.exe C:\\Windows\\ss.txt");
//this.setDefaultCloseOperation(EXIT_ON_CLOSE);
A4S a4sObj = new A4S(new String[] {jComboBox2.getSelectedItem().toString()}); //defaultline
//A4S a4sObj = new A4S(new String[]{"COM16"}); //addedline
//r.gc();
//this.setDefaultCloseOperation(EXIT_ON_CLOSE);
} catch (IOException ex) {
Logger.getLogger(serialportselection.class.getName()).log(Level.SEVERE, null, ex);
}
finally{
//p.destroy();
//System.gc();
// }
}
Here is the code i tried. But none seems to work.
Move all Process related work into separate Thread.
Use waitFor method to recognise Process end - then you are free to
exit your app.
As I can understood you used SWING for creating UI.
You can set
yourFrame.setDefaultCloseOperation(EXIT_ON_CLOSE);
for your frame. This must help.
What I am trying to do is check if a check box is enabled from another method that is also running on another thread. I am fairly new to Java so I apologise in advanced if my code isn't how Java is usually written (or if it is written badly).
So I've made a method that created a iframe then adds a check box to it. I've removed the part which creates the jframe just to keep my code minimal - you can see it below:
private void initialize() {
chckbxEnabled.setHorizontalAlignment(SwingConstants.LEFT);
chckbxEnabled.setForeground(Color.WHITE);
chckbxEnabled.setBounds(98, 123, 81, 23);
frame.getContentPane().add(chckbxEnabled);
}
I've then created a new method in a new thread and called it from another method which I haven't shown here.
static Thread thread = new Thread(new Runnable() {
public void getPing() throws IOException, InterruptedException {
while (true) {
System.out.println(chckbxEnabled.isEnabled());
if(chckbxEnabled.isEnabled()) {] // Part I am having trouble with
String apiKey = "exmapleApiKey";
URL url = new URL("http://example.com/ping.php?mode=get&apikey="+apiKey);
URLConnection yc = url.openConnection();
BufferedReader in = new BufferedReader(
new InputStreamReader(
yc.getInputStream()));
String inputLine;
inputLine = in.readLine();
}
Thread.sleep(1000);
}
}
public void run() {
try {
getPing();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
As you can see I am trying to access chckbxEnabled.isEnabled(). This worked because just after I made my main class I added private static JCheckBox chckbxEnabled = new JCheckBox("Enabled");. So I can access it but it always returns true when I print it even though the check box is sometimes checked.
So my question is what is a better way of doing this as I expect that way I have experimented with is 'messy' and not the way it should be done?
You are mixing up methods:
isEnabled is for checking if the user can interact with the user (think greyed out elements)
isSelected is what you are looking for (check for the checkmark inside the box). You might want to take a look at ItemListener (example)
Also: keep in mind that you can draw to the api only form the gui thread.
Update:
So: most gui frameworks allow only one thread to draw the gui, since synchronisation is very complex. Therefore most of swing is not thread safe. A good answer outlining this (actually related to swing), can be found here
Quote:
A note on thread safety: It may seem strange that such an important
part of the Java platform is not thread safe. It turns out that any
attempt to create a thread-safe GUI library faces some fundamental
problems. For more on this issue, see the following entry in Graham
Hamilton's blog: MultiThreaded toolkits: A failed dream?
Given that we have to draw the gui from a single thread, what does this mean?
Update operations, i.e. changing a labels text should not be done from a thread you spawned, but should be done from the main thread that runs your gui code (in swing it is called event dispatch thread(in the swing trail).
A tutorial on how to have worker threads that update the gui can be found i.e. here. the basic idea is to have a backgound thread do the calculations and return the result. There is SwingWorker to help with this. The gui thred will then update the gui.
A introduction to concurreny and swing is i.e. here
I am creating a Transliterating tool in Java. It's almost complete.
But, when I type so fast the GUI freezes.
So, I debugged the application to pinpoint the command where it is happening.
The call to method JTextField.modelToView(pos) causes this, which further calls TextUI.modelToView(JTextComponent c, int pos).
It appears, this method first acquires lock on text component's document by calling AbstractDocument::readLock() method, whose source code is:
public synchronized final void readLock() {
try {
while (currWriter != null) {
if (currWriter == Thread.currentThread()) {
// writer has full read access.... may try to acquire
// lock in notification
return;
}
wait();
}
numReaders += 1;
} catch (InterruptedException e) {
throw new Error("Interrupted attempt to aquire read lock");
}
}
Which calls wait() if current thread is not the writer thread.
But, I am only mutating document when space key is pressed, which I believe happens in EDT. And, Swing would also be mutating it in EDT. Also, I am calling JTextField.modelToView(pos) when DocumentListener.insertUpdate(DocumentEvent) is invoked.
Then, what is the reason, the application freezes!
Here are the screenshots:
The application screenshot
When Application freezes
If I minimize and maximize the window
I am calling JTextField.modelToView(pos) when DocumentListener.insertUpdate(DocumentEvent) is invoked.
The Document has not been updated completely when the DocumentEvent is fired. Wrap your code in the DocumentListener in a SwingUtilities.invokeLater(...). This should cause your event code to be executed after the Document has finished updating itself.
I have a c++ application which runs for a long time and I want to track the progress of it. I have a user interface for this application in java. Can anyone please tell me how to track the progress of the native application using JProgressBar. My native application returns an integer when it is done and I have a "Done" button that shows up when this integer is returned. But I want to have a progress bar that shows that the native application is running.
The only ways would be to either create a callback in java (meaning the code in c++ would call the java function) to inform of the current progress or create a function that the java code calls to get the current progress of your task.
http://www.codeproject.com/Articles/22881/How-to-Call-Java-Functions-from-C-Using-JNI
The java code would then use the value to update the jprogress bar.
Another possible simpler solution from Adam's is to have your C++ program output an update of progress to standard output, perhaps a String representation of the percent of progress. The Java program's Process would then have its OutputStream monitored by calling getInputStream() on the Process (yeah, it's not a typo; it's getInputStream()) in a thread background to the Swing thread, and use the information for updating the JProgressBar.
As others have said you need to have a way for your java application to know how far alone your c++ application is.
If you want a quick fix, use a JProgressBar and set it to interdeminate. It will animate the bar to show you something is happening. Once your process returns set the bar to 100%.
Easy way:
ProcessBuilder processBuilder = new ProcessBuilder(command);
JProgressBar progressBar = new JProgressBar();
progressBar.setIndeterminate(true);
Process p = processBuilder.start();
p.waitFor();
progressBar.setIndeterminate(false);
progressBar.setValue(progressBar.getMaxValue());
Better way:
ProcessBuilder processBuilder = new ProcessBuilder(command);
JProgressBar progressBar = new JProgressBar();
processBuilder.redirectErrorStream(true);
Process p = processBuilder.start();
InputStream is = p.getInputStream();
try {
in = new BufferedReader(new InputStreamReader(is, "UTF-8"));
while ((line = in.readLine()) != null) {
//error checking
int progressValue = Integer.parseInt(line);
progressBar.setValue(progressValue);
} finally {
in.close();
}
}
progressBar.setValue(progressBar.getMaxValue());
I am creating a small swing application which plots a set of points given in a file. Guidelines suggested me to invoke a new thread for the GUI, for which I used the following code.
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new View().setVisible(true);
}
});
One of the scenario in the application is to open a file (which is done using a JFileChooser).
private void openMenuItemActionPerformed(java.awt.event.ActionEvent evt) {
int returnVal = fileChooser.showOpenDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
//some heavy operations
} else {
System.out.println("File access cancelled by user.");
}
}
There are some heavy operations that are needed to be done, before proceeding to plot the points.
My questions are, is it advisable to place heavy codes in the GUI thread ? Is it possible to send the file object to the main thread for processing and send the results to GUI thread ?
Please note that I have no idea about Java Threading API.
use SwingWorker
SwingWorker proposes a way to solve it by performing the time-consuming task on another background thread, keeping the GUI responsive during this time.
take a look at this
http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html
http://www.theeggeadventure.com/wikimedia/index.php/SwingWorker_Example
http://weblogs.java.net/blog/mkarg/archive/2010/01/03/did-you-know-swingworker-can-send-progress-status
http://www.javaworld.com/javaworld/jw-06-2003/jw-0606-swingworker.html
If the result of the long running task modifies a Swing component, you can use SwingWorker. For more information, please see Worker Threads and SwingWorker.