Getting and Setting a Flag variable in a thread - java

I am interfacing with a JNI that allows me to use a fingerprint scanner. The code I have written takes the scanned ByteBuffer parsed back to it by the JNI and turns it into a BufferedImage for saving.
What I can't figure out is how to wait for the scan thread to finish before the the jlabel icon on my GUI tries to update. What would be the easiest way to do this?
What else do I need to add?
Edit:
//Scanner class
Thread thread = new Thread() {
public void run() {
// [...] get ByteBuffer and Create Image code
try {
File out = new File("C:\\Users\\Desktop\\print.png");
ImageIO.write(padded, "png", out);
// [???] set flag here
} catch (IOException e) {
e.printStackTrace();
}
}
};
thread.start();
return true;
//Gui class
private void btnScanPrintActionPerformed(java.awt.event.ActionEvent evt) {
Scanner scanPrint = new Scanner();
boolean x = scanPrint.initDevice();
//Wait for the scanning thread to finish the Update the jLabel here to show
//the fingerprint
}

Not sure if you are using Swing or Android for UI but you would want to notify the main event dispatch thread (in swing it is called just that). You would run the scanning thread, then when complete send a 'message' to the EDT with the action that you want to be done to the button.
Thread thread = new Thread(new Runnable(){
public void run(){
//scan
SwingUtiltilies.invokeLater(new Runnable(){
//here you can update the the jlabel icon
public void run(){
jlabel.setText("Completed");
}
});
}
});
In UI development there is no waiting for an action to complete because you always want the EDT to be responsive.

at the end of a the scan thread, use SwingUtilities.invokeLater() to update the gui with the results of the scan.

Related

why i can't do anything in my application when Jbutton is pressed and performing its defined function in java?

this is how I'm trying to accomplish this:
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Hello there");
Thread.sleep(1000);
panel.updateUI();
}
});
I set Enter button as the default button so when I keep pressing it the button press maybe 100 times or more but because I'm using Thread.sleep(1000) it takes some time so I have time to type in my JtextField or even close the window but can't do anything.
also, I tried to put btnNewButton.addActionListener() in the run method of a thread but no difference.
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Hello there");
Thread.sleep(1000);
panel.updateUI();
}
});
}
});
thread.start();
// I used try catch block in real code
can anyone help me to solve the issue?
**I'm creating this application in eclipse using windowsBuilder.
This is because of something that is called EDT - the Event Dispatch Thread.
This special purpose thread is responsible for all the events in your GUI - including drawing (refreshing) and interactions (button click). This means, that exactly the same thread is used to draw your application as the one that is used to execute actionPerformed code. Since you are literally halting that thread for some amount of time, your application will be non responsive for that exact period of time.
Whatever is being executed on user interactions should be short and execute fast for the reason of not blocking the application. If you need to do some heavy stuff, there is a facility for that purpose called SwingWorker that allows you to easily do some processing in the background thread (pool) and schedule UI updates during execution (like update of progress bar)
In your second "thread" snippet, your thread is not doing anything beside adding actionListener to the button, and then it terminates (probably after less than 1ms ;)) - action callback is still executed by the EDT. If you would start that custom thread from inside of run method - then it would be indeed in parallel and GUI would not be frozen - but again, SwingWorker is the way to go here.
Not entirely sure what your code is supposed to do, but if you want to press the button and then 1000ms later it will check your field you should do something like this:
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("before 1000ms");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("after 1000ms");
System.out.println("Reading the text field ...");
}
});
thread.start();
System.out.println("after the thread");
Output:
after the thread
before 1000ms
after 1000ms
Reading the text field ...

wait for GUI created by event dispatch thread

