I want to connect sharp network scanner using morena api and twain. Everything is ok if scanner is reachable but when scanner is not reachable, jni library opens a select scanner window. I think it is twain ds screen, I want to disable this screen. If scanner is not reachable, I want to throw error instead of open select device window. When I stop application, this screen also close so I think it depends on java thread. Question is, how can I stop this window's thread without stop whole program. I can run main method in another thread, and I can find this thread id, but when I stop this thread it is not close select device window.
import SK.gnome.morena.Morena;
import SK.gnome.morena.MorenaException;
import SK.gnome.morena.MorenaImage;
import SK.gnome.morena.MorenaSource;
import SK.gnome.twain.TwainManager;
import SK.gnome.twain.TwainSource;
import javax.swing.*;
public class HelloWorld
{ public static void main(String[] args) throws MorenaException
{
TwainSource[] list = null;
try {
list = TwainManager.listSources();
} catch (Exception var4) {
list = null;
}
MorenaSource source= list[1];
System.err.println("Selected source is "+source);
if (source!=null)
{ source.maskUnsupportedCapabilityException(false); // Lesson 3
source.maskBadValueException(false); // Lesson 3
source.setVisible(false); // Lesson 2
source.setColorMode(); // Lesson 2
source.setResolution(300); // Lesson 2
((TwainSource)source).setUnits(TwainSource.TWUN_CENTIMETERS);
source.setFrame(0, 0, 7.8, 10.5);
System.err.println("Image resolution is "+source.getResolution());
MorenaImage image=new MorenaImage(source);
System.err.println("Size of acquired image is "
+image.getWidth()+" x "
+image.getHeight()+" x "
+image.getPixelSize());
}
Morena.close();
}
}
Do you ever want the window itself to pop up? If not you can try TwainManager.getDefaultSource() instead of hardcoding list[1], or TwainManager.listSources() to either build your own selection or evaluate for 0 results and throw your own error.
To use TwainManager.getDefaultSource():
MorenaSource source = TwainManager.listSources();
See Morena's TWAIN JTP Support for more info.
Related
I've been working on this project with a peer for comp sci class, and I can't figure out how to make SFX and music have their own independent volume controls. Both the music and the SFX both play just fine when they need to (hovering/clicking on buttons, menu music, etc), and I made sliders for both of them (music volume and SFX volume), but for some reason only music can be controlled. I have sat here for hours trying to figure out why it doesn't work. The FloatControl gain does update with the slider (I printed out it's value and it was working just fine, just not updating the actual volume of the sound effects). I also got rid of everything to do with the music by commenting out everything regarding it's slider controls, audio input stream, gain control, etc; it was as if SFX was the only audio related thing in the program, but it still didn't work. I don't understand why since the code is identical to the music's code (just that "music" is now "sound").
The below code is not meant to be functional on it's own since the actual code is 605 lines so far and that's too long to post on here. It does contain the core components, so if you want to set it up to work you have to make the JFrame and all the buttons, or have me post the full code and sound files.
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.sound.sampled.*;
import java.awt.event.*;
import javax.swing.border.Border;
import javax.swing.BorderFactory;
import java.io.*;
import java.io.File.*;
import java.io.IOException;
public class AudioTesting {
// Declare Global Objects
static final String[] SFXName = {"menuHover", "buttonEnter", "buttonLeave", "gameStart"};
static final String[] TrackName = {"Bossfight_Incomplete"};
static final String userName = System.getProperty("user.name");
static Clip sound;
static Clip music;
static JSlider musicVolumeSlider;
static JSlider soundVolumeSlider;
public static void main(String []args){
GameSetting();
}
public static void GameSetting(){
musicVolumeSlider = new JSlider(-45,6,6);
soundVolumeSlider = new JSlider(-45,6,6);
musicVolumeSlider.setMajorTickSpacing(5);
musicVolumeSlider.setMinorTickSpacing(1);
musicVolumeSlider.setPaintTicks(true);
//musicVolumeSlider.setPreferredSize(new Dimension(SLIDER_SIZE_X,SLIDER_SIZE_Y));
// musicVolumeSlider.setBackground(menuColor);
musicVolumeSlider.addChangeListener(new SliderListener());
soundVolumeSlider.setMajorTickSpacing(5);
soundVolumeSlider.setMinorTickSpacing(1);
soundVolumeSlider.setPaintTicks(true);
// soundVolumeSlider.setPreferredSize(new Dimension(SLIDER_SIZE_X,SLIDER_SIZE_Y));
// soundVolumeSlider.setBackground(menuColor);
soundVolumeSlider.addChangeListener(new SliderListener());
}
//manages the loading and playing of sfx
public static void SFXManager(int sfx){
try{
sound = AudioSystem.getClip();
File sfxFile = new File("C:\\Users\\" + userName + "\\Documents\\" + SFXName[sfx] + ".wav");
sound.open(AudioSystem.getAudioInputStream(sfxFile));
}catch (Exception ex){}
sound.flush();
sound.start();
}
// manages the loading and playing of music tracks
public static void MusicManager(int track){
try{
music = AudioSystem.getClip();
File musicFile = new File("C:\\Users\\" + userName + "\\Documents\\" + TrackName[track] + ".wav");
music.open(AudioSystem.getAudioInputStream(musicFile));
}catch (Exception ex){}
music.start();
music.loop(Clip.LOOP_CONTINUOUSLY);
}
static class SliderListener implements ChangeListener {
public void stateChanged(ChangeEvent e) throws IllegalArgumentException {
float currentMusicVolume = 0;
float currentSoundVolume = 0;
FloatControl musicGainControl = (FloatControl) music.getControl(FloatControl.Type.MASTER_GAIN);
FloatControl soundGainControl = (FloatControl) sound.getControl(FloatControl.Type.MASTER_GAIN);
//-------------------------------------------------------------PROBLEM AREA v v v
//For changing the volume of the music (this works just fine)
if (e.getSource() == musicVolumeSlider){
currentMusicVolume = musicVolumeSlider.getValue();
//if the slider is all the way at it's lowest, set the volume to -80 (i.e. mute)
if (currentMusicVolume == -45){
currentMusicVolume = -80;
}
musicGainControl.setValue(currentMusicVolume); // Reduce volume by slider value
}
//for changing the volume of the sfx
if (e.getSource() == soundVolumeSlider){
currentSoundVolume = soundVolumeSlider.getValue();
//if the slider is all the way at it's lowest, set the volume to -80 (i.e. mute)
if (currentSoundVolume == -45){
currentSoundVolume = -80;
}
soundGainControl.setValue(currentSoundVolume); // Reduce volume by slider value
}
}
}
//-------------------------------------------------------------PROBLEM AREA ^ ^ ^
// I didn't implement it in here, but here is where all the mouse and event listeners go for the different buttons
// If a button is hovered over or pressed, it plays a sound from the index that corresponds with that sound
// I.e. if you hover over a button, call SFXManager(0); which plays the first sound in the array (buttonHover.wav) etc.
}
I've found these float controls to be kind of hit-or-miss, in part because they depend on the local PC and its OS. It's often the case that only the master gain works, if you want to change volumes in real time. The master gain changes will affect ALL the playing sounds.
You could follow the suggestion from the last paragraphs of the Oracle sound tutorial on audio controls and write your own volume controls. To do so requires intercepting the audio input stream, compiling the bytes into PCM, multiplying the PCM by a volume factor, converting the PCM back to bytes, and finally, shipping the bytes out via a SourceDataLine.
This is basically the plan I followed when I wrote AudioCue. You are welcome to use that code base as an example for rolling your own, or to import and directly make use of the files within your project. I tried to follow the Clip API as closely as I could, while adding real time volume controls for each playing audio instance. One limitation is that it only works with wav files. But if you can work with that, feel free to use the library. I'm happy to answer any questions if you have any trouble setting it up.
I'm currently learning how to make the program available as a Maven resource. I'm not clear on how the Gradle instructions work--another contributor did that part. It is pretty easy to just copy the five files into your project and use them with just a little tinkering to the import/package lines.
I have a basic text based Java app. I want the user to be able to enter sensitive info (password) in a text editing session that only exists for that purpose.
A bit like with git you get a temporary session/file in vi (or another set editor) to edit comment and save/quit - then the git process resumes and consumes that file. The file is (probably) deleted or at least forgotten about.
Do not need any advanced editor capabilities, just basic typing, backspace etc.
I want the user to be able to see what they're typing BUT once they have typed a password, it must be erased from screen. So plain STDIN won't work as the input remains on the screen.
How can I do it in Java or for that matter in another language?
I have looked at Scanner (basically STDIN) and Console.readPassword (user cannot see what they type).
Perhaps a solution that involves STDIN and immediate erasure of the typed line could be acceptable. But emulating git/vi interplay is more attractive because it's arguably a bit more standard.
EDIT: I have implemented something close - create temp file and run notepad.exe on that, let user save and close notepad, read from temp file, delete it. Simple but it relies on an external tool, needs to be adjusted to run on linux as well.. I would like something more seamless where the behaviour is emulated within the java app itself
Swing is pretty consistently available, here is an example of a method that opens a window, waits until the window is closed, and returns the text.
import javax.swing.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.awt.EventQueue;
import java.awt.event.*;
public class EditMe{
LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>(1);
public void showEditor(){
JFrame frame = new JFrame("edit text");
JEditorPane pane = new JEditorPane("txt", "");
frame.add(pane);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.addWindowListener( new WindowAdapter(){
#Override
public void windowClosed(WindowEvent evt){
try{
queue.put(pane.getText());
} catch(InterruptedException e){
//not really possible, but just incase.
throw new RuntimeException(e);
}
}
} );
frame.setSize( 640, 480 );
frame.setVisible(true);
}
public static String getText() throws InterruptedException{
EditMe me = new EditMe();
EventQueue.invokeLater( ()-> me.showEditor() );
return me.queue.take();
}
public static void main(String[] args) throws Exception{
System.out.println("waiting for response");
String s = getText();
System.out.println("response received: \n" + s);
}
}
This would be about equivalent to a notepad solution, but it uses swing that comes with standard jdk's. (There are headless jdk's that don't include swing.)
What I am doing is making a program that constantly takes screenshots of the users desktop and saves them as long as the user wants. I was initially placed a call to the method that captures in a while method but that was too slow and I need as many images take as soon as possible. What I decided to do was use threading.
While the program is running my PC get's slow (ie mouse flashes, moves slow, ect) and when I stop the program I get the following error.
Exception in thread "Thread-294" java.lang.OutOfMemoryError: Java heap space
at sun.awt.windows.WRobotPeer.getRGBPixels(Unknown Source)
at java.awt.Robot.createScreenCapture(Unknown Source)
at maple.Record.run(Record.java:29)
Here is the line that produces the error.
img = r.createScreenCapture(new Rectangle (0, 0, width, height));
Here is my class that contains the thread.
import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Vector;
import javax.imageio.ImageIO;
import javax.media.MediaLocator;
public class Record implements Runnable {
Robot r;
static int width = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();
static int height = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
BufferedImage img;
public static boolean stop = false;
public void run() {
try {
r = new Robot();
img = r.createScreenCapture(new Rectangle (0, 0, width, height));
ImageIO.write(img, "png", new File(JavCapture.tmpLocation + "\\tmp\\" + System.currentTimeMillis() + ".png"));
} catch (IOException | AWTException e) { e.printStackTrace(); }
}
}
The error is produced when I am calling the JpegImagesToMovies that has been edited to work with .png files.
Please check out this link for more information on that.
How can I solve the problem, and how can I make the thread use less memory so that it doesn't slow the PC down.
Here is the call in the main method.
do {
(new Thread(new Record())).start();
} while (!Record.stop);
From the looks of it you are creating a separate thread for every screenshot, this will run you out of memory very fast. Instead you should have a single thread that sits in loop, sleeps and takes screenshots from time to time.
public class ScreenshotTaker implements Runnable {
private volatile boolean done = false;
public void run( ) {
while (!done) {
... take screenshot...
...sleep ...
}
}
public void setDone( ) {
done = true;
}
}
You're asking for trouble, you should go for some Threadpool implementation that would limit your thread count. To get idea on usage, see the official tutorial: http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html
As in your solution:
do {
(new Thread(new Record())).start();
} while (!Record.stop);
you create threads faster than they can process their job. Basically you just say create many threads as fast as possible, there is no guarantee on count of them processed till new one is created. So it's just a question of time till program dies (resources are exhausted = CPU + Memory)
You should limit the thread creation process here
(new Thread(new Record())).start();
Those threads start almost together and bloats your memory up.
With so little code to go with it is hard to say, but you should definitely make the following:
Robot r;
BufferedImage img;
into local variables instead of instance variables. The way you have it, the objects they refer to will be reachable for much longer than your program actually needs them. That's one road to an OutOfMemoryException.
I am not sure how to explain this. But I'll try.. Fest slows down to crawl while working with JXTreeTable of swingx. It doesn't slow down initially. It works fine for a while, but after a while when the same actions are repeated it slows down badly.
I have raised a bug for this in github. Please tell me if this is something that I am doing wrong instead. I am not able to reproduce the problem when I tried to create an SSCCE.
Anyway, here's a video of it slowing down.
http://screencast.com/t/liNttCw2In0w
At times 0.39s to 0.40 a set of operations are performed. These are done when there is one row in the JXTreeTable.
At time 0.49 to end of recording the same operation is repeated but there are now 3 rows in the table, it takes very long for the mouse to click.
I have attached a screenshot taken at the time when fest slows down, which attempts to explain it more
This is the code that does the work:
Step 1) Selecting a node from the tree is done as below:
JTreeFixture folioTreeFixture = importShareholders.panel("treePanel").tree("folioTree");
folioTreeFixture.separator("~");
folioTreeFixture.selectPath(new StringWrapper("Shareholders", true)+"~"+
(ShareType.isEquity(shareType) ? new StringWrapper("Equity Folios", true) : new StringWrapper("Preference Folios", true))+"~"+
new FolioTreeRep(folio.getName(),folioNo, shareType).toString());
Step 2) Searching and selecting a row from the JXTreeTable
int selectRow=-1;
JTableFixture table=importShareholders.table("historyTable");
for(int i=0;i<table.rowCount();i++){
String certificateNumber = table.cell(TableCell.row(i).column(ShareholderHistoryTable.columnIndex(ShareholderHistoryTable.CERT_NO))).value();
String remarks=table.cell(TableCell.row(i).column(ShareholderHistoryTable.columnIndex(ShareholderHistoryTable.REMARKS))).value();
if(StringUtils.isEmpty(remarks) && StringUtils.isNotEmpty(certificateNumber) && Integer.parseInt(certificateNumber)==certNo){
selectRow=i;
break;
}
}
if(selectRow==-1){
fail("Couldn't find certificate number to transfer");
}
Step 3) Showing the pop up menu and clicking the row
table.showPopupMenuAt(TableCell.row(selectRow).column(0)).menuItem("btnTransfer").click();
I am not sure why its slowing down. Please let me know if there is any more info I can help with. Would be grateful for some help in solving the problem
I have profiled the application and I dont find anything untoward happening. I dont have a lot of experience profiling applications. I would be grateful if someone could have a second look at this. I profiled it with yourkit and have uploaded the snapshot dump here:
https://www.dropbox.com/s/dh976v01q9c3sgj/ImportShareholderData.shouldTransferAndSplit-2013-06-14-shutdown.snapshot.zip
Any help will be greatly appreciated..
EDIT:
I think I forgot to mention the same thing works when I do it manually. It only slows down with fest. That leads me to believe that there is an issue with fest maybe?
Sorry about that.
EDIT 2:
As request by Marcin (sorry for the delay Marcin).. Here's the code when the first row is getting split
public List<Integer> splitRowEqually(ShareType shareType, String date, int folioNo, int certNo, int... certnos) throws NoSuchFieldException, TorqueException {
//select a tree node
selectFolioInTree(shareType, folioNo);
Pause.pause(new Condition("Wait until tab is created") {
#Override
public boolean test() {
return importShareholders.tabbedPane().tabTitles().length>0;
}
});
//select a row on the table to split
int row=selectRowWithCertNunber(certNo);
List<Integer> rowsIndexes=new ArrayList<Integer>();
JTableFixture table = importShareholders.table();
//show popup menu on that row and select split
table.showPopupMenuAt(row(row).column(columnIndex(TRANS_TYPE))).menuItem("btnSplit").click();
DialogFixture splitDialog=FinderUtilities.getDialogWithTitle("Split Share Certificate");
splitDialog.textBox("tfDateOfSplit").setText(date);
int noOfShares= Integer.parseInt(table.cell(row(row).column(columnIndex(NO_OF_SHARES))).value());
int distFrom= Integer.parseInt(table.cell(row(row).column(columnIndex(DIST_NO_FROM))).value());
int distTo= Integer.parseInt(table.cell(row(row).column(columnIndex(DIST_NO_TO))).value());
//split the row into the number of times decided by the certnos array
int noOfSharesInEachSplit=noOfShares/certnos.length;
for(int i=0;i<certnos.length;i++){
int distToInSplit = distFrom + noOfSharesInEachSplit-1;
enterSplitRowDetails(splitDialog, certnos[i], distFrom, distToInSplit<=distTo ? distToInSplit : distTo);
distFrom=distToInSplit+1;
rowsIndexes.add(row++);
}
splitDialog.button("btnSplit").click();
return rowsIndexes;
}
//selects a node from the left hand side tree
public void selectFolioInTree(final ShareType shareType,final int folioNo) throws TorqueException {
JTreeFixture folioTreeFixture = importShareholders.panel("treePanel").tree("folioTree");
folioTreeFixture.separator("~");
// I use these wrapper classes - StringWrapper and FolioTreeRep, so that I can get a html
// string for the tree node like <html><b>Shareholder</b></html>
String treePath = new StringWrapper("Shareholders", true) + "~" +
(ShareType.isEquity(shareType) ? new StringWrapper("Equity Folios", true) : new StringWrapper("Preference Folios", true)) + "~" +
new FolioTreeRep(mapOfFolioNames.get(folioNo), folioNo, shareType).toString();
folioTreeFixture.clickPath(treePath);
}
//search the table for a row that contains the cert no provided in the Certificate Number column.
private int selectRowWithCertNunber(int certNo) throws NoSuchFieldException {
int selectRow=-1;
JTableFixture table=importShareholders.table("historyTable");
for(int i=0;i<table.rowCount();i++){
String certificateNumber = table.cell(row(i).column(columnIndex(CERT_NO))).value();
String remarks=table.cell(row(i).column(columnIndex(REMARKS))).value();
if(StringUtils.isEmpty(remarks) && StringUtils.isNotEmpty(certificateNumber)
&& Integer.parseInt(certificateNumber)==certNo){
selectRow=i;
break;
}
}
if(selectRow==-1){
fail("Couldn't find certificate number to transfer");
}
return selectRow;
}
// enter details on the table in the SplitDialog
private void enterSplitRowDetails(DialogFixture splitDialog, int cert, int distFrom, int distTo) {
splitDialog.button("btnAdd").click();
int row = splitDialog.table().rowCount();
splitDialog.table().enterValue(row(row - 1).column(0), String.valueOf(cert));
splitDialog.table().enterValue(row(row - 1).column(1), String.valueOf(distFrom));
splitDialog.table().enterValue(row(row - 1).column(2), String.valueOf(distTo));
}
Emm... It is quite interesting question;
I suppose the question contains less really required details especially the robot integration and IO solutions details so I cannot just give you a proper answer...
Anyway, I'll try to analyze the problem in voice a little bit in my way...
First. According to your screenshot comments, I can notice that all "30s pauses or so" occur on some, as I can get it, stream reading process "select/search" (your app gets some data to output etc). So maybe it is much deeper than you think because it is probably thread problem;
I couldn't find the GuiQuery/GuiTask/GuiActionRunne classes usage in your code snippets so I may suggest the "synch problem" may take place in the mentioned case...
Second. OK... If it is still the thread problem I may suggest the robot and IO solutions are both in some ONE thread (the Main thread or something) because, according to your tips as "At times 0.39s to 0.40 a set of operations are performed. These are done when there is one row in the JXTreeTable." ... GUI is waiting for some process to be completed...
Third.
And again... According to this issue as
"It is recommended to turn on an automated check to verify that all
Swing components updates are done in Swing’s EDT (Event Dispatcher
Thread). For those unfamiliar with the EDT, it is responsible for
handling and updating all Swing widgets in a separate thread, causing
that the application never loses responsiveness to user gestures (just
in short, more about the EDT here). To do that, we add the following
hook to the test:"
import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
import org.junit.BeforeClass;
...
#BeforeClass
public static void setUpOnce() {
FailOnThreadViolationRepaintManager.install();
}
Next step is to launch the frame or dialog. As JUnit runs in its own
thread, we must launch the frame or dialog through Fest, to ensure,
again, that EDT is properly used:
import org.fest.swing.edt.GuiActionRunner;
import org.fest.swing.edt.GuiQuery;
import org.fest.swing.fixture.FrameFixture;
import org.junit.Before;
...
private FrameFixture testFrame;
private AllTypesFrame frame;
...
#Before
public void setUp() {
frame = GuiActionRunner.execute(new GuiQuery<AllTypesFrame>() {
protected AllTypesFrame executeInEDT() {
return new AllTypesFrame();
}
});
testFrame = new FrameFixture(frame);
testFrame.show();
}
... makes me think it is maybe the "thread-problem" which is described in the First and Second tips...
so, as a conclusion, I can say that maybe you have to multi-thread your test a little more because it is obviously some kind of synch problem...
P.S.
#sethu, before you start your debugging I want to point a little...
I still suspect threads conflict is taking place here (see my previous tips) because, as I may notice, your code snippets are showing static expressions usage to invoke methods like Pause.pause(...) or FinderUtilities.getDialogWithTitle(...) etc I cannot see the whole project architecture so it is hard to analyze according the represented bits but it is pretty clear the "manual testing" goes fine because action listeners react in real time but fest testing does the annoying delays because it uses some "timer" to countdown until a click emulation occurs etc and of course it is a background process which needs a separate thread... Watch debugging carefully maybe somewhere in your code UI thread and fest thread do conflict (see static methods, thread.sleep etc) the points where fest thread could block (override) the UI's one... :S By the way what method Pause.pause(...) does?
P.P.S.
If you have some additional information please comment my answer
Report if my answer helps you
I do not know what are your robot settings but you can at least try to set idleTimeout and other timeouts for the robot you use. The default timeout is 10 sec (look in org.fest.swing.core.Settings). After I decrease it (first 1000ms, next 100ms) I noticed that robot works faster.
robot().settings().idleTimeout(YOUR_TIMEOUT)
Here is my test setup and one test method. Hope is clear.
Here you have my before/after
private static int testMethodCounter = 0;
private static EmergencyAbortListener mEmergencyAbortListener;
private FrameFixture workbenchFrame;
private Robot robot2;
private static final int myIdleTimeout = 100;
#Before
public void setUp() throws Exception {
// my workaround to be able to start the app once and reuse for all tests
if (testMethodCounter == 0) {
robot2 = BasicRobot.robotWithNewAwtHierarchy();
GuiActionRunner.execute(new GuiTask() {
#Override
protected void executeInEDT() throws Throwable {
ApplicationLauncher.application(ProgramRun.class).start();
}
});
} else {
// the second test method see all before created gui components
robot2 = BasicRobot.robotWithCurrentAwtHierarchy();
}
testMethodCounter++;
robot2.settings().idleTimeout(myIdleTimeout);
workbenchFrame = WindowFinder.findFrame(FrameNames.WORKBENCH.getName()).withTimeout(10000)
.using(robot2);
}
#After
public void tearDown() {
// current window will not be closed
robot2.cleanUpWithoutDisposingWindows();
}
#Test
public void someSmokeTest() throws Exception {
Pause.pause(1000);
// perform some test specific gui actions
// here is very important moment, I need new robot because
// workbenchFrame.button(ButtonNames.SOME_BUTTON_NAME).click(); creates new dialog
// which will be avilable in AWT stack after creation
robot2.cleanUpWithoutDisposingWindows();
robot2 = BasicRobot.robotWithCurrentAwtHierarchy();
// the new Robot needs timeout setup
// without this I have long breaks between gui events
robot2.settings().idleTimeout(myIdleTimeout);
workbenchFrame.button(ButtonNames.SOME_BUTTON_NAME).click();
DialogFixture dialog = WindowFinder.findDialog("dialog2")
.withTimeout(5000).using(robot2);
// some actions on the dialog
// once again next new dialog
workbenchFrame.menuItem(MenuItemNames.NAME).click();
robot2.cleanUpWithoutDisposingWindows();
robot2 = BasicRobot.robotWithCurrentAwtHierarchy();
// and idleTimeout setup once again, new Robot needs new setup
robot2.settings().idleTimeout(myIdleTimeout);
// next actions + assertion
}
I have a set of images i want to add one after another and create a movie. I will be using Quicktime for java for this(I'm on a mac).
I searched the web i have found lots of examples that show how to play movies using qtj, but i can't find any code snippets or tutorials showing how i can create a movie frame by frame using qtj?
I've done this through QTJ with the MovieMaker class from processing libraries (GPL). Processing is pure java, though it can hide it for beginners.
Small tutorial:
Download Processing, open it, go to Sketch -> Show Sketch Folder, create a folder called "data", and put all your images inside that folder, named "filename01.gif" through "filename09.gif". Paste the following code into the editor, and hit play:
/**
* Makes a QuickTime movie out of an array of images.
*/
import processing.video.*;
MovieMaker mm;
PImage[] imageFrames;
int index;
void setup() {
size(320, 240);
int numFrames = 9;
imageFrames = new PImage[numFrames];
for( int i = 0; i < imageFrames.length; i++ )
{
imageFrames[i] = loadImage( "filename" + nf(i+1,2) + ".gif" );
}
// Save uncompressed, at 15 frames per second
mm = new MovieMaker(this, width, height, "drawing.mov");
// Or, set specific compression and frame rate options
//mm = new MovieMaker(this, width, height, "drawing.mov", 30,
// MovieMaker.ANIMATION, MovieMaker.HIGH);
}
void draw() {
if( index < imageFrames.length )
{
// show the image
image( imageFrames[index], 0, 0 );
// Add window's pixels to movie
mm.addFrame();
index++;
}
else
{
mm.finish();
// Quit running the sketch once the file is written
exit();
}
}
This will create a file "drawing.mov" from your images in the sketch folder. If you go to file --> export application, and then open the sketch folder and navigate to the folder application.macosx/source or application.windows/source, there should be a .java file that has the actual code, which should look like this:
import processing.core.*;
import processing.xml.*;
import processing.video.*;
import java.applet.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.text.*;
import java.util.*;
import java.util.zip.*;
import java.util.regex.*;
public class movie2 extends PApplet {
/**
* Makes a QuickTime movie out of an array of images.
*/
MovieMaker mm;
PImage[] imageFrames;
int index;
public void setup() {
size(320, 240);
int numFrames = 9;
imageFrames = new PImage[numFrames];
for( int i = 0; i < imageFrames.length; i++ )
{
imageFrames[i] = loadImage( "filename" + nf(i+1,2) + ".gif" );
}
// Save uncompressed, at 15 frames per second
mm = new MovieMaker(this, width, height, "drawing.mov");
// Or, set specific compression and frame rate options
//mm = new MovieMaker(this, width, height, "drawing.mov", 30,
// MovieMaker.ANIMATION, MovieMaker.HIGH);
}
public void draw() {
if( index < imageFrames.length )
{
// show the image
image( imageFrames[index], 0, 0 );
// Add window's pixels to movie
mm.addFrame();
index++;
}
else
{
mm.finish();
// Quit running the sketch once the file is written
//exit();
println( "done" );
}
}
static public void main(String args[]) {
PApplet.main(new String[] { "--bgcolor=#e0dfe3", "movie2" });
}
}
To use pure java, you'll need to use core.jar and video.jar from the processing application folder on your classpath, and then compile this java code. Here's a function reference and a javadoc for the processing library. Here are the javadocs for the MovieMaker class. If you want, you can see the source to the MovieMaker class.
HTH
There is an export related piece of sample code here:
http://developer.apple.com/samplecode/ImportExport/listing1.html
It shows how a single native QuickTime Movie can be opened for reading and then be passed on to a MovieExporter component to create a new QuickTime Movie from it.
For the code to import a file for as source for writing, see
void importMedia()
For the code to export the source to a QuickTime Movie, see
void run()
It should be possible to open an image file using the same approach, though, as long as the file format of the input file is supported by QuickTime (like f.e. BMP).
You should be able to write a sequence of image files using most of this code as well.
The only point which you will have to investigate is which method you'll have to call to append additional frames to an existing Movie. It might work using the same API, but most likely you'll need to use another call.
If you have to dig for another method you should be able to find it in the QT Java Reference Documentation located here:
http://developer.apple.com/Java/Reference/1.4/Java14API_QTJ/
It's a hack and most likely poor in performance, but it might actually work.
And... I never tried this (I am a QuickTime for Windows guy by trade) so: sorry, no warranty = ).
Edit: If you are looking for a way to write frames to a QT Movie using an existing input buffer instead of reading the data from file using the QT API, there should be APIs for
this as well. Just check out the reference documentation.
Edit 2: Actually it might be worthwhile to check out the C/C++ API Documentation here, as naming of components and calls seems to follow roughly the same naming conventions (i.e. this might help to dig for the calls of the Java API you need) and the C/C++ Docs seem to be more thorough in terms of providing Guides and How To's as a starting point. The C/C++ Docs can be found here:
http://developer.apple.com/referencelibrary/QuickTime/index.html
The most interesting sections should be
Import & Export
Compression & Decompression
Have Fun!