I have a uk.co.mmscomputing applet for scanning through web application. It works fine with Cannon DR-9080C scanner. Recently I purchased Kodak i2600 scanner and it is not working with my applet. The scanner scans all pages in the tray when i click Acquire for the first time but when I load more pages and click Acquire again, I get "Java Stopped Working" error.
I tried setting up uk.co.mmscomputing again but it was not helpful.
package uk.co.mmscomputing.application.imageviewer;
import java.io.*;
import java.awt.image.*;
import javax.swing.*;
import uk.co.mmscomputing.device.scanner.*;
import uk.co.mmscomputing.device.twain.*;
public class ScannerTab extends ImageTab implements ScannerListener{
static private int no=1;
public ScannerTab(java.util.Properties properties){
super(properties);
}
#Override
protected void setButtonPanel(JPanel gui){
super.setButtonPanel(gui);
try{
Scanner scanner=Scanner.getDevice(); // get a device and set GUI panel up
if(scanner!=null){
gui.add(scanner.getScanGUI());
scanner.addListener(this);
if(scanner instanceof TwainScanner){
TwainIdentity[] list=((TwainScanner)scanner).getIdentities();
for(int i=0;i<list.length;i++){
System.out.println(list[i].toString());
}
}
}
}catch(Exception e){
System.out.println("9\b"+getClass().getName()+".setButtonPanel:\n\t"+e);
}
}
public void update(ScannerIOMetadata.Type type, final ScannerIOMetadata metadata){
if(type.equals(ScannerIOMetadata.ACQUIRED)){ // acquired BufferedImage
final BufferedImage image=metadata.getImage();// make reference copy here to avoid race condition
new Thread(){
#Override
public void run(){
try{
addImage("scan_"+(no++),image);
}catch(Exception e){
System.out.println("9\b"+getClass().getName()+".update:\n\t"+e);
System.err.println(getClass().getName()+".update:\n\t"+e);
e.printStackTrace();
}
}
}.start();
}else if(type.equals(ScannerIOMetadata.FILE)){ // acquired image as file (twain only for the time being)
final File file=metadata.getFile(); // make reference copy here to avoid race condition
new Thread(){
#Override
public void run(){
try{
open(file.getPath());
}catch(Exception e){
System.out.println("9\b"+getClass().getName()+".update:\n\t"+e);
System.err.println(getClass().getName()+".update:\n\t"+e);
e.printStackTrace();
}finally{
if(!file.delete()){
System.out.println("9\b"+getClass().getName()+".update:\n\tCould not delete: "+file.getPath());
System.err.println(getClass().getName()+".update:\n\tCould not delete: "+file.getPath());
}
}
}
}.start();
}else if(type.equals(ScannerIOMetadata.NEGOTIATE)){
negotiate(metadata);
}else if(type.equals(ScannerIOMetadata.STATECHANGE)){
System.out.println("Scanner State "+metadata.getStateStr());
if(metadata instanceof TwainIOMetadata){ // TWAIN only !
if(metadata.isState(TwainConstants.STATE_TRANSFERREADY)){ // state = 6
TwainSource source = ((TwainIOMetadata)metadata).getSource();
try{
TwainImageInfo imageInfo=new TwainImageInfo(source);
imageInfo.get();
System.out.println(imageInfo.toString());
}catch(Exception e){
System.out.println("3\b"+getClass().getName()+".update:\n\tCannot retrieve image information.\n\t"+e);
}
try{
TwainImageLayout imageLayout=new TwainImageLayout(source);
imageLayout.get();
System.out.println(imageLayout.toString());
}catch(Exception e){
System.out.println("3\b"+getClass().getName()+".update:\n\tCannot retrieve image layout.\n\t"+e);
}
}else if(metadata.isState(TwainConstants.STATE_TRANSFERRING)){ // state = 7
TwainSource source = ((TwainIOMetadata)metadata).getSource();
try{
int[] tweis=new int[0x1240-0x1200];
for(int i=0;i<tweis.length;i++){tweis[i]=0x1200+i;}
TwainExtImageInfo imageInfo=new TwainExtImageInfo(source,tweis);
imageInfo.get();
System.out.println(imageInfo.toString());
}catch(Exception e){
System.out.println("3\b"+getClass().getName()+".update:\n\tCannot retrieve extra image information.\n\t"+e);
}
}
}
}else if(type.equals(ScannerIOMetadata.INFO)){
System.out.println(metadata.getInfo());
}else if(type.equals(ScannerIOMetadata.EXCEPTION)){
System.out.println("9\b"+metadata.getException().getMessage());
metadata.getException().printStackTrace();
}
}
private void negotiate(ScannerIOMetadata metadata){
ScannerDevice sd=metadata.getDevice(); // SANE & TWAIN
try{
sd.setShowUserInterface(false);
System.out.println("9\b"+e.getMessage());
}
if(metadata instanceof TwainIOMetadata){ // TWAIN only!
TwainSource source=((TwainIOMetadata)metadata).getSource();
try{
TwainCapability[] caps=source.getCapabilities(); // print out all the capabilities
for(int i=0;i<caps.length;i++){
System.out.println(caps[i].toString());
}
}catch(Exception e){
System.out.println("9\b"+e.getMessage());
}
}
}
}
Related
How to set the volume in this simple example?
I saw different approaches before but I don't know how to adapt them for my simple snippet.
Related Questions:
Changing Volume with JLayer
Changing volume in Java when using JLayer
Code listing:
package view.sound;
import java.io.FileInputStream;
import javazoom.jl.player.Player;
public class Audio extends Thread {
String fileLocation = "src/EgyptianTavernFullofGuitarists_1.mp3";
boolean loop = true;
Player player;
#Override
public void run() {
try {
do {
FileInputStream buff = new FileInputStream(fileLocation);
player = new Player(buff);
player.play();
} while (loop);
} catch (Exception ioe) {
}
}
public void close(){
loop = false;
player.close();
this.interrupt();
}
}
I've created a mini quiz game in java and wanted to convert it to an exe..It has photos and sounds attached to it but they are in their respective folders and with the correct paths. When i click on "Insert a new question" the exe works fine, the same thing happens for the "exit" option. But when i click "Play" no window pops up but i don't get an error either..
I tried placing the photos and sounds in the same folder as the class that uses them but it didn't fix the problem. I also tried inserting ".." at the beginning of the URL paths but it didn't fix it either. I've attached the code for the not showing frame.
ArrayList<Question> questions;
int selectedQuestion = 0;
int remainingLife = 3;
Random random = new Random();
int fillAnswer = 0;
String [] answerArray = new String[4];
Clip clipSuccess;
Clip clipFailure;
Clip clipGameOver;
public static Mixer mixer;
public static Clip clip;
javax.swing.Timer timer = new javax.swing.Timer(1000, new java.awt.event.ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
timer.stop();
jLabel5.setIcon(null);
playRound();
}
});
public PlayGame() {
initComponents();
questions = new ArrayList<Question>();
populateArrayList();
clipSuccess = setSound("../Sounds/success.wav");
clipFailure = setSound("../Sounds/failure.wav");
clipGameOver = setSound("../Sounds/gameOver.wav");
playRound();
}
public void populateArrayList(){
try{
FileInputStream file = new FileInputStream("Questions.dat");
ObjectInputStream inputFile = new ObjectInputStream(file);
boolean endOfFile = false;
while(!endOfFile){
try{
questions.add((Question) inputFile.readObject());
}
catch(EOFException e){
endOfFile = true;
}
catch(Exception f){
JOptionPane.showMessageDialog(null, f.getMessage());
}
}
inputFile.close();
}
catch(IOException e){
JOptionPane.showMessageDialog(null, e.getMessage());
}
}
public Clip setSound(String soundPath){
Mixer.Info[] mixInfos = AudioSystem.getMixerInfo();
/*for(Mixer.Info info: mixInfos){
System.out.println(info.getName() + "----" + info.getDescription());
}*/
mixer = AudioSystem.getMixer(mixInfos[3]);
DataLine.Info dataInfo = new DataLine.Info(Clip.class, null);
try {
clip = (Clip)mixer.getLine(dataInfo);
}
catch(LineUnavailableException lue){
lue.printStackTrace();
}
try{
URL soundURL = PlayGame.class.getResource(soundPath);
AudioInputStream audioStream = AudioSystem.getAudioInputStream(soundURL);
clip.open(audioStream);
}
catch(LineUnavailableException lue){
lue.printStackTrace();
}
catch(UnsupportedAudioFileException uofe){
uofe.printStackTrace();
}
catch(IOException ioe){
ioe.printStackTrace();
}
return clip;
}
public void successAnswer(){
JOptionPane.showMessageDialog(null, "Απάντησες σωστά!");
jLabel5.setText("");
jLabel5.setIcon(new ImageIcon(PlayGame.class.getResource("../Images/Fireworks-animated.gif")));
clipSuccess.setFramePosition(0);
clipSuccess.start();
timer.start();
}
public void wrongAnswer(){
remainingLife--;
JOptionPane.showMessageDialog(null, "Απάντησες λάθος..");
jLabel5.setText("");
jLabel5.setIcon(new ImageIcon (PlayGame.class.getResource("../Images/failure.gif")));
if (remainingLife == 0){
clipFailure.setFramePosition(0);
clipFailure.start();
timer.start();
JOptionPane.showMessageDialog(null, "Δυστυχώς έχασες..");
clipGameOver.setFramePosition(0);
clipGameOver.start();
do{
try{
Thread.sleep(50);
}
catch(InterruptedException ie){
ie.printStackTrace();
}
}while(clipGameOver.isActive());
System.exit(0);
}
clipFailure.setFramePosition(0);
clipFailure.start();
timer.start();
}
public void playRound(){
selectedQuestion = random.nextInt(questions.size());
jTextField3.setText(Integer.toString(remainingLife));
jTextArea2.setText(questions.get(selectedQuestion).getQuestionName());
for (int i=0; i<4; i++){
fillAnswer = random.nextInt(questions.size());
answerArray[i] = questions.get(fillAnswer).getQuestionAnswer();
if (i==2){
answerArray[i] = questions.get(selectedQuestion).getQuestionAnswer();
continue;
}
}
Collections.shuffle(Arrays.asList(answerArray));
jComboBox1.setModel(new javax.swing.DefaultComboBoxModel<>(answerArray));
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
int selectedAnswer = jComboBox1.getSelectedIndex();
jLabel5.setIcon(null);
if (questions.get(selectedQuestion).getQuestionAnswer().trim().equals(answerArray[selectedAnswer].trim())){
successAnswer();
}
else{
wrongAnswer();
}
timer.start();
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
System.exit(0);
In the IDE the output is a jframe with a question, a combo box of 4 answers, the player's life points and two buttons (one for locking the answer and one for exiting the program). But in the exe form it doesn't even pop up.
EDIT - This is the error the wrapper program shows:
Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: org/netbeans/lib/awtextra/AbsoluteLayout
at quiz.PlayGame.initComponents(PlayGame.java:277)
at quiz.PlayGame.(PlayGame.java:62)
I want to play music when my getoutput method is invoked and stop the music when the invoking is finished. I'm able to do the former but not the latter. How do I stop the music after I've finished invoking the getoutput method?
import java.io.InputStream;
import javax.sound.sampled.AudioSystem;
import sun.audio.AudioPlayer;
import sun.audio.AudioStream;
public class Student {
public void music() {
try {
// open the sound file as a Java input stream
String gongFile = "C:\\Users\\wei liang\\Documents\\Programming fundamentals\\T7-Arrays\\Assignment\\TT.wav";
InputStream in = new FileInputStream(gongFile);
// create an audiostream from the inputstream
AudioStream audioStream = new AudioStream(in);
// play the audio clip with the audioplayer class
AudioPlayer.player.start(audioStream);
} catch (Exception ex) {
System.out.println("Error! Can't find file.");
ex.printStackTrace();
}
}
}
This is my main method which calls the music method and another method not shown in the Student class.
public class StudentUser {
//Main method
public static void main(String args[]) {
//creating a new Student object
Student stud = new Student();
//Calling the music method
stud.music();
//Calling the getoutput method
stud.getoutput();
}
}
I would suggest using Thread, the Thread will be kept live until the music file is played and it will be ended automatically.
Since you did not provided getoutput method, you just call music method and it will play the music and ends.
Your Student class would be like:
import javax.sound.sampled.*;
import java.io.File;
class Student {
public synchronized void music(final String fileName, final SoundOptions mode) {
Thread music = new Thread(new Runnable() {
#Override
public void run() {
try {
AudioInputStream inputStream = AudioSystem.getAudioInputStream(
new File(fileName));
final Clip audioLineClip = (Clip) AudioSystem.getLine(
new Line.Info(Clip.class));
audioLineClip.open(inputStream);
audioLineClip.setFramePosition(0);
audioLineClip.addLineListener(new LineListener() {
#Override
public void update(LineEvent event) {
LineEvent.Type type = event.getType();
if (type == LineEvent.Type.OPEN) {
} else if (type == LineEvent.Type.CLOSE) {
System.exit(0);
} else if (type == LineEvent.Type.START) {
} else if (type == LineEvent.Type.STOP) {
audioLineClip.close();
}
}
});
switch (mode) {
case Stop:
audioLineClip.stop();
break;
case Play:
audioLineClip.start();
break;
case Loop:
audioLineClip.loop(Clip.LOOP_CONTINUOUSLY);
break;
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
});
if (mode != SoundOptions.Stop) {
music.start();
synchronized (music) {
while (true) {
try {
music.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} else {
music.interrupt();
}
}
}
enum SoundOptions {
Play, Loop, Stop
}
and StudentUser class:
public class StudentUser {
private static String gongFile = "C:\\Users\\wei liang\\Documents\\Programming fundamentals\\T7-Arrays\\Assignment\\TT.wav";
//Main method
public static void main(String args[]) {
//Creating a new Student object
Student stud = new Student();
//Calling the music method and it is stops when music ends
stud.music(gongFile, SoundOptions.Play);
}
}
So my code works just the way I want it the only issue I'm having is this.. Basically I am having a main class which controls gates on a railroad track, when a train is approaching or crossing the track from either 1 of two tracks the gates should close. The only issue I'm having is the statements for when a gate opens or closes spam like 3-5 times everytime it does something so if the gate is closing it will go..
GATE: Closing
GATE: Closing
GATE: Closing
GATE: Closing
GATE: Closing
GATE: Closed
I'm wondering why this is occuring, here is my code for the Gate class and Main class
public class Gate {
private boolean isClosed = false;
private boolean closing = false;
private boolean opening = false;
public Gate(){
}
public void close(){
if(!(isClosing() == true)){
Runnable task = new Runnable() {
public void run() {
try {
setClosing(true);
setOpening(false);
System.out.println("GATE: Closing");
Thread.sleep(400);
System.out.println("GATE: Closed");
setClosed(true);
setClosing(false);
}catch(Exception ex){
}
}
};
new Thread(task, "closeThread").start();
}
}
public void open(){
if(!(isOpening() == true)){
Runnable task = new Runnable() {
public void run() {
try {
setOpening(true);
System.out.println("GATE: Opening");
Thread.sleep(400);
setOpening(false);
if(closing == false){
setClosed(false);
System.out.println("GATE: Opened");
}
}catch(Exception ex){
}
}
};
new Thread(task, "openThread").start();
}
}
public boolean isClosed(){
return isClosed;
}
public boolean isClosing(){
return closing;
}
public boolean isOpening(){
return opening;
}
public synchronized void setClosing(boolean t){
closing = t;
}
public synchronized void setOpening(boolean t){
opening = t;
}
public synchronized void setClosed(boolean t){
isClosed = t;
}
}
public class Controller {
public static void main(String[] args){
Track t1 = new Track("Track 1");
Track t2 = new Track("Track 2");
Gate g = new Gate();
t1.simulateTrack();
t2.simulateTrack();
do{
System.out.print("");
if((t1.isApproaching() || t1.isCrossing()) || (t2.isApproaching() || t2.isCrossing())){
if(!g.isClosed() && !g.isClosing()){
g.close();
}
}else if(g.isClosed() && !g.isOpening()){
g.open();
}
}while((t1.isSimulating() || t2.isSimulating()));
}
}
Also the code for Track
import java.security.SecureRandom;
public class Track {
private static final SecureRandom gen = new SecureRandom() ;
private boolean approaching = false;
private boolean atCrossing = false;
private boolean simulating = false;
private String trackName = "";
public Track(String n){
trackName = n;
}
public void simulateTrack(){
Runnable task = new Runnable() {
public void run() {
try {
setSimulating(true);
for(int i = 0; i < 10; i++){
Thread.sleep((gen.nextInt(5000) + 2500));
setApproaching(true);
System.out.println(trackName + ": Train is now approaching.");
Thread.sleep((gen.nextInt(5000) + 3500));
setCrossing(true);
setApproaching(false);
System.out.println(trackName + ": Train is now crossing.");
Thread.sleep((gen.nextInt(1000) + 1000));
setCrossing(false);
System.out.println(trackName + ": Train has left.");
}
setSimulating(false);
} catch (Exception ex) {
}
}
};
new Thread(task, "simulationThread").start();
}
public boolean isApproaching(){
return approaching;
}
public boolean isCrossing(){
return atCrossing;
}
public boolean isSimulating(){
return simulating;
}
public synchronized void setSimulating(boolean t){
simulating = t;
}
public synchronized void setApproaching(boolean t){
approaching = t;
}
public synchronized void setCrossing(boolean t){
atCrossing = t;
}
}
This is just an idea:
By shooting the close() logic on a background thread you lose the atomicity. The main's do loop can go around 5 times before it gives up the control of the main thread and one of the "closeThread"s start executing. Don't you see multiple "GATE: Closed"s as well?
Try this (not tested, sorry):
public synchronized void close() { // added synchornized
if (!isClosing()) { // read: "if not closing"
setClosing(true); // set closing so next time close() is called it is a no op
setOpening(false); // close other loopholes so the state is correct
System.out.println("GATE: Closing");
// we're in closing state now, because the close method is almost finished
// start the actual closing sequence
Runnable task = new Runnable() {
public void run() {
try {
Thread.sleep(400);
System.out.println("GATE: Closed");
setClosed(true);
setClosing(false);
}catch(Exception ex){
}
}
};
new Thread(task, "closeThread").start();
}
}
You'll need to modify open() the same way, so that the invariants are always kept. Checking and setting the closing and opening flags are mutually exclusive, that's what you get by placing synchronized on both of them.
I have a class Automator that can automate a user. I am specifically having problems setting the system clipboard in windows. The Automator class makes use of the ClipSetThread class, which is a thread that sets the system clipboard. A instance of ClipSetThread takes as input a thread, that if null, it joins with (waits for it to complete).
I feel that I am not calling ClipSetThread right because I still have the errors I have had before in its reliability; prior to the ClipSetThread. This code does not throw any errors when it runs, it works about 2/3 of the time though. Other times it will print 1134, _234, or etc. It seems that the threads are not joining (waiting for) each other, or get skipped.
Code:
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.mouse.NativeMouseEvent;
import org.jnativehook.mouse.NativeMouseInputListener;
public class Automator extends Thread implements NativeMouseInputListener
{
Robot rob = null;
TheAppClass theApp = null;
ClipSetThread lastClipSet = null;
boolean doit = false;
boolean settingClip = false;
public void run()
{
try // to make the Global hook
{
GlobalScreen.registerNativeHook();
}
catch (NativeHookException ex){theApp.updateOutput("No Global Keyboard or Mouse Hook");return;}
try // to create a robot (can simulate user input such as mouse and keyboard input)
{
rob = new Robot();
}
catch (AWTException e1) {theApp.updateOutput("The Robot could not be created");return;}
while(true) {}
}
public void setApp(TheAppClass app)
{
theApp = app;
theApp.updateOutput("Succesfully started automator");
}
public void setClip(String arg)
{
ClipSetThread set = new ClipSetThread(theApp, lastClipSet);
lastClipSet = set;
set.setClip(arg);
}
public void DOit()
{
theApp.updateOutput("Starting");
pasteAtCursorLocation("1");
tab(1);
pasteAtCursorLocation("2");
tab(1);
pasteAtCursorLocation("3");
tab(1);
pasteAtCursorLocation("4");
tab(1);
theApp.updateOutput("Complete");
}
public void nativeMouseReleased(NativeMouseEvent e)
{
//System.out.println("Mouse Released: " + e.getButton());
if(doit)
{
DOit();
doit = false;
}
}
public void pasteAtCursorLocation(String text)
{
setClip(text);
rob.keyPress(KeyEvent.VK_CONTROL);
rob.keyPress(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_CONTROL);
theApp.updateOutput("Simulated Paste");
}
public void tab(int numTimes)
{
while(numTimes > 0)
{
rob.keyPress(KeyEvent.VK_TAB);
rob.keyRelease(KeyEvent.VK_TAB);
numTimes--;
theApp.updateOutput("Simulated Tab");
}
}
// Unimplemented
public void nativeMouseClicked(NativeMouseEvent arg0) {}
public void nativeMousePressed(NativeMouseEvent arg0) {}
public void nativeMouseDragged(NativeMouseEvent arg0) {}
public void nativeMouseMoved(NativeMouseEvent arg0) {}
}
ClipSetThread:
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
public class ClipSetThread extends Thread
{
Clipboard sysClip = null;
TheAppClass theApp = null;
public ClipSetThread(TheAppClass app, Thread waitFor)
{
theApp = app;
sysClip = Toolkit.getDefaultToolkit().getSystemClipboard();
if(waitFor != null)
{try {waitFor.join();}catch (InterruptedException e) {}}
}
public void setClip(String arg)
{
// Two strings that will hopefully never be on the clipboard
String checkStr1 = "9999999999999";
String checkStr2 = "99999999999999";
// When we read in the clipboard we want to see if we change these strings from the ones they
// will never be, if they do change we read the clipboard successfully
String clipBoardTextBefore = checkStr1;
String clipBoardTextAfter = checkStr2;
// First get a copy of the current system clipboard text
while(true)
{
try
{
Transferable contents = sysClip.getContents(null);
clipBoardTextBefore = (String)contents.getTransferData(DataFlavor.stringFlavor);
}
catch(Exception e)
{
try {Thread.sleep(20);} catch (InterruptedException e1) {}
continue;
}
break;
}
// If we failed to change the string it means we failed to read the text
if(clipBoardTextBefore.equals(checkStr1))
theApp.updateOutput("Could NOT get sysClip text");
else
{
// If we didn't failed to get the current text try to change it
while(true)
{
try{sysClip.setContents(new StringSelection(arg), null);}
catch(Exception e)
{
try {Thread.sleep(20);} catch (InterruptedException e1) {}
continue;
}
break;
}
// Now again check to see the clipboard text
while(true)
{
try
{
Transferable contents = sysClip.getContents(null);
clipBoardTextAfter = (String)contents.getTransferData(DataFlavor.stringFlavor);
}
catch(Exception e)
{
try {Thread.sleep(20);} catch (InterruptedException e1) {}
continue;
}
break;
}
// If we failed to read the clipboard text
if(clipBoardTextAfter.equals(checkStr2))
theApp.updateOutput("Could NOT check if sysClip update was successful");
else
{ // We re-read the clipboard text, see if it changed from the original clipboard text
if(clipBoardTextAfter.equals(checkStr1))
theApp.updateOutput("Could NOT successfully set clipboard text");
else
theApp.updateOutput("Set Clipboard Text:" + arg + "\n");
}
}
}
}
So, firstly, you never call start on the ClipSetThread. You should also check to see if the thread is still alive before joining it.
public class ClipSetThread extends Thread {
Clipboard sysClip = null;
TheAppClass theApp = null;
private String toClipboard;
public ClipSetThread(TheAppClass app, Thread waitFor, String toClipBoard) {
theApp = app;
sysClip = Toolkit.getDefaultToolkit().getSystemClipboard();
this.toClipboard = toClipBoard;
// !! Check to see if the thread is also alive before trying to join with it...
if (waitFor != null && waitFor.isAlive()) {
try {
waitFor.join();
} catch (InterruptedException e) {
}
}
}
// You should really put your logic into the `run` method in order to allow
// the code to actually run in a separate thread...otherwise there is no
// point in using a thread....
#Override
public void run() {
// Two strings that will hopefully never be on the clipboard
String checkStr1 = "9999999999999";
String checkStr2 = "99999999999999";
// When we read in the clipboard we want to see if we change these strings from the ones they
// will never be, if they do change we read the clipboard successfully
String clipBoardTextBefore = checkStr1;
String clipBoardTextAfter = checkStr2;
// First get a copy of the current system clipboard text
while (true) {
try {
Transferable contents = sysClip.getContents(null);
clipBoardTextBefore = (String) contents.getTransferData(DataFlavor.stringFlavor);
} catch (Exception e) {
try {
Thread.sleep(20);
} catch (InterruptedException e1) {
}
continue;
}
break;
}
// If we failed to change the string it means we failed to read the text
if (clipBoardTextBefore.equals(checkStr1)) {
theApp.updateOutput("Could NOT get sysClip text");
} else {
// If we didn't failed to get the current text try to change it
while (true) {
try {
sysClip.setContents(new StringSelection(toClipboard), null);
} catch (Exception e) {
try {
Thread.sleep(20);
} catch (InterruptedException e1) {
}
continue;
}
break;
}
// Now again check to see the clipboard text
while (true) {
try {
Transferable contents = sysClip.getContents(null);
clipBoardTextAfter = (String) contents.getTransferData(DataFlavor.stringFlavor);
} catch (Exception e) {
try {
Thread.sleep(20);
} catch (InterruptedException e1) {
}
continue;
}
break;
}
// If we failed to read the clipboard text
if (clipBoardTextAfter.equals(checkStr2)) {
theApp.updateOutput("Could NOT check if sysClip update was successful");
} else { // We re-read the clipboard text, see if it changed from the original clipboard text
if (clipBoardTextAfter.equals(checkStr1)) {
theApp.updateOutput("Could NOT successfully set clipboard text");
} else {
theApp.updateOutput("Set Clipboard Text:" + toClipboard + "\n");
}
}
}
}
}
As per our previous converstaion, it's dangerous to use while (true) {}, it's also wasteful, as it will consume CPU cycles unnecessarily...
public class Automator extends Thread implements NativeMouseInputListener {
// A "locking" object...
private static final Object WAIT_LOCK = new Object();
Robot rob = null;
TheAppClass theApp = null;
ClipSetThread lastClipSet = null;
boolean doit = false;
boolean settingClip = false;
public void run() {
try // to make the Global hook
{
GlobalScreen.registerNativeHook();
} catch (NativeHookException ex) {
theApp.updateOutput("No Global Keyboard or Mouse Hook");
return;
}
try // to create a robot (can simulate user input such as mouse and keyboard input)
{
rob = new Robot();
} catch (AWTException e1) {
theApp.updateOutput("The Robot could not be created");
return;
}
// This is wasteful...
// while (true) {
// }
// Locks do not consume CPU cycles while in the wait state...
synchronized (WAIT_LOCK) {
try {
WAIT_LOCK.wait();
} catch (Exception exp) {
}
}
}
public void dispose() {
// Tell the thread it can terminate...
synchronized (WAIT_LOCK) {
WAIT_LOCK.notify();
}
// This will STOP the current thread (which called this method)
// while the lastClipSet finishes...
if (lastClipSet != null && lastClipSet.isAlive()) {
lastClipSet.join();
}
}
public void setClip(String arg) {
ClipSetThread set = new ClipSetThread(theApp, lastClipSet, arg);
lastClipSet = set;
// You MUST START the thread...
set.start();
}
/*...*/
}
Updated
This code could produce a infinite loop. What happens if the clipboard does not contain a String value??
while(true)
{
try
{
Transferable contents = sysClip.getContents(null);
clipBoardTextBefore = (String)contents.getTransferData(DataFlavor.stringFlavor);
}
catch(Exception e)
{
try {Thread.sleep(20);} catch (InterruptedException e1) {}
continue;
}
break;
}
You tend to do this a lot. I might suggest that you provide some kind of "escape" mechanism to allow it to fail after a number of retries...
boolean successful = false;
int retries = 0;
while (!successful && retries < 20) {
{
try
{
Transferable contents = sysClip.getContents(null);
clipBoardTextBefore = (String)contents.getTransferData(DataFlavor.stringFlavor);
successful = true;
}
catch(Exception e)
{
retries++;
try {Thread.sleep(20);} catch (InterruptedException e1) {}
}
}
Updated with working example
Okay, that was fun. I've put together a (simple) working example. You will want to open a text editor of some kind. When you run the program, you have 5 seconds to make it active ;)
The only basic change I've made is I set added a auto delay between events of 250 milliseconds (see rob.setAutoDelay(250).
Now, you could also place a delay between each key event as well, using Robot#delay, but that's up to you
public class Engine extends Thread {
private Robot rob = null;
private PasteThread lastClipSet = null;
public void setClip(String arg) {
if (lastClipSet != null && lastClipSet.isAlive()) {
try {
lastClipSet.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
PasteThread set = new PasteThread(arg);
lastClipSet = set;
lastClipSet.start();
}
public void pasteAtCursorLocation(String text) {
System.out.println("Paste " + text);
setClip(text);
rob.keyPress(KeyEvent.VK_CONTROL);
rob.keyPress(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_CONTROL);
}
public Engine() throws AWTException {
rob = new Robot();
rob.setAutoDelay(250);
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
}
pasteAtCursorLocation("This is a simple test, thanks for watching!");
}
public static void main(String[] args) {
try {
new Engine();
} catch (AWTException ex) {
Logger.getLogger(Engine.class.getName()).log(Level.SEVERE, null, ex);
}
}
public class PasteThread extends Thread {
private String toPaste;
public PasteThread(String value) {
toPaste = value;
}
#Override
public void run() {
Clipboard sysClip = Toolkit.getDefaultToolkit().getSystemClipboard();
System.out.println("Current clipboard contents = " + getClipboardContents(sysClip));
sysClip.setContents(new StringSelection(toPaste), null);
System.out.println("New clipboard contents = " + getClipboardContents(sysClip));
}
public String getClipboardContents(Clipboard clipboard) {
String value = null;
boolean successful = false;
int retries = 0;
while (!successful && retries < 20) {
Transferable contents = clipboard.getContents(null);
if (contents.isDataFlavorSupported(DataFlavor.stringFlavor)) {
try {
value = (String) contents.getTransferData(DataFlavor.stringFlavor);
successful = true;
} catch (Exception exp) {
retries++;
exp.printStackTrace();
}
} else {
retries++;
}
}
System.out.println(successful + "/" + retries);
return value;
}
}
}
Could you please try to repeat the Paste action with a sleep 1 second in between
public void pasteAtCursorLocation(String text)
{
setClip(text);
rob.keyPress(KeyEvent.VK_CONTROL);
rob.keyPress(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_CONTROL);
theApp.updateOutput("Simulated Paste");
// put in a sleep 1 second here
rob.keyPress(KeyEvent.VK_CONTROL);
rob.keyPress(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_CONTROL);
theApp.updateOutput("Simulated Paste");
}
It could be that pasting 2x is giving different results. The reason for this strange behavior could the way Windows manages the clipboard. If pasting 2x the clipboard is giving different result then you know that the root cause for this strange behavior is not to find in your code but how Java and Windows work together.