i have a thread running which keeps repainting the maze recursively until the exit is reached. The method below is responsible for repainting the maze.
private void moveFromStep(int x, int y) {
if(step){
if(isWall(x,y))
return ;
if(isVisited(x,y))
return ;
if(isGoal(x,y)){
free = true;
JOptionPane.showMessageDialog(this, "Solution Complete: finish reachable");
}
if(!free){
step = false;
setVisited(x,y);
repaint();
//try {Thread.sleep(3000);} catch (Exception e) { }
//try {wait();} catch (Exception e) { }
moveFromStep(x-1,y);
moveFromStep(x+1,y);
moveFromStep(x,y-1);
moveFromStep(x,y+1);
}
}
}
now i have a JPanel running separately and i want to repaint it step by step.
i want to do this by using a "Step" button. So like the maze is printed step by step when "Step" button is pressed. The code below is the action listener for the buttons
public void actionPerformed(ActionEvent event) {
String action = event.getActionCommand();
MazeStep mazeStep = new MazeStep();
Thread mazeThreadStep = null;
if (action.equals("Load Maze")) {
mazeAnim.readFile(getName());
//mazeStep = new MazeStep();
mazeStep.readFile(getName());
}
else if(action.equals("Start")){
JFrame world = new JFrame();
mazeStep = new MazeStep();
mazeStep.readFile(getName());
world.setSize(300, 300);
world.setTitle("Maze solver");
world.setContentPane(mazeStep);
world.setVisible(true);
mazeThreadStep = new Thread(mazeStep);
mazeThreadStep.start();
}
if(action.equals("Step")){
mazeStep.step = true;
synchronized (mazeThreadStep) {
mazeThreadStep.notify();
}
}
}
So can anyone help me what could be done in order to achieve this plz.
Related
i have a problem trying to stop my Timer. I have two different classes, the first contains the button that starts and stop the button and the second is the chrono class. Here is the button:
btnStopstart = new JButton("START");
btnStopstart.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
Chrono1 cn = new Chrono1(chrono);
String texte = btnStopstart.getText();
if(texte.equals("START")){
btnStopstart.setText("STOP");
try {
cn.Editchrono(texte);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}else if(texte.equals("STOP")){
btnStopstart.setText("START");
cn.Editchrono(texte);
}
}
});
And here is the chrono class:
public class Chrono1 {
private static int sec;
private JTextField chrono;
public Chrono1(JTextField chrono){
this.chrono = chrono;
}
public void Editchrono(String txt){
/* Le timer */
int delais=1000;
ActionListener tache_timer;
tache_timer = new ActionListener(){
public void actionPerformed(ActionEvent e){
sec++;
if(sec == 15 ){
//Conditions
}
if(sec == 16){
/*On realise une pause de 1 sec */
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
//mettre les conditions ici
sec = 0;
}
//System.out.println(sec);
chrono.setText("" + sec);
}
};
final Timer timer1= new Timer(delais,tache_timer);
if(txt.equals("START")){
timer1.start();
}else if(txt.equals("STOP")){
timer1.stop();
//sec = 0;
}
}
}
Thank you for the help.
You're calling stop() on a Swing Timer all right, but not on the Timer instance that's running. Rather you're calling stop() on a completely new Timer instance, one that's not even running, and one that is completely unrelated to the Timer that is in fact running. You need to give the Chrono1 class a Timer field, say called timer, set this field to reference the running Timer when it starts, and call stop on this field (if not null) when stop is called. You also need to create one and only one Chrono1 object.
e.g.,
public class Chrono1 {
private static int sec;
private JTextField chrono;
private Timer timer1; // ***** added ***
public Chrono1(JTextField chrono){
this.chrono = chrono;
}
public void Editchrono(String txt){
int delais=1000;
ActionListener tache_timer;
tache_timer = new ActionListener(){
public void actionPerformed(ActionEvent e){
// .... etc.....
}
};
if(txt.equals("START")) {
// **** note changes? ****
// final Timer timer1= new Timer(delais,tache_timer); // ** no **
timer1= new Timer(delais,tache_timer); // ** yes! **
timer1.start();
}else if(txt.equals("STOP")){
if (timer1 != null && timer1.isRunning()) {
timer1.stop();
}
//sec = 0;
}
}
}
Also this guy shouldn't be re-created:
Chrono1 cn = new Chrono1(chrono);
And so this should be a private instance field of either the whole class or of the inner ActionListener class and not re-created with each button push.
e.g., make the changes below:
btnStopstart.addActionListener(new ActionListener(){
private Chrono1 cn = new Chrono1(chrono); // **** add this
public void actionPerformed(ActionEvent e) {
// Chrono1 cn = new Chrono1(chrono); // **** remove this
String texte = btnStopstart.getText();
if(texte.equals("START")){
btnStopstart.setText("STOP");
try {
cn.Editchrono(texte);
} catch (Exception e1) {
e1.printStackTrace();
}
} else if(texte.equals("STOP")) {
btnStopstart.setText("START");
cn.Editchrono(texte);
}
}
});
I have a constructor of a JFrame where I have a Thread(t1) which is running thanks to a
while(true)
I would like to know how to implement my JFrame so it can kill the thread when I close it, because t1 need to be running when the JFrame is active
EDIT:
Here is the code:
public class Vue_Session extends JFrame {
private JPanel contentPane;
private int idsess;
private User u;
public Vue_Session(User us, int id) {
this.u = us;
this.idsess = id;
toServ t=new toServ(idsess);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setBounds((int) screenSize.getWidth() / 2 - 800 + (800 / 2), 90, 800,
600);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new BorderLayout());
Vue_Idee vueIdee = new Vue_Idee(this.idsess, this.u);
contentPane.add(vueIdee, BorderLayout.SOUTH);
Vue_IdeeSession vueSess = new Vue_IdeeSession(this.idsess);
contentPane.add(vueSess, BorderLayout.CENTER);
Thread t1 = new Thread( new Runnable(){
public void run(){
while(true){
try{
Thread.sleep(500);
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t.getIdee();
vueSess.act();
revalidate();
}
}
});
t1.start();
}
You can handle it with a boolean variable like
boolean end = false;
while (!end){...}
Also I suggest you use ExecutorService or ForkJoinPool so you can simply control your tasks, threads, etc
EDIT:
boolean end = false;
new Thread(() -> {
while (!end) {
//...
}
}).start();
and this is where you should end your tasks:
addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosed(java.awt.event.WindowEvent evt) {
end = true;
System.exit(0);
// or this.dispose();
}
});
good luck :)
It's a controversial topic but in general I would replace the while (true) construct with
while(!Thread.currentThread().isInterrupted()){
try{
Thread.sleep(500);
}catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
t.getIdee();
vueSess.act();
revalidate();
}
More information on this topic can be found here:
http://www.javaspecialists.eu/archive/Issue056.html
Okay, here was the answer:
I needed to add en WindowListenne:
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent b) {
t1.stop();
dispose();
}
});
And also:
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
First, you need to make the thread kill-able. To do this, instead of looping forever, loop as long as certain looping flag is true.
After that, you need to create a listener that gets called whenever the user closes the frame. You can use WindowAdapter to do this. When the listener is called, set the looping flag to false. Once the thread dies, you can safely terminate the program.
For example:
public class Vue_Session extends JFrame {
Thread thread = null;
boolean threadAlvie = true;
boolean threadDie = false;
public Vue_Session(User us, int id) {
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowEvent) {
threadAlive = false;
// Wait until the thread dies
while (!threadDie) {
// Sleep for 100 milliseconds.
Thread.sleep(100);
}
System.exit(0);
}
});
thread = new Thread(new Runnable() {
public void run(){
while (threadAlive){
// do something
}
threadDie = true;
}
});
thread.start();
}
}
I am attempting to load a saved file from JFileChooser using an actionListener. Here is a snippet of code.
class chooserListener implements ActionListener{
public void actionPerformed (ActionEvent e)
{
if (e.getSource() instanceof JFileChooser){
JFileChooser openFile = (JFileChooser)e.getSource();
String command = e.getActionCommand();
if (command.equals(JFileChooser.APPROVE_SELECTION)){
File selectedFile = openFile.getSelectedFile();
loadSavedGame(selectedFile);
System.out.print("clicked open file");
tp.setSelectedIndex(0);
}
else if (command.equals(JFileChooser.CANCEL_SELECTION)) {
System.out.print("tester");
tp.setSelectedIndex(0);
}
}
}
}
chooser.addActionListener(new chooserListener());
public void loadSavedGame(File loadfile) {
int allCells = countCells(loadfile);
setMineGame(allCells);
try {
Scanner loadFile = new Scanner(loadfile);
while (loadFile.hasNextInt()){
for (int i = 0; i < allCells; i++){
mineGame.setCell(i, loadFile.nextInt());
//System.out.print("loading saved game");
}
loadFile.close();
mineGame.repaint();
tp.setSelectedIndex(0);
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private int countCells(File countCell) {
int cellCount = 0;
try {
Scanner getCells = new Scanner(countCell);
while (getCells.hasNextInt()){
cellCount++;
}
getCells.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print(cellCount);
return cellCount;
}
public void setMineGame(int cells) {
game.removeAll();
mineGame.setDifficulty(cells);
mineGame = new Board(statusbar, difficulty);
game.add(mineGame, BorderLayout.CENTER);
game.add(statusbar, BorderLayout.SOUTH);
frame.validate();
frame.repaint();
}
public void setDifficulty(int cells){
if(cells == 256){
difficulty = 0;
}
if (cells == 676){
difficulty = 1;
}
else difficulty = 2;
}
I feel like I have too many methods for the action listener to do. It is hanging when I click 'open', and the test print line 'System.out.print("clicked open file");' does not print. the rest of my code is really large and I'm not sure how to to an SSCE(?). I'm wondering if anyone can see why my actionListener is hanging? thanks IA
It seems like loadSavedGame(File file) takes a lot of time to execute. As this method is running in the Event Dispatch Thread you feel like your program is hanging and never reaches System.out.print("clicked open file"); line. I'd start testing the time of response for this method in a separate test case
Anyway I'd suggest you a few tips:
1) Note there's no need to implement an ActionListener to do your code. You can simple make this:
JFileChooser chooser = new JFileChooser();
int returnValue = chooser.showOpenDialog(null);
if(returnValue == JFileChooser.APPROVE_OPTION){
//make stuff if approved
} else if(returnValue == JFileChooser.CANCEL_OPTION){
//make stuff if canceled
}
I think it makes people life easier.
2) On the other hand note you have two I/O operations: getting the cells count through countCells(File countCell) method and getting the cells themselves inside loadSavedGame(File loadfile) method. You can do it better reading the file just once:
public List<Integer> getCells(File file){
List<Integer> list = new ArrayList<>();
try {
Scanner getCells = new Scanner(file);
while (getCells.hasNextInt()){
list.add(Integer.valueOf(getCells.nextInt()));
}
getCells.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
return list;
}
}
And make this change in loadSavedGame method:
public void loadSavedGame(File loadfile) {
List<Integer> allCells = getCells(loadfile);
setMineGame(allCells.size());
int index = 0;
for(Integer value : allCells){
mineGame.setCell(index, value);
index++;
}
mineGame.repaint();
tp.setSelectedIndex(0);
}
I have a JTable in which I want to call a function when a cell is double-clicked and call another function when the cell is triple-clicked.
When the cell is triple-clicked I do not want to call the double-click-function.
What I have right now is (mgrdAlarm is the JTable) :
mgrdAlarm.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
System.out.println("getClickCount() = " + e.getClickCount());
if (e.getClickCount()==2)
{
doubleClick();
System.out.println("Completed : doubleClick()");
}
if (e.getClickCount()==3)
{
tripleClick();
System.out.println("Completed : tripleClick()");
}
}
});
When double-clicked the console shows :
getClickCount() = 1
getClickCount() = 2
Completed : doubleClick()
When triple-clicked the console shows :
getClickCount() = 1
getClickCount() = 2
Completed : doubleClick()
getClickCount() = 3
Completed : tripleClick()
When triple-clicked I want the console to show :
getClickCount() = 1
getClickCount() = 2
getClickCount() = 3
Completed : tripleClick()
So I do not want to call the function doubleClick() when the cell is triple-clicked, but I do want to call the function doubleClick() when the cell is double-clicked.
[EDIT]
As all replies suggest the solution seems to be to delay the double-click-action and wait a certain time for the triple-click.
But as discussed here that might lead to a different type of problem :
The user might have set his double-click-time quite long, which might overlap with the timeout of my triple-click.
It is no real disaster if my double-click-action is executed before my triple-click-action, but it does generate some extra overhead, and especially some extra data traffic which I would like to prevent.
As the only solution so far might lead to other problems, which might actually be worse than the original problem, I will leave it as it is right now.
public class TestMouseListener implements MouseListener {
private boolean leftClick;
private int clickCount;
private boolean doubleClick;
private boolean tripleClick;
public void mouseClicked(MouseEvent evt) {
if (evt.getButton()==MouseEvent.BUTTON1){
leftClick = true; clickCount = 0;
if(evt.getClickCount() == 2) doubleClick=true;
if(evt.getClickCount() == 3){
doubleClick = false;
tripleClick = true;
}
Integer timerinterval = (Integer)Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval");
Timer timer = new Timer(timerinterval, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if(doubleClick){
System.out.println("double click.");
clickCount++;
if(clickCount == 2){
doubleClick(); //your doubleClick method
clickCount=0;
doubleClick = false;
leftClick = false;
}
}else if (tripleClick) {
System.out.println("Triple Click.");
clickCount++;
if(clickCount == 3) {
tripleClick(); //your tripleClick method
clickCount=0;
tripleClick = false;
leftClick = false;
}
} else if(leftClick) {
System.out.println("single click.");
leftClick = false;
}
}
});
timer.setRepeats(false);
timer.start();
if(evt.getID()==MouseEvent.MOUSE_RELEASED) timer.stop();
}
}
public static void main(String[] argv) throws Exception {
JTextField component = new JTextField();
component.addMouseListener(new TestMouseListener());
JFrame f = new JFrame();
f.add(component);
f.setSize(300, 300);
f.setVisible(true);
component.addMouseListener(new TestMouseListener());
}
}
The previous answers are correct: you have to account for the timing and delay recognizing it as a double click until a certain amount of time has passed. The challenge is that, as you have noticed, the user could have a very long or very short double click threshold. So you need to know what the user's setting is. This other Stack Overflow thread ( Distinguish between a single click and a double click in Java ) mentions the awt.multiClickInterval desktop property. Try using that for your threshold.
You can do something like that, varying delay time:
public class ClickForm extends JFrame {
final static long CLICK_FREQUENTY = 300;
static class ClickProcessor implements Runnable {
Callable<Void> eventProcessor;
ClickProcessor(Callable<Void> eventProcessor) {
this.eventProcessor = eventProcessor;
}
#Override
public void run() {
try {
Thread.sleep(CLICK_FREQUENTY);
eventProcessor.call();
} catch (InterruptedException e) {
// do nothing
} catch (Exception e) {
// do logging
}
}
}
public static void main(String[] args) {
ClickForm f = new ClickForm();
f.setSize(400, 300);
f.addMouseListener(new MouseAdapter() {
Thread cp = null;
public void mouseClicked(MouseEvent e) {
System.out.println("getClickCount() = " + e.getClickCount() + ", e: " + e.toString());
if (cp != null && cp.isAlive()) cp.interrupt();
if (e.getClickCount() == 2) {
cp = new Thread(new ClickProcessor(new Callable<Void>() {
#Override
public Void call() throws Exception {
System.out.println("Double click processed");
return null;
}
}));
cp.start();
}
if (e.getClickCount() == 3) {
cp = new Thread(new ClickProcessor(new Callable<Void>() {
#Override
public Void call() throws Exception {
System.out.println("Triple click processed");
return null;
}
}));
cp.start();
}
}
});
f.setVisible(true);
}
}
You need to delay the execution of double click to check if its a tripple click.
Hint.
if getClickCount()==2 then put it to wait.. for say like 200ms?
It's exactly the same problem as detecting double-click without firing single click. You have to delay firing an event until you're sure there isn't a following click.
There's a tutorial for this
here
Edit: It fires click events individually though, so you would get:
Single Click THEN
Double Click THEN
Triple Click. So you would still have to do some timing trickery.
The code is:
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class Main {
public static void main(String[] argv) throws Exception {
JTextField component = new JTextField();
component.addMouseListener(new MyMouseListener());
JFrame f = new JFrame();
f.add(component);
f.setSize(300, 300);
f.setVisible(true);
component.addMouseListener(new MyMouseListener());
}
}
class MyMouseListener extends MouseAdapter {
public void mouseClicked(MouseEvent evt) {
if (evt.getClickCount() == 3) {
System.out.println("triple-click");
} else if (evt.getClickCount() == 2) {
System.out.println("double-click");
}
}
}
Here is what i have done to achieve this, this actually worked fine for me. A delay is necessary to detect the type of click. You can choose it. The following delays if a triple click can be happened within 400ms. You can decrease it to the extent till a consecutive click is not possible. If you are only worrying about the delay, then this is a highly negligible delay which must be essential to carry this out.
Here flag and t1 are global variables.
public void mouseClicked(MouseEvent e)
{
int count=e.getClickCount();
if(count==3)
{
flag=true;
System.out.println("Triple click");
}
else if(count==2)
{
try
{
t1=new Timer(1,new ActionListener(){
public void actionPerformed(ActionEvent ae)
{
if(!flag)
System.out.println("Double click");
flag=false;
t1.stop();
}
});
t1.setInitialDelay(400);
t1.start();
}catch(Exception ex){}
}
}
I am using this mmscomputing library as java applet to scan an image or document.
Using swings,awt i created one scan button which is acquiring scanner by calling scanner.acquire() method of mmscomputing jar..
and then placing that scanned image into jpanel for displaying.
Problem is, first time when i start my applet and hitting my scan button..scanning works fine..Twain states it goes into are: 3,4,5,6,7,5,4,3
then second time,hitting my scan button again ..
Twain states it goes into are: 3,4,5,4,3
It's not going into image transfer ready and transferring state and thus not into below CODE IF loop
if (type.equals(ScannerIOMetadata.ACQUIRED))
so i am not able to see the new scanned image into my jpanel second time...
then third time, hitting my scan button .. again it works fine.. getting into all states.
So i mean, For alternatively turns or restarting the java applet again ..it works.
what would be the issue.. ?
I want, every time when i hit scan button it should get me a new image into Jpanel.. but it's doing alternative times.
can i forcefully explicitly set or change twain states to come into 6th and 7th states..
or is there some twain source initialisation problem occurs second time?
because restarting applet is doing fine every time.. or some way to reinitialise applet objects everytime on clicking scan button..as it would feel like I am restarting applet everytime on clicking scan button...
I am not getting it..
Below is the sample code:
import uk.co.mmscomputing.device.twain.TwainConstants;
import uk.co.mmscomputing.device.twain.TwainIOMetadata;
import uk.co.mmscomputing.device.twain.TwainSource;
import uk.co.mmscomputing.device.twain.TwainSourceManager;
public class XXCrop extends JApplet implements PlugIn, ScannerListener
{
private JToolBar jtoolbar = new JToolBar("Toolbar", JToolBar.HORIZONTAL);
ImagePanel ipanel;
Image im =null;
BufferedImage imageforCrop;
ImagePlus imp=null;
int imageWidth;
int imageHeight;
private static final long serialVersionUID = 1L;
Container content = null;
private JPanel jContentPane = null;
private JButton jButton = null;
private JButton jButton1 = null;
JCheckBox clipBox = null;
JPanel crpdpanel=null;
JPanel cpanel=null;
private Scanner scanner=null;
private TwainSource ts ;
private boolean is20;
ImagePanel imagePanel,imagePanel2 ;
public static void main(String[] args) {
new XXCrop().setVisible(true);
}
public void run(String arg0) {
new XXCrop().setVisible(false);
repaint();
}
/**
* This is the default constructor
*/
public XXCrop() {
super();
init();
try {
scanner = Scanner.getDevice();
if(scanner!=null)
{
scanner.addListener(this);
}
} catch (Exception e)
{
e.printStackTrace();
}
}
/**
* This method initializes this
*
* #return void
*/
public void init()
{
this.setSize(1200, 600);
this.setLayout(null);
//this.revalidate();
this.setContentPane(getJContentPane());
}
private JToolBar getJToolBar()
{
jtoolbar.add(getJButton1());
jtoolbar.add(getJButton());
jtoolbar.setName("My Toolbar");
jtoolbar.addSeparator();
Rectangle r=new Rectangle(0, 0,1024, 30 );
jtoolbar.setBounds(r);
return jtoolbar;
}
private JPanel getJContentPane()
{
if (jContentPane == null)
{
jContentPane = new JPanel();
jContentPane.setLayout(null);
jContentPane.add(getJToolBar());
}
return jContentPane;
}
private JButton getJButton() {
if (jButton == null) {
jButton = new JButton();
jButton.setBounds(new Rectangle(4, 16, 131, 42));
jButton.setText("Select Device");
jButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
if (scanner.isBusy() == false) {
selectDevice();
}
}
});
}
return jButton;
}
/* Select the twain source! */
public void selectDevice() {
try {
scanner.select();
} catch (ScannerIOException e1) {
IJ.error(e1.toString());
}
}
private JButton getJButton1()
{
if (jButton1 == null) {
jButton1 = new JButton();
jButton1.setBounds(new Rectangle(35,0, 30, 30));
jButton1.setText("Scan");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e)
{//jContentPane.remove(crpdpanel);
//jContentPane.removeAll();
//jContentPane.repaint();
//jContentPane.revalidate();
getScan();
}
});
}
return jButton1;
}
public void getScan()
{
try
{
//scanner = Scanner.getDevice();
//scanner.addListener(this);
scanner.acquire();
}
catch (ScannerIOException e1)
{
IJ.showMessage("Access denied! \nTwain dialog maybe already opened!");
e1.printStackTrace();
}
}
public Image getImage()
{
Image image = imp.getImage();
return image;
}
/*Image cimg;
public Image getCimg()
{
return cimg;
}*/
public void update(ScannerIOMetadata.Type type, ScannerIOMetadata metadata) {
if (type.equals(ScannerIOMetadata.ACQUIRED))
{
//imagePanel.revalidate();
//imagePanel.repaint();
//imagePanel.invalidate();
//jContentPane.remove(ipanel);
//ipanel.repaint();
if(imp!=null)
{
jContentPane.remove(ipanel);
jContentPane.remove(cpanel);
jContentPane.remove(crpdpanel);
}
imp = new ImagePlus("Scan", metadata.getImage());
//imp.show();
im = imp.getImage();
//imagePanel = new ImagePanel(im,imageWidth,imageHeight);
imagePanel = new ImagePanel(im);
imagePanel.updateUI();
imagePanel.repaint();
imagePanel.revalidate();
ClipMover mover = new ClipMover(imagePanel);
imagePanel.addMouseListener(mover);
imagePanel.addMouseMotionListener(mover);
ipanel = imagePanel.getPanel();
ipanel.setBorder(new LineBorder(Color.blue,1));
ipanel.setBorder(BorderFactory.createTitledBorder("Scanned Image"));
ipanel.setBounds(0, 30,600, 600);
ipanel.repaint();
ipanel.revalidate();
ipanel.updateUI();
jContentPane.add(ipanel);
jContentPane.getRootPane().revalidate();
jContentPane.updateUI();
//jContentPane.repaint();
// cimg=imagePanel.getCimg();
// ImagePanel cpanel = (ImagePanel) imagePanel.getUIPanel();
/*
cpanel.setBounds(700, 30,600, 800);
jContentPane.add(imagePanel.getUIPanel());
*/
cpanel = imagePanel.getUIPanel();
cpanel.setBounds(700, 30,300, 150);
cpanel.repaint();
cpanel.setBorder(new LineBorder(Color.blue,1));
cpanel.setBorder(BorderFactory.createTitledBorder("Cropping Image"));
jContentPane.add(cpanel);
jContentPane.repaint();
jContentPane.revalidate();
metadata.setImage(null);
try {
new uk.co.mmscomputing.concurrent.Semaphore(0, true).tryAcquire(2000, null);
} catch (InterruptedException e) {
IJ.error(e.getMessage());
}
}
else if (type.equals(ScannerIOMetadata.NEGOTIATE)) {
ScannerDevice device = metadata.getDevice();
try {
device.setResolution(100);
} catch (ScannerIOException e) {
IJ.error(e.getMessage());
}
try{
device.setShowUserInterface(false);
// device.setShowProgressBar(true);
// device.setRegionOfInterest(0,0,210.0,300.0);
device.setResolution(100); }catch(Exception e){
e.printStackTrace(); }
}
else if (type.equals(ScannerIOMetadata.STATECHANGE)) {
System.out.println("Scanner State "+metadata.getStateStr());
System.out.println("Scanner State "+metadata.getState());
//switch (metadata.ACQUIRED){};
ts = ((TwainIOMetadata)metadata).getSource();
//ts.setCancel(false);
//ts.getState()
//TwainConstants.STATE_TRANSFERREADY
((TwainIOMetadata)metadata).setState(6);
if ((metadata.getLastState() == 3) && (metadata.getState() == 4)){}
// IJ.error(metadata.getStateStr());
}
else if (type.equals(ScannerIOMetadata.EXCEPTION)) {
IJ.error(metadata.getException().toString());
}
}
public void stop(){ // execute before System.exit
if(scanner!=null){ // make sure user waits for scanner to finish!
scanner.waitToExit();
ts.setCancel(true);
try {
scanner.setCancel(true);
} catch (ScannerIOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I'm not an expert, but when ScannerIOMetadata.STATECHANGE shouldn't you check if the scanning is complete?
And if it is you should initialize the scanner again.
Something like that:
if (metadata.isFinished())
{
twainScanner = (TwainScanner) Scanner.getDevice();
}