I've got a class that creates and runs a thread, which creates a GUI.
I want the initial class to remain suspended until the GUI is closed (OK button for example)
I tried thread.join(); but since the GUI is created on the event dispatch thread this does not seem to work, and the class continues as the GUI pops up.
private void CreateAndRunThread(){
GUIMaker GM= new GUIMaker(data);
GM.run();
try {
TFM.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
MessageDialog.showDialog("GM Done");
}
thread's GUI creation:
#Override
public void run() {
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//Turn off metal's use of bold fonts
UIManager.put("swing.boldMetal", Boolean.FALSE);
CreateAndShowGUI(frame); //adds frame, packs and sets visible
}
});
}
Use CountDownLatch:
CountDownLatch latch = new CountDownLatch(1);
Call the following in the inital class to block:
latch.await();
Call the following when the GUI is closed:
latch.countDown();
Also it seems that you are not starting thread properly. You need to call GM.start() method instead of GM.run().

JLayer Player overwrites refesh of SWT widgets when placed in a loop

I am attempting to make an application that retrieves images and .mp3 files and transitions from one image to the next once the audio has finished. The underlying framework of how I transition between these images is a little convoluted, but I have managed to get an action in SWT that successfully enables me to manually transition from one to the next. However, a problem has arisen when I've tried to automate it; when placed into a loop, my playAudio() method begins before all of the calls I make in my displayShow() method have resolved, which results in a blank window, despite the audio still playing.
Here is the run method for the action that I want to start the show:
Action startAction = new Action("Start") {
public void run() {
//do {
displayShow();
playAudio();
//} while(true);
}
};
Here is playAudio(). I am able to PLAY the audio without incident:
public void playAudio() {
final String audio = "Happy_Birthday.mp3";
audioLatch = new CountDownLatch(1);
audioThread = new Thread() {
public void run() {
try {
Player player = new Player
(new BufferedInputStream
(new FileInputStream(audio)));
player.play();
audioLatch.countDown();
} catch (JavaLayerException e) {
} catch (FileNotFoundException e) {
} catch (Exception e) {
}
}
};
audioThread.start();
try {
audioLatch.await();
} catch (InterruptedException e) {
}
}
And here is displayShow():
private void displayShow() {
new Thread() {
public void run() {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
Control[] children = container.getChildren();
for (int i = 0; i < children.length; i++) {
children[i].dispose();
}
show.showSlide(container);
container.layout();
}
});
}
}.start();
}
show.showSlide returns a composite whose parent is container, which is the immediate child of the highest parent composite. Within the newly created composite, an image is added to a label and the label's parent is assigned to composite. I realize whether displayShow() is in a separate thread or not seems to be immaterial; this was just the last thing I tried.
It is not solely the addition of the loop that causes the refresh to not execute. The only way I can get the manual transition to work is if I remove the CountDownLatch from the playAudio() method. Were I to remove this latch, the only way to encase these two methods in a loop would be embedded while loops, which seem to hog a fair amount of the CPU and still does not solve my problem. Am I missing anything?
The audioLatch.await() is blocking the main program thread, this is the thread that all SWT operations run on so the Display.asyncExec runnables are just being queued until the thread is available.
If you really must wait in the playAudio method you could run the display event loop there until the background thread is finished:
while (! background thread finished)
{
if (!display.readAndDispatch())
display.sleep();
}

Managing thread from a mouseclick

May be it is a basic question. But I'm a little confused about it. In my design I've a thread that is started from a mouse click. Method looks something like this:
Runnable r = new Runnable(){
public void run(){
A.firstMethod();
A.SecondMethod();
B.FirstMethod();
B.SecondMethod();
B.ThirdMethod();
}
};
new Thread(r).start();
Here B.FirstMethod(), B.SecondMethod(), B.ThirdMethod(); are accessing same variables and do some database operations during execution (i.e. locking, reading, writing etc.). But, If mouse is clicked during the execution or before finishing all the tasks I often get error message from database. How can I handle such type of situations. Here I cannot force the user to wait just with a simple Progressbar.
To handle such situation, you can disable the button once the thread has started its execution, and enable it again once the thread is going to finish its execution.
The code will then look like following:
Runnable r = new Runnable()
{
public void run()
{
button.setEnabled(false);
A.FirstMethod();
A.SecondMethod();
B.FirstMethod();
B.SecondMethod();
B.ThirdMethod();
button.setEnabled(true);
}
};
new Thread(r).start();
Or when the button is clicked, you can use a boolean variable to check if the thread is in progress or not, and then decide as to what needs to be done like:
volatile boolean inProgress = false; // Instance Variable
Runnable r = new Runnable()
{
public void run()
{
inProgress = true;
A.FirstMethod();
A.SecondMethod();
B.FirstMethod();
B.SecondMethod();
B.ThirdMethod();
inProgress = false;
}
};
if(!inProgress)
new Thread(r).start();
else
Popup some message perhaps

JProgressBar indeterminate thread

I have a problem while creating a JProgressBar which is set to indeterminate.
The following code is my implementation of the JProgressBar and is called/constructed from another class:
public class Progress implements Runnable
{
private JFrame frameProgress;
private JProgressBar progressBar;
public Progress(String title, String message)
{
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (Exception e)
{
GlobalVariables.LOGGING_logger.error("Error instatiating progress bar.",
e);
}
UIManager.put("ProgressBar.selectionForeground", Color.black);
UIManager.put("ProgressBar.selectionBackground", Color.black);
this.frameProgress = new JFrame(title);
this.frameProgress.setIconImage(GlobalVariables.GUI_icon.getImage());
this.frameProgress.setSize(300, 60);
this.frameProgress.setLocation(16, 16);
this.progressBar = new JProgressBar();
this.progressBar.setStringPainted(true);
this.progressBar.setString(message);
this.progressBar.setIndeterminate(true);
this.frameProgress.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.frameProgress.add(this.progressBar);
this.frameProgress.setResizable(false);
this.frameProgress.setVisible(true);
}
public void start()
{
new Thread(this).start();
}
public void close()
{
this.frameProgress.dispose();
this.frameProgress = null;
this.progressBar = null;
}
#Override
public void run()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
// do nothing, because progress bar is indeterminate
}
});
}
}
The caller of this JProgressBar is the following code snippet:
Progress p = new Progress("bla", "blub");
p.start();
boolean successfull = xmlWriter.writeCommonSettingsFromGUI(this);
p.close();
And now i want, while the xmlWriter.writeCommonSettingsFromGUI(this); is doing something, that the JProgressBar is shown to the user and is working while the algorithm is running.
How can I achieve this? I don't know so much about threading and searched in many other forums, but I don't found any answer for my question.
Please help me and thank you in advance ;)
EDIT:
The Progress JFrame opens up with no content for that time, the algorithm is running.
You are probably facing concurrency issues with Swing. Assuming that the following code runs on the EDT (Event Dispatching Thread):
Progress p = new Progress("bla", "blub");
eventually, this will open a JFrame with a progress bar in it.
I would consider using a JDialog instead of a JFrame
I would not force the size of the JFrame, but rather call pack()
Then, still running on the EDT (and thus blocking all UI-events such as repaint, mouse clicks, etc...), you call p.start() which starts a new Thread() which will invoke run() which itself calls
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
// do nothing, because progress bar is indeterminate
}
});
This basically won't do anything except push an additional event on the EventQueue and it will run after all currently pending events. This event will run... "nothing" since your Runnable is just empty. The new Thread dies almost immediately. So all this code is useless.
Still pursuing on the EDT, you call boolean successfull = xmlWriter.writeCommonSettingsFromGUI(this); (btw, "successful" ends with only one 'l'). This will continue on blocking the EDT, preventing repaints from occurring and preventing the JProgressBar from painting itself. Eventually you will dispose the JFrame but since all this code is running on the EDT, the user will not see much of the progress bar and the UI will look frozen.
Consider reading the Swing tag wiki (especially the very last part with 3 important links).
Using a SwingWorker should help you out in this.

Categories

Resources