Update JProgresBar located inside EventQueue.InvokeLater - java

I have a problem with updating JProgressBar:
//Start to search for files on drives
private void searchForDICOMFIles2(ArrayList<String> foundDriveLetters)
{
//Thread 1 - search for DICOM files and add them to array
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
////here is the problem
for (String currentDriveLetter_2:foundDriveLetters)
{
File currentDrive_2 = new File(currentDriveLetter_2);
checkFilesAndFoldersForDICOMFiles(currentDrive_2);
}
//updating here will work
Screen_ImportingFiles.setCheckMarkForTaskLabel(1);
Screen_ImportingFiles.updateProgressBar(25, 1, true);
} catch (Exception e) {
e.printStackTrace();
Method checkFilesAndFoldersForDICOMFiles is a huge FOR loop which iterates through files on drive and searches for DICOM files based on extension and if there is no extension, it tries to read the file to determine if it is DICOM or not. Based on the number of files, it also wants to display progression of file checking (i.e. 50% would mean it checked 150 file out of 300). When I want to update progress bar from this method it is not updating progression Bar on JFrame.
Is there a way how to update progress bar like this?

Related

Download CSV through HtmlUnit and read into array

I have a page that has a button to download information in the format of a CSV file. The button opens a confirm dialog to download the file. I need to store that file to a temporary location (whether that be memory or saving to an actual file and then deleting it after) and then read the data in the CSV to an array.
I've tried the code in these questions (question 1, question 2, question 3, and question 4), and it's not quite what I need - mostly because they weren't downloading a CSV and using the data in it.
I'm not sure that the ConfirmDialog is being opened, but I did add a ConfirmHandler returning true to attempt to download the file. However, I don't know where the file is downloading if it is at all.
Here's what I have happening and where I get stuck:
I log in just fine. I go to a report generator. I generate a report that opens in a new window. The new window opens fine and I catch it with a WebWindowListener. I then search for the "save as CSV" button on the new window. I can find that, and I can click on it, but a System.out.print call shows that the ConfirmHandler isn't firing.
for (DomElement e : newPage.getElementsByTagName("button")) {
int i = 0;
webClient.setConfirmHandler(new ConfirmHandler() {
private static final long serialVersionUID = 1L;
#Override
public boolean handleConfirm(Page arg0, String arg1) {
System.out.println("Test"); //isn't firing
return false;
}
});
if (((HtmlButton) e).getAttribute("onclick").contains("CSV")) {
((HtmlButton) e).click();
}else {
if (i++ == (newPage.getElementsByTagName("button").size() - 1)) throw new AssertionError("CSV button not found");
}
}
The inspiration for this answer came from this answer.
I really wanted to get the CSV information without downloading the file, and so I, inside of the webWindowContentChanged(arg0) method of my webWindowListener, just used arg0.getWebWindow().getEnclosingPage().getWebResponse().getContentAsString() and then used String.split() a couple times to get the information I wanted.
Here's what the code looks like so it's a little clearer:
webClient.addWebWindowListener(new WebWindowListener() {
#Override
public void webWindowContentChanged(WebWindowEvent arg0) {
if (CSVclicked) { //boolean that is set true when I click the download button...
String CSV = arg0.getWebWindow().getEnclosedPage().getWebResponse().getContentAsString();
//do things...
CSVclicked = false; //don't use the same behavior next time the method is called...
}
}
});

Slow Multithreading in Java - Air Percussion project

I am creating "Air Percussion" using IMU sensors and Arduino to communicate with computer (3 separate IMUs and Arduinos). They are connected to the computer through USBs. I am gathering data on separate Threads (each thread for each sensor). When I connect only one "set" my program is working really fast. I can get even 5 plays of sound per second. Unfortunatelly when i am trying to connect 3 sensors and run them on separate Threads at the same time my program slows down horribly. Even when im moving only one of sensors, I can get like 1 "hit" per second and sometimes it's even losing some of the sounds it should play. I'll show only important parts of the code below.
In the main i've got ActionListener for button, where it should start gathering the data. I run there 3 separate Threads for each USB Port.
connectButton.addActionListener(new ActionListener(){
#Override public void actionPerformed(ActionEvent arg0) {
int dialogButton = 1;
if(!flagaKalibracjiLewa || !flagaKalibracjiPrawa){ //some unimportant flags
dialogButton = JOptionPane.showConfirmDialog(null, "Rozpoczynając program bez kalibracji będziesz miał do dyspozycji mniejszą ilość dzwięków. Czy chcesz kontynuować?","Warning",JOptionPane.YES_NO_OPTION);
}else{
dialogButton = JOptionPane.YES_OPTION;
}
if(dialogButton == JOptionPane.YES_OPTION){
if(connectButton.getText().equals("Connect")) {
if(!flagaKalibracjiLewa && !flagaKalibracjiPrawa) podlaczPorty();
Thread thread = new Thread(){
#Override public void run() {
Scanner data = new Scanner(chosenPort.getInputStream());
dataIncoming(data, "lewa");
data.close();
}
};
Thread thread2 = new Thread(){
#Override public void run() {
Scanner data = new Scanner(chosenPort2.getInputStream());
dataIncoming(data, "prawa");
data.close();
}
};
Thread thread3 = new Thread(){
#Override public void run() {
Scanner data = new Scanner(chosenPort3.getInputStream());
dataIncoming(data, "stopa");
data.close();
}
};
thread.start();
thread2.start();
thread3.start();
connectButton.setText("Disconnect");
} else {
// disconnect from the serial port
chosenPort.closePort();
chosenPort2.closePort();
chosenPort3.closePort();
portList.setEnabled(true);
portList2.setEnabled(true);
portList3.setEnabled(true);
connectButton.setText("Connect");
}
}
}
});
in "dataIncoming" method there is bunch of not important things (like picking, which sound should be played etc.). The important part is in the while loop. In the "while" im gathering next lines of data from sensor. When one of the values is higher than something it should play a sound but only if some time has passed and the sensor has moved a certain way. (when the drumstick is going down the "imuValues[4]" is increasing, when its going up its decreasing, so when its past 160 it means that the player has taken the drumstick up so its ready for the next hit)
while(data.hasNextLine()) {
try{
imuValues = data.nextLine().split(",");
if(Double.parseDouble(imuValues[4])>200 && flagaThreada) {
flagaThreada = false;
playSound(sound1);
}
if(Double.parseDouble(imuValues[4])<160 && System.currentTimeMillis()-startTime>100) {
flagaThreada = true;
startTime=System.currentTimeMillis();
}
}catch(Exception e){
System.out.println("ERROR");
}
}
and finally the method for playing the sound is :
public static synchronized void playSound(String sound) {
try {
String url = "/sounds/"+sound+".wav";
Clip clip = AudioSystem.getClip();
AudioInputStream inputStream = AudioSystem.getAudioInputStream(
Main.class.getResourceAsStream(url));
clip.open(inputStream);
clip.start();
} catch (Exception e) {
System.err.println("ERROR IN OPENING");
}
}
Is my computer to slow to compute and play sounds for 3 sensors at the same time? Or is there a way to create those Threads in a better fashion?
I wrote a version of Clip, called AudioCue, which allows multi-threading on the play commands. It is open source, BSD license (free), consists of three files which you can cut and paste into your program. There is also an API link for it. More info at AudioCue. The site has code examples as well as link to API and source code. There is also some dialogue about its use at Java-gaming.org, under the "Sound" topic thread.
The basic principle behind the code is to make the audio data available in a float array, and send multiple, independent "cursors" through it (one per play command). The setup lets us also do real time volume fading, pitch changes and panning. The audio is output via a SourceDataLine which you can configure (set thread priority, buffer size).
I'm maybe a week or two away from sharing a more advanced version that allows all AudioCues to be mixed through a single output line. This version has five classes/interfaces instead of three, and is being set up for release on github. I'm also hoping to get a donate button and the like set up for this next iteration. The next version might be more useful for Arduino in that I believe you are only allowed up to 8 audio outputs on that system.
Other than that, the steps you have taken (separating the open from the play, using setFramePosition for restarts) are correct. I can't think of anything else to add to help out besides writing your own mixer/cue player (as I have done and am willing to share).

Quality issue when playing sound and fast fade-out in Java

Sorry for my bad english
I write a Java desktop application that plays musical instruments audio files samples.
Each time a note is received by the application, it must stop the current playing note and play the new one. if the user stops playing, the app must do a fade-out to the active note.
By the way, smaller latency is better.
I created a runnable which owns a play and stop method allowing me to play or stop a note(with fade out)
My code works but the sound quality is bad(many click and clipping etc)..
-How to improve my code? Did I make mistake?
-Otherwise it is there any other Java technology than JavaFx media player that is best suited for my need?
public class SamplePlayer implements Runnable{
private boolean fadeOut=false; // true when a fade out is needed
private int soundToFadeOut=0; //the sound number to fade out
private int sound=0; // the sound number to play (nothing if zero)
private int lastSound=0; //the last sound number played that wee need to stop befor playing a new one
MediaPlayer[] sample = new MediaPlayer[42]; //array to store all pre-loaded sounds
public SamplePlayer()
{
for(int i=0;i<42;i++) // load all sounds
{
Media pick = new Media(new File("./src/files/samples/1_"+(i+55)+".wav" ).toURI().toString());
sample[i] = new MediaPlayer(pick);
}
}
/**
* Here i try to play a sound each time the sound variable has changed
* and fade out the sound specified in soundToFadeOut variable if fadeOut variable come to true;
*/
#Override
public void run() {
while(true) // bad, but it's just for testing
{
try {
if(sound!=0) // if a sound need to be played
{
if(lastSound!=0) // if i's not the first sound to played i stop the previous one.
{
sample[lastSound].stop();
}
sample[sound].setVolume(1); //returns the volume to 1 in case we made a fade out
lastSound=sound;
sound=0;//sound = 0 to monitor new other sound
}
if(fadeOut==true) // if wee need to make a fade out
{
fadeOut=false;
fadeOut(sample[soundToFadeOut],50);
}
Thread.sleep(1); // if not the thread keep busy and play, stop method not working properly
} catch (InterruptedException ex) {
Logger.getLogger(SamplePlayer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private void fadeOut(MediaPlayer player,double itteration) // fade out method : run a new thread to itterate on volume
{Runnable task = () -> {
try{
for(int i=0;i<itteration;i++)
{
double value=(itteration-i)/itteration; // set value to 1.0 to near 0.0 each itteration
if(value<0.1)
{
value=0;
}
player.setVolume(value);
Thread.sleep(5);
}
}catch(Exception e){e.printStackTrace();}
};
new Thread(task).start();
}
/*
*
* play and stop method which are called when a sound need to be played or stoped (fade out)
*
*/
public void play(int note)
{
sound=note-55; // -55 just to match with our array range
}
public void stop(int note)
{
soundToFadeOut=note-55;
fadeOut=true;
}
}

Increasing screen capture speed when using Java and awt.Robot

Edit: If anyone also has any other recommendations for increasing performance of screen capture please feel free to share as it might fully address my problem!
Hello Fellow Developers,
I'm working on some basic screen capture software for myself. As of right now I've got some proof of concept/tinkering code that uses java.awt.Robot to capture the screen as a BufferedImage. Then I do this capture for a specified amount of time and afterwards dump all of the pictures to disk. From my tests I'm getting about 17 frames per second.
Trial #1
Length: 15 seconds
Images Captured: 255
Trial #2
Length: 15 seconds
Images Captured: 229
Obviously this isn't nearly good enough for a real screen capture application. Especially since these capture were me just selecting some text in my IDE and nothing that was graphically intensive.
I have two classes right now a Main class and a "Monitor" class. The Monitor class contains the method for capturing the screen. My Main class has a loop based on time that calls the Monitor class and stores the BufferedImage it returns into an ArrayList of BufferedImages.
If I modify my main class to spawn several threads that each execute that loop and also collect information about the system time of when the image was captured could I increase performance? My idea is to use a shared data structure that will automatically sort the frames based on capture time as I insert them, instead of a single loop that inserts successive images into an arraylist.
Code:
Monitor
public class Monitor {
/**
* Returns a BufferedImage
* #return
*/
public BufferedImage captureScreen() {
Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage capture = null;
try {
capture = new Robot().createScreenCapture(screenRect);
} catch (AWTException e) {
e.printStackTrace();
}
return capture;
}
}
Main
public class Main {
public static void main(String[] args) throws InterruptedException {
String outputLocation = "C:\\Users\\ewillis\\Pictures\\screenstreamer\\";
String namingScheme = "image";
String mediaFormat = "jpeg";
DiscreteOutput output = DiscreteOutputFactory.createOutputObject(outputLocation, namingScheme, mediaFormat);
ArrayList<BufferedImage> images = new ArrayList<BufferedImage>();
Monitor m1 = new Monitor();
long startTimeMillis = System.currentTimeMillis();
long recordTimeMillis = 15000;
while( (System.currentTimeMillis() - startTimeMillis) <= recordTimeMillis ) {
images.add( m1.captureScreen() );
}
output.saveImages(images);
}
}
Re-using the screen rectangle and robot class instances will save you a little overhead. The real bottleneck is storing all your BufferedImage's into an array list.
I would first benchmark how fast your robot.createScreenCapture(screenRect); call is without any IO (no saving or storing the buffered image). This will give you an ideal throughput for the robot class.
long frameCount = 0;
while( (System.currentTimeMillis() - startTimeMillis) <= recordTimeMillis ) {
image = m1.captureScreen();
if(image !== null) {
frameCount++;
}
try {
Thread.yield();
} catch (Exception ex) {
}
}
If it turns out that captureScreen can reach the FPS you want there is no need to multi-thread robot instances.
Rather than having an array list of buffered images I'd have an array list of Futures from the AsynchronousFileChannel.write.
Capture loop
Get BufferedImage
Convert BufferedImage to byte array containing JPEG data
Create an async channel to the output file
Start a write and add the immediate return value (the future) to your ArrayList
Wait loop
Go through your ArrayList of Futures and make sure they all finished
I guess that the intensive memory usage is an issue here. You are capturing in your tests about 250 screenshots. Depending on the screen resolution, this is:
1280x800 : 250 * 1280*800 * 3/1024/1024 == 732 MB data
1920x1080: 250 * 1920*1080 * 3/1024/1024 == 1483 MB data
Try caputuring without keeping all those images in memory.
As #Obicere said, it is a good idea to keep the Robot instance alive.

Java - How to get Next Image By Button press

I've managed to add an image into a JPanel in netbeans and display it.I wonder how to get to the next one,by pressing a button.
I've added the image using this code:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt){
// TODO add your handling code here:
JFileChooser fileChooser = new JFileChooser();
int result = fileChooser.showOpenDialog(null);
if ( result == JFileChooser.APPROVE_OPTION ){
String Ruta = fileChooser.getSelectedFile().getAbsolutePath();
jTextField1.setText(Ruta);
Icon icon = new ImageIcon(Ruta);
jLabel2.setIcon(icon);
JOptionPane.showMessageDialog(this,"You chose to open this file: " +
fileChooser.getSelectedFile().getName());
}
}
And when i press a button called "jButton2" to get the next image,without manually selecting it again from folder.
For example:
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt){
// TODO add your handling code here:
}
Thank You very much.
You have to enumerate images in the directory you are browsing in. When the user selects the file, you should keep a list of all images from that directory in order to retrieve them when user click the next button. As well you can get the file list whenever the user clicks the next button.
maybe something like this:
private File allFiles;
private int currentIndex;
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
JFileChooser fileChooser = new JFileChooser();
int result = fileChooser.showOpenDialog(null);
if ( result == JFileChooser.APPROVE_OPTION ){
currentFile = fileChooser.getSelectedFile();
String Ruta = currentFile.getAbsolutePath();
jTextField1.setText(Ruta);
allFiles = currentFile.getParent().listFiles(); // maybe you need a filter to include image files only....
currentIndex = indexOf(allFiles, currentFile);
Icon icon = new ImageIcon(Ruta);
jLabel2.setIcon(icon);
JOptionPane.showMessageDialog(this,"You chose to open this file: " + fileChooser.getSelectedFile().getName());
}
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
if (currentIndex+1 < allFiles.length) {
jtextField1.setText(allFiles[++currentIndex]);
}
}
private int indexOf(File[] files, File f) {
for (int i=0; i+1 < files.length; i++) {
if (files[i].equals(f)) {
return i;
}
}
return -1;
}
Get the parent file if the current image (File.getParent()).
Use one of the File.list..() methods to get the image files.
Sort them into some order that means 'next' to the user.
Iterate that connection until you find the current File then display the next one after that.
I am assuming that you want the next image, if possible in the same directory you chose in your first code excerpt. What you could do is that once the user has chosen the image, you could use Apache's FileUtils to get the extension of files. If the file is a JPG, JPEG, PNG, etc you could load it's location in a List of strings.
This will give you a list of picture paths. You could then use the buttons to traverse the list. Once the button is pressed, you move to the next item, load the image and render it.
EDIT: This is how I would go about it step by step:
Create a global variable of type List.
Create a global variable which will act as a counter;
In your jButton1ActionPerformed method:
Get the parent directory of the file that the user has chosen;
Use Apache's FileUtil class to get the extension of the file names. If the file name is an image, such as PNG, JPG, etc, add it (the path of that file) to your list.
In you jButton2ActionPerformed, increment the counter (if the counter is not smaller than the size of your list, re-initialize it to 0, so as to avoid OutOfBoundsExceptions) and load the the file denoted by the counter using similar logic to your jButton1ActionPerformed method.

Categories

Resources