I'm trying the code I found on the voted answer from this question: Download file using java apache commons?
It's a download application, take a little look, (I'm not much familiar with JFrames and ActionEvents)
Download.java
package main;
public class Download extends JFrame implements Runnable{
public static int total;
public static int done;
private static class ProgressListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
done = (int)((DownloadCountingOutputStream) e.getSource()).getByteCount();
jbar.repaint();
DownloadCountingOutputStream.parent.draw((int)((DownloadCountingOutputStream) e.getSource()).getByteCount());//redraw
DownloadCountingOutputStream.parent.repaint();
}
}
public static JProgressBar jbar = new JProgressBar();
public void draw(int downloaded){System.out.println("downloaded: "+downloaded+ " Total: "+total);
if (downloaded== 0){
Container cont = new Container();
setDefaultCloseOperation(3);
setSize(600, 450);
setResizable(false);
setVisible(true);
cont.add(jbar);
jbar.setBounds(40, 50, 500, 50);
jbar.setMaximum(total);//The total value of bytes to download
//jbar.setValue(50);
add(cont);
jbar.setVisible(true);
}
jbar.setValue(downloaded);
//This should update the value of the progress Bar
}
public void run() {
URL dl = null;
File fl = null;
OutputStream os = null;
InputStream is = null;
ProgressListener progressListener = new ProgressListener();
draw(done);
try {
fl = new File(System.getProperty("user.home").replace("\\", "/") + "/Desktop/afile.rar");
dl = new URL("https://dl.dropbox.com/u/48076798/afile.rar");
os = new FileOutputStream(fl);
is = dl.openStream();
total = Integer.parseInt(dl.openConnection().getHeaderField("Content-Length"));
String total = dl.openConnection().getHeaderField("Content-Length");
DownloadCountingOutputStream dcount = new DownloadCountingOutputStream(os);
dcount.setListener(progressListener);
dcount.setParent(this);
IOUtils.copy(is, dcount);
} catch (Exception e) {
System.out.println(e);
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
DownloadCountingOutputStream.java
package main;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.commons.io.output.CountingOutputStream;
public class DownloadCountingOutputStream extends CountingOutputStream {
private ActionListener listener = null;
public static Download parent;
public DownloadCountingOutputStream(OutputStream out) {
super(out);
}
public void setListener(ActionListener listener) {
this.listener = listener;
}
public void setParent(Download o){
parent = o;
}
#Override
protected void afterWrite(int n) throws IOException {
super.afterWrite(n);
if (listener != null) {
listener.actionPerformed(new ActionEvent(this, 0, null));
}
}
}
It's difficult to tell from the code sample you've provide...
The main cause of this problem is trying to update the UI while blocking from the Event Dispatching Thread (EDT).
It's important to NEVER do any long running or blocking operations within the EDT as this will prevent repaint requests from been acted upon.
For more information have a read through Concurrency in Swing
The example below demonstrates the use of a SwingWorker that provides progress updates that are re-synced with the UI
public class TestProgress {
public static void main(String[] args) {
new TestProgress();
}
public TestProgress() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
ProgressPane progressPane = new ProgressPane();
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(progressPane);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
progressPane.doWork();
}
});
}
public class ProgressPane extends JPanel {
private JProgressBar progressBar;
public ProgressPane() {
setLayout(new GridBagLayout());
progressBar = new JProgressBar();
add(progressBar);
}
public void doWork() {
Worker worker = new Worker();
worker.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
progressBar.setValue((Integer) evt.getNewValue());
}
}
});
worker.execute();
}
}
public class Worker extends SwingWorker<Object, Object> {
#Override
protected Object doInBackground() throws Exception {
for (int index = 0; index < 1000; index++) {
int progress = Math.round(((float) index / 1000f) * 100f);
setProgress(progress);
Thread.sleep(10);
}
return null;
}
}
}
Related
I am developing a messaging application with sockets. I have an initial JFrame that allows the user to choose a contact to connect to, and lets them choose if they'd like to be the client or the server. When they make this choice, it calls a method in which creates the chat window frame, and also uses a SwingWorker to initialise a connection, create an action listner on the send buton of the chat window so that it sends messages when pressed, and creates a SocketListener that is always listening while the window is open.
This works just fine, however if I close the chat window and then reopen it by choosing server or client again, nothing happens - the frame loads up however I cannot send any messages on it.
I'm not sure what the problem is here, could it be that i'm not disposing of the swing worker or the frame properly? Any help would be greatly appreciated and apologies for my lack of knowledge.
Here is the relevent code for this:
public static void server() {
JButton server = new JButton();
server.setText("Server");
server.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String name = nameChoice;
String ip = ipChoice;
String port = portChoice;
try {
server2(port);
} catch (IOException e1) {
e1.printStackTrace();
} catch (Exception e1) {
e1.printStackTrace();
}
}
});
panel.add(server);
}
public static void server2(String port) throws Exception {
gui.frame();
SwingWorker worker = new SwingWorker() {
#Override
protected Void doInBackground() throws Exception {
sockets.serverSetup(port);
gui.sendButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String msg = gui.newMsg.getText();
gui.newMsg.setText(null);
try {
sockets.sendMsg(msg);
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
while(gui.open==true) {
sockets.receiveMsg();
}
sockets.closeConnection();
System.out.println("Closed");
return null;
}
};
worker.execute();
}
network
package com.company;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Vector;
public class network {
static ServerSocket s;
static Socket s1;
static OutputStream s1out;
static DataOutputStream dos;
static InputStream s1in;
static chatWindowScreen gui = new chatWindowScreen();
static String st;
public static Vector sentVec = new Vector();
public static Vector receivedVec = new Vector();
public static Vector messages = new Vector();
public static void serverSetup(String port) throws IOException {
System.out.println("Test");
int portInt = Integer.parseInt(port);
s = new ServerSocket(portInt);
s1 = s.accept();
System.out.println("Server set up");
//sendMsg("Hi");
}
public static void clientSetup(String port, String ip) throws IOException {
System.out.println("Test");
int portInt = Integer.parseInt(port);
s1 = new Socket(ip, portInt);
System.out.println("Client set up");
//receiveMsg();
}
public static void closeConnection() throws IOException {
dos.close();
s1out.close();
s1.close();
}
public static void sendMsg(String message) throws IOException {
System.out.println("Test");
s1out = s1.getOutputStream();
dos = new DataOutputStream(s1out);
dos.writeUTF(message);
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String t1 = sdf.format(cal.getTime());
message = t1 + " - " + message;
sentVec.add(message);
receivedVec.add("");
messages.add(message);
gui.sent.setText("Sent \n");
for (int i = 0; i < sentVec.size(); i++) {
gui.sent.append(sentVec.get(i) + "\n");
}
gui.received.setText("Received \n");
for (int i = 0; i < receivedVec.size(); i++) {
gui.received.append(receivedVec.get(i) + "\n");
}
System.out.println("complete");
}
public static void receiveMsg() throws IOException {
System.out.println("Test");
s1in = s1.getInputStream();
DataInputStream dis = new DataInputStream(s1in);
st = (dis.readUTF());
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String t1 = sdf.format(cal.getTime());
st = t1 + " - " + st;
receivedVec.add(st);
sentVec.add("");
messages.add(st);
gui.received.setText("Received \n");
for (int i = 0; i < receivedVec.size(); i++) {
gui.received.append((String) receivedVec.get(i) + "\n");
}
gui.sent.setText("Sent \n");
for (int i = 0; i < sentVec.size(); i++) {
gui.sent.append((String) sentVec.get(i) + "\n");
}
}
public static Vector getSentVec() {
return sentVec;
}
public static Vector getReceivedVec() {
return receivedVec;
}
}
chatWindowScreen
package com.company;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.IOException;
import java.util.Vector;
public class chatWindowScreen {
static JFrame frame = new JFrame();
static JPanel panel = new JPanel();
static JTextArea sent;
static JTextArea received;
static JTextArea newMsg;
static JButton sendButton;
public static String msg;
static boolean open = true;
static network sockets = new network();
public static boolean close = false;
public void frame() throws Exception {
System.out.println("GUI opened");
frame.setTitle("Messaging Application");
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.addWindowListener(new WindowListener() {
#Override
public void windowOpened(WindowEvent e) {
}
#Override
public void windowClosing(WindowEvent e) {
}
#Override
public void windowClosed(WindowEvent e) {
System.out.println("Closed");
panel.removeAll();
open=false;
}
#Override
public void windowIconified(WindowEvent e) {
}
#Override
public void windowDeiconified(WindowEvent e) {
}
#Override
public void windowActivated(WindowEvent e) {
}
#Override
public void windowDeactivated(WindowEvent e) {
}
});
sentMsg();
receivedMsg();
msgBox();
sendBtn();
save();
frame.add(panel);
frame.setVisible(true);
}
public static void sentMsg() {
sent = new JTextArea(15, 20);
sent.setText("Sent" + "\n");
sent.setLineWrap(true);
sent.setEditable(false);
JScrollPane pane = new JScrollPane(sent, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
panel.add(pane);
}
public static void receivedMsg() {
received = new JTextArea(15, 20);
received.setText("Received" + "\n");
received.setEditable(false);
received.setLineWrap(true);
JScrollPane pane1 = new JScrollPane(received, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
panel.add(pane1);
}
public static void msgBox() {
newMsg = new JTextArea(1, 15);
newMsg.setText("");
newMsg.setLineWrap(true);
JScrollPane pane2 = new JScrollPane(newMsg, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
panel.add(pane2);
}
public static void sendBtn() {
sendButton = new JButton();
sendButton.setText("Send!");
/*sendButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
msg = newMsg.getText();
newMsg.setText(null);
SwingWorker worker = new SwingWorker() {
#Override
protected Object doInBackground() throws Exception {
sockets.sendMsg(msg);
return null;
}
};
worker.execute();
try {
sockets.sendMsg(msg);
} catch (IOException e1) {
e1.printStackTrace();
}
msg = null;
}
});*/
panel.add(sendButton);
}
public static void save(){
JButton save = new JButton();
save.setText("Save Conversation");
save.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
saveToFile save = new saveToFile();
}
});
panel.add(save);
}
}
public class frame11 extends javax.swing.JFrame implements ActionListener,
PropertyChangeListener {
public String[] columnNames = { "Path",
"File Name",
"Size"};
public Object[][] data ;
int isJPEG (String s) throws IOException
{ int c=0;//not jpeg
if ( (s.endsWith(".JPG")) || (s.endsWith(".JPEG"))||(s.endsWith(".jpeg"))||(s.endsWith(".jpg")))
{
c=1;//is jpeg
}
return c;
}
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
JFileChooser fch = new JFileChooser("C:\\");
jProgressBar1.setValue(0);
jProgressBar1.setStringPainted(true);
jTextField1.setText(null);
jTextField2.setText(null);
jTextField4.setText(null);
jLabel7.setText(null);
data = new Object[15][3];
jTable2.setModel(new DefaultTableModel(data, columnNames));
fch.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int ret = fch.showOpenDialog(null);
int apr=0;
if (ret==JFileChooser.APPROVE_OPTION)
{ apr=1;
jTextField1.setText(fch.getSelectedFile().toString());
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
}
else jTextField1.setText("Nothing clicked!!!");
if (apr==1) {
jLabel7.setText("Wait Please, While searching ...");
task = new Task();
task.addPropertyChangeListener(this);
task.execute();
EventQueue.invokeLater(new Runnable() { // Added
#Override
public void run() {
File f = fch.getSelectedFile();
String s= f.getAbsolutePath();
int cnt;
int st=0;
Path myfile = Paths.get(s);
if(f.isDirectory()&& Files.isReadable(myfile)){
try {
st=st+CheckFiles(f);
cnt=count(f);
String ss=Integer.toString(cnt);
jTextField2.setText(ss);
jTextField4.setText(Integer.toString(st));
} catch (IOException ex) {
Logger.getLogger(frame1.class.getName()).log(Level.SEVERE, null, ex);
}
}
jLabel7.setText("Scanning Finished. Thanks for waiting ");
}
});
}
}//GEN-LAST:event_jButton1ActionPerformed
private Task task;
#Override
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
int progress = (Integer) evt.getNewValue();
jProgressBar1.setValue(progress);
System.out.println("Property changed");
}
}
//#Override
public void actionPerformed(ActionEvent e) {
}
class Task extends SwingWorker<Void, Void> {
#Override
public Void doInBackground() {
Random random = new Random();
int progress = 0;
setProgress(0);
while (progress < 100) {
try {
Thread.sleep(random.nextInt(100));
} catch (InterruptedException ignore) {}
progress += random.nextInt(10);
setProgress(Math.min(progress, 100));
}
return null;
}
/*
* Executed in event dispatching thread
*/
#Override
public void done() {
Toolkit.getDefaultToolkit().beep();
setCursor(null);
}
}
I would like your help, I'm trying to scan my pc for JPEG images to count them. I have two problems, the first is that I'm using a jtable, but the results is never added until the program ends, and the progress bar isn't synchronized sometimes it ends before the program and sometimes after. please help me resolve these two problems and thank you.
You're using a SwingWorker in order to create a background thread -- good -- but you're making Swing calls directly from that background thread -- bad:
jProgressBar1.setValue(n);
Instead call setProgress(...) from within your SwingWorker, and add a PropertyChangeListener to the worker that listens for changes to the worker's "progress" bound property.
For examples:
How do I make my SwingWorker example work properly?
Cant get JProgressBar to update from SwingWorker class
JProgressBar Tutorial
For an example of an mcve that shows an example of use of a JProgressBar with a SwingWorker:
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
#SuppressWarnings("serial")
public class TestProgress2 extends JPanel {
private JProgressBar progressBar = new JProgressBar(0, 100);
private Action startBackgroundTaskAction = new StartBackgroundTaskAction();
public TestProgress2() {
progressBar.setStringPainted(true);
add(progressBar);
add(new JButton(startBackgroundTaskAction));
}
public void setActionEnabled(boolean enabled) {
startBackgroundTaskAction.setEnabled(enabled);
}
private class StartBackgroundTaskAction extends AbstractAction {
public StartBackgroundTaskAction() {
super("Start Background Task");
putValue(MNEMONIC_KEY, KeyEvent.VK_S);
}
#Override
public void actionPerformed(ActionEvent e) {
progressBar.setString(null);
progressBar.setValue(0);
setActionEnabled(false);
MyTask myTask = new MyTask();
myTask.addPropertyChangeListener(new MyTaskListener());
myTask.execute();
}
}
private class MyTaskListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent pcEvt) {
MyTask myTask = (MyTask) pcEvt.getSource();
if ("progress".equals(pcEvt.getPropertyName())) {
int progress = myTask.getProgress();
progressBar.setValue(progress);
}
if (pcEvt.getNewValue() == SwingWorker.StateValue.DONE) {
setActionEnabled(true);
progressBar.setString("Done");
try {
myTask.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
private class MyTask extends SwingWorker<Void, Void> {
#Override
protected Void doInBackground() throws Exception {
Random random = new Random();
int progress = 0;
setProgress(0);
while (progress < 100) {
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException ignore) {}
progress += random.nextInt(10);
setProgress(Math.min(progress, 100));
}
return null;
}
}
private static void createAndShowGui() {
TestProgress2 mainPanel = new TestProgress2();
JFrame frame = new JFrame("TestProgress2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
EDIT--CORRECTED CODE BASED ON ACCEPTED ANSWER IS SHOWN AT BOTTOM OF THIS POST.
I found a way (written by Andremoniy) to catch double- and triple-clicks without firing single- and double-clicks. It works very well for my purposes.
I modified it so that it could have the click interval tweaked by the implementation. That also works well.
My modifications include making it an abstract class, defining the 5 abstract methods that the implementation would have to define (methods for single, double, triple, and "many" clicks as well as the click interval tweaker).
Here is the modified version (the println statements are instructive):
public abstract class Click123 extends JPanel
{
public abstract void singleClick();
public abstract void doubleClick();
public abstract void tripleClick();
public abstract void manyClick();
public abstract int getFreq();
public Click123()
{
addMouseListener
(
new MouseAdapter()
{
Thread cp = null;
public void mouseClicked(MouseEvent e)
{
if (cp != null && cp.isAlive())
cp.interrupt();
if (e.getClickCount() == 1)
{
cp = new Thread(new ClickProcessor(new Callable<Void>() {
#Override public Void call() throws Exception {
singleClick();
return null;
}
}));
cp.start();
}
else if (e.getClickCount() == 2)
{
cp = new Thread(new ClickProcessor(new Callable<Void>() {
#Override public Void call() throws Exception {
doubleClick();
return null;
}
}));
cp.start();
}
else if (e.getClickCount() == 3)
{
cp = new Thread(new ClickProcessor(new Callable<Void>()
{
#Override public Void call() throws Exception {
tripleClick();
return null;
}
})
);
cp.start();
}
else manyClick();
} // mouseClicked
} // new MouseAdapter
); // add mouseListener
} // Click123
class ClickProcessor implements Runnable
{
Callable<Void> eventProcessor;
ClickProcessor(Callable<Void> eventProcessor)
{
this.eventProcessor = eventProcessor;
}
#Override public void run()
{
try
{
Thread.sleep(getFreq());
eventProcessor.call();
} catch (InterruptedException e) { System.out.println(e);}
catch (Exception e) { System.out.println(e);}
} // run
} // class ClickProcessor
} // class Click123
Here's the implementing program:
public class NewMain1 {
static int INITIAL_CLICK_FREQUENCY = ((Integer)Toolkit.getDefaultToolkit()
.getDesktopProperty("awt.multiClickInterval"));
public static int CLICK_FREQUENCY;
static JSpinner spinner = new JSpinner();
static final JLabel ch = new JLabel("Click here to test");
public static void main(String[] args) {
CLICK_FREQUENCY = INITIAL_CLICK_FREQUENCY;
spinner = new JSpinner();
spinner.setModel(new SpinnerNumberModel(CLICK_FREQUENCY, 200, 900, 50));
spinner.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
CLICK_FREQUENCY = (int) spinner.getValue();
}
});
Click123 frame = new Click123(){
public void singleClick(){
JOptionPane.showMessageDialog(null,"Single click at " + CLICK_FREQUENCY);
}
public void doubleClick(){
JOptionPane.showMessageDialog(null,"Double click at " + CLICK_FREQUENCY);
}
public void tripleClick(){
JOptionPane.showMessageDialog(null,"Triple click at " + CLICK_FREQUENCY);
}
public void manyClick(){
JOptionPane.showMessageDialog(null,"Many clicks at " + CLICK_FREQUENCY);
}
public int getFreq(){
return CLICK_FREQUENCY;
}
};
frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
frame.setLayout(new FlowLayout());
frame.setSize(500, 300);
ch.setBorder(new EtchedBorder());
frame.add(ch);
frame.add(spinner);
frame.setVisible(true);
} // main
}
As originally written, Click123 extends JFrame. I modified it (by changing the top line to extends JTextField) to work with a grid of type JTextField. Then I added a button to change the click interval on the fly. So now I have THREE identical (except for the extension type) huge hunks of code.
My question is this: How do I modify Click123 so that, without alteration, it can be used to make ANY component aware of single-, double-, and triple-clicks?
EDIT--SUMMARY OF NECESSARY CHANGES (For my own app, the abstract methods need MouseEvent to be passed in order to determine which component fired the clicks):
Class definition:
public abstract class Click123<T extends Component>
{
public abstract void singleClick(MouseEvent e); // same for 3 others
...
public Click123(T target)
{
target.addMouseListener
(
new MouseAdapter() ...
} ...
}
final added as modifier in order to pass MouseEvent:
public void mouseClicked(final MouseEvent e)
Pass MouseEvent:
singleClick(e); // same for doubleClick and tripleClick and manyClick
Receive MouseEvent in order to determine which component fired the clicks:
public void doubleClick(MouseEvent e)
Implementation:
frame = new JPanel();
new Click123(frame) {
Generics aren't necessary. All you need is to add the MouseListener to a Component.
public abstract class Click123 // doesn't extend anything
{
public Click123(Component comp)
{
comp.addMouseListener(new MouseAdapter() {
// ...
}));
}
}
Now you can just pass the JFrame, or whatever Component you want:
Click123 handler = new Click123(myJFrame){
public void singleClick(){
JOptionPane.showMessageDialog(null,"Single click at " + CLICK_FREQUENCY);
}
// Other implementing methods here
}
Generics are part of the solution. Just do the following:
Make your class Click123<T extends Component>
Make your constructor public Click123(T targetedComponent) {
Call targetedComponent.addMouseListener rather than addMouseListener
Create a JFrame or JPanel or whatever and then pass it to your new Click123 as a constructor argument. Then use your JFrame where you were using your Click123.
Upon request, I am posting code that works. Edits in original post are too scattered to be useful. Original code modifications are flagged with //////////.
package clickForm;
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.concurrent.Callable;
public abstract class Click123<T extends Component> ////////////////
{
public abstract void singleClick(MouseEvent e); ////////////////
public abstract void doubleClick(MouseEvent e); ////////////////
public abstract void tripleClick(MouseEvent e); ////////////////
public abstract void manyClick(MouseEvent e); ////////////////
public abstract int getFreq();
public Click123(T target) ////////////////
{
target.addMouseListener ////////////////
(
new MouseAdapter() ////////////////
{
Thread cp = null;
public void mouseClicked(final MouseEvent e)
{
if (cp != null && cp.isAlive())
cp.interrupt();
if (e.getClickCount() == 1)
{
cp = new Thread(new ClickProcessor(new Callable<Void>() {
#Override public Void call() throws Exception {
singleClick(e); //////////////////////////////////////////
return null;
}
}));
cp.start();
}
else if (e.getClickCount() == 2)
{
cp = new Thread(new ClickProcessor(new Callable<Void>() {
#Override public Void call() throws Exception {
doubleClick(e); //////////////////////////////////////////
return null;
}
}));
cp.start();
}
else if (e.getClickCount() == 3)
{
cp = new Thread(new ClickProcessor(new Callable<Void>()
{
#Override public Void call() throws Exception {
tripleClick(e); //////////////////////////////////////////
return null;
}
})
);
cp.start();
}
else manyClick(e); //////////////////////////////////////////
} // mouseClicked
} // new MouseAdapter
); // add mouseListener
} // Click123
class ClickProcessor implements Runnable
{
Callable<Void> eventProcessor;
ClickProcessor(Callable<Void> eventProcessor)
{
this.eventProcessor = eventProcessor;
}
#Override public void run()
{
try
{
Thread.sleep(getFreq());
eventProcessor.call();
} catch (InterruptedException e) { System.out.println(e);}
catch (Exception e) { System.out.println(e);}
} // run
} // class ClickProcessor
} // class Click123
Implementation:
package clickForm;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE;
import javax.swing.border.EtchedBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Main {
static int CLICK_FREQUENCY = (int) Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval");
static JSpinner spinner = new JSpinner();
static final JLabel ch = new JLabel("Click here to test");
static JFrame frame = new JFrame();
public static void main(String[] args) {
spinner = new JSpinner();
spinner.setModel(new SpinnerNumberModel(CLICK_FREQUENCY, 200, 900, 50));
spinner.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
CLICK_FREQUENCY = (int) spinner.getValue();
}
});
new Click123(ch){ /////////////////////////////////////////////
#Override
public void singleClick(MouseEvent e) { //////////////////////////////
JOptionPane.showMessageDialog(null,"Single at " + CLICK_FREQUENCY);
}
#Override
public void doubleClick(MouseEvent e) { //////////////////////////////
JOptionPane.showMessageDialog(null,"Double at " + CLICK_FREQUENCY);
}
#Override
public void tripleClick(MouseEvent e) { //////////////////////////////
JOptionPane.showMessageDialog(null,"Triple at " + CLICK_FREQUENCY);
}
#Override
public void manyClick(MouseEvent e) { //////////////////////////////
JOptionPane.showMessageDialog(null,"Many at " + CLICK_FREQUENCY);
}
#Override
public int getFreq() {
return CLICK_FREQUENCY;
}
};
frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
frame.setLayout(new FlowLayout());
frame.setSize(500, 300);
ch.setBorder(new EtchedBorder());
frame.add(ch);
frame.add(spinner);
frame.setVisible(true);
} // main
}
I'm trying to capture the screen without including my application's window. To do this I first call setVisible(false), then I call the createScreenCapture method, and finally I call setVisible(true). This isn't working however and I'm still getting my applications window in the screen capture. If I add a call to sleep this seems to resolve the issue, but I know this is bad practice. What is the right way to do this?
Code:
setVisible(false);
BufferedImage screen = robot.createScreenCapture(rectScreenSize);
setVisible(true);
Have you tried to use SwingUtilities.invokeLater() and run the capture inside of the runnable passed as an argument? My guess is that the repaint performed to remove your application is performed right after the end of the current event in the AWT-EventQueue and thus invoking the call immediately still captures your window. Invoking the createCapture in a delayed event through invokeLater should fix this.
you have to delay this action by implements Swing Timer, for example
import javax.imageio.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
public class CaptureScreen implements ActionListener {
private JFrame f = new JFrame("Screen Capture");
private JPanel pane = new JPanel();
private JButton capture = new JButton("Capture");
private JDialog d = new JDialog();
private JScrollPane scrollPane = new JScrollPane();
private JLabel l = new JLabel();
private Point location;
private Timer timer1;
public CaptureScreen() {
capture.setActionCommand("CaptureScreen");
capture.setFocusPainted(false);
capture.addActionListener(this);
capture.setPreferredSize(new Dimension(300, 50));
pane.add(capture);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(pane);
f.setLocation(100, 100);
f.pack();
f.setVisible(true);
createPicContainer();
startTimer();
}
private void createPicContainer() {
l.setPreferredSize(new Dimension(700, 500));
scrollPane = new JScrollPane(l,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.setBackground(Color.white);
scrollPane.getViewport().setBackground(Color.white);
d.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
d.add(scrollPane);
d.pack();
d.setVisible(false);
d.addWindowListener(new WindowListener() {
public void windowOpened(WindowEvent e) {
}
public void windowClosing(WindowEvent e) {
f.setVisible(true);
}
public void windowClosed(WindowEvent e) {
}
public void windowIconified(WindowEvent e) {
}
public void windowDeiconified(WindowEvent e) {
}
public void windowActivated(WindowEvent e) {
}
public void windowDeactivated(WindowEvent e) {
}
});
}
private void startTimer() {
timer1 = new Timer(1000, new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
capture.doClick();
f.setVisible(false);
}
});
}
});
timer1.setDelay(500);
timer1.setRepeats(false);
timer1.start();
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("CaptureScreen")) {
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); // gets the screen size
Robot r;
BufferedImage bI;
try {
r = new Robot(); // creates robot not sure exactly how it works
Thread.sleep(1000); // waits 1 second before capture
bI = r.createScreenCapture(new Rectangle(dim)); // tells robot to capture the screen
showPic(bI);
saveImage(bI);
} catch (AWTException e1) {
e1.printStackTrace();
} catch (InterruptedException e2) {
e2.printStackTrace();
}
}
}
private void saveImage(BufferedImage bI) {
try {
ImageIO.write(bI, "JPG", new File("screenShot.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
}
private void showPic(BufferedImage bI) {
ImageIcon pic = new ImageIcon(bI);
l.setIcon(pic);
l.revalidate();
l.repaint();
d.setVisible(false);
//location = f.getLocationOnScreen();
//int x = location.x;
//int y = location.y;
//d.setLocation(x, y + f.getHeight());
d.setLocation(150, 150);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
d.setVisible(true);
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
CaptureScreen cs = new CaptureScreen();
}
});
}
}
I want to prevent multiple instances of application being launched in java. I know 2 methods for this:
locking file
locking socket
But which is one is more efficient and good to use? Which one should I use?
Any other solution to do the same are also welcome.
There is a library called jUnique which does that and will save you the bother of implementing it yourself.
If you deploy with Java WebStart the SingleInstanceService does this.
See http://download.oracle.com/javase/6/docs/technotes/guides/javaws/developersguide/faq.html#218
EDIT: I tried that with Win200864b(version isn't important) and alive JFrame and move toFront() or Iconified in SystemTray with JFrame.DO_NOTHING_ON_CLOSE
public interface ApplicationStartedListener {
void applicationStarted();
void foreignApplicationStarted(String name);
void messageArrived(Object obj);
}
//
import java.io.Serializable;
public class ClassCheck implements Serializable {
private static final long serialVersionUID = 1L;
private String className = null;
public ClassCheck() {
}
public ClassCheck(String className) {
setClassName(className);
}
#Override
public String toString() {
return this.className;
}
public String getClassName() {
return this.className;
}
public void setClassName(String className) {
this.className = className;
}
}
//
import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.io.File;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class RunOnceFromFile {
private SingleInstanceController sic = null;
private JFrame frame;
private Robot r;
private JTextField tf;
public RunOnceFromFile() {
try {
r = new Robot();
} catch (AWTException ex) {
ex.printStackTrace();
}
sic = new SingleInstanceController(new File(System.getProperty("java.io.tmpdir") + "Example.file"), "sic_example_application");
if (sic.isOtherInstanceRunning()) {
sic.sendMessageToRunningApplication("toFront");
System.exit(0);
} else {
frame = new JFrame("TEST");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
tf = new JTextField("JTextFiled");
frame.add(tf, BorderLayout.NORTH);
frame.setExtendedState(Frame.ICONIFIED);
frame.setExtendedState(Frame.NORMAL);
frame.setExtendedState(frame.getExtendedState() | JFrame.ICONIFIED);
frame.setExtendedState(frame.getExtendedState() & (~JFrame.ICONIFIED));
frame.setLocationRelativeTo(null);
frame.setVisible(true);
sic.registerApplication();
sic.addApplicationStartedListener(new ApplicationStartedListener() {
public void applicationStarted() {
Runnable doRun = new Runnable() {
public void run() {
frame.toFront();
}
};
SwingUtilities.invokeLater(doRun);
}
public void foreignApplicationStarted(final String name) {
Runnable doRun = new Runnable() {
public void run() {
frame.toFront();
}
};
SwingUtilities.invokeLater(doRun);
}
public void messageArrived(final Object obj) {
Runnable doRun = new Runnable() {//activateWindow(frame);
public void run() {
frame.toFront();
}
};
SwingUtilities.invokeLater(doRun);
}
private void activateWindow(JFrame frame) {
frame.setExtendedState(Frame.ICONIFIED);
frame.setExtendedState(Frame.NORMAL);
frame.setAlwaysOnTop(true);
frame.setAlwaysOnTop(false);
Point location = MouseInfo.getPointerInfo().getLocation();
Point locationOnScreen = frame.getLocationOnScreen();
r.mouseMove(locationOnScreen.x + 100, locationOnScreen.y + 10);
r.mousePress(InputEvent.BUTTON1_MASK);
r.mouseRelease(InputEvent.BUTTON1_MASK);
r.mouseMove(location.x, location.y);
}
});
}
}
public static void main(String[] args) {
RunOnceFromFile roff = new RunOnceFromFile();
}
}
//
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class SingleInstanceController {
private String appname = null;
private Socket client = null;
private File file = null;
private ArrayList<ApplicationStartedListener> listener = null;
private ObjectInputStream ois = null;
private ObjectOutputStream oos = null;
private boolean result = false;
private ServerSocket server = null;
public SingleInstanceController(String appname) {
this(new File(System.getProperty("java.io.tmpdir") + "/923jhakE53Kk9235b43.6m7"), appname);
}
public SingleInstanceController(File file, String appname) {
this.file = file;
this.appname = appname;
this.listener = new ArrayList<ApplicationStartedListener>();
}
public void addApplicationStartedListener(ApplicationStartedListener asl) {
this.listener.add(asl);
}
public void removeApplicationStartedListener(ApplicationStartedListener asl) {
this.listener.remove(asl);
}
public boolean isOtherInstanceRunning() {
if (!this.file.exists()) {
return false;
}
return sendMessageToRunningApplication(new ClassCheck(this.appname));
}
public boolean sendMessageToRunningApplication(final Object obj) {
this.result = false;
try {
this.client = new Socket("localhost", getPortNumber());
new Thread(new Runnable() {
public void run() {
try {
SingleInstanceController.this.oos = new ObjectOutputStream(SingleInstanceController.this.client.getOutputStream());
SingleInstanceController.this.ois = new ObjectInputStream(SingleInstanceController.this.client.getInputStream());
SingleInstanceController.this.oos.writeObject(obj);
SingleInstanceController.this.oos.flush();
SingleInstanceController.this.result = SingleInstanceController.this.ois.readBoolean();
} catch (IOException e) {
SingleInstanceController.this.result = false;
}
}
}).start();
for (int i = 0; i < 10; i++) {
if (this.result == true) {
break;
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.client.close();
return this.result;
} catch (IOException e) {
return false;
}
}
public boolean registerApplication() {
try {
if (!this.file.exists()) {
if (!this.file.getParentFile().mkdirs() && !this.file.getParentFile().exists()) {
return false;
}
if (!this.file.createNewFile()) {
return false;
}
}
BufferedWriter wuffy = new BufferedWriter(new FileWriter(this.file));
int port = getFreeServerSocket();
if (port != -1) {
startServer();
}
wuffy.write(String.valueOf(port));
wuffy.close();
return true;
} catch (IOException e) {
return false;
}
}
protected void messageArrived(Object obj) {
for (ApplicationStartedListener asl : this.listener) {
asl.messageArrived(obj);
}
}
protected void applicationStartet() {
for (ApplicationStartedListener asl : this.listener) {
asl.applicationStarted();
}
}
protected void foreignApplicationStarted(String name) {
for (ApplicationStartedListener asl : this.listener) {
asl.foreignApplicationStarted(name);
}
}
private int getPortNumber() {
try {
BufferedReader buffy = new BufferedReader(new FileReader(this.file));
int port = Integer.parseInt(buffy.readLine().trim());
buffy.close();
return port;
} catch (Exception e) {
return -1;
}
}
private void startServer() {
new Thread(new Runnable() {
public void run() {
while (true) {
try {
SingleInstanceController.this.client = SingleInstanceController.this.server.accept();
if (SingleInstanceController.this.client.getInetAddress().isLoopbackAddress()) {
new Thread(new Runnable() {
public void run() {
try {
SingleInstanceController.this.oos = new ObjectOutputStream(SingleInstanceController.this.client.getOutputStream());
SingleInstanceController.this.ois = new ObjectInputStream(SingleInstanceController.this.client.getInputStream());
Object obj = SingleInstanceController.this.ois.readObject();
if (obj instanceof ClassCheck) {
if (obj.toString().equals(SingleInstanceController.this.appname)) {
SingleInstanceController.this.oos.writeBoolean(true);
applicationStartet();
} else {
SingleInstanceController.this.oos.writeBoolean(false);
foreignApplicationStarted(obj.toString());
}
} else {
messageArrived(obj);
SingleInstanceController.this.oos.writeBoolean(true);
}
SingleInstanceController.this.oos.flush();
SingleInstanceController.this.client.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
}
private int getFreeServerSocket() {
for (int i = 2000; i < 10000; i++) {
try {
this.server = new ServerSocket(i);
return i;
} catch (IOException ignore) {
}
}
return -1;
}
}
My vote goes to locking on a port (i think this is what you mean by socket). I don't know the exact reason for this. But in fact i come across only this as a solution in most practical projects. Though i will be happy to hear the alternative ways.
In response to your question, the port solution will keep more resources from the machine:
- You will keep a port locked: ports are limited and you may find problems with firewalls or other programs listening on the same port.
- You'll need an active thread.
The file solution will use less resources from the machine, to avoid locking the file forever you need to add a thread, to delete the file, in the addShutdownHook method from Runtime.
the serversocket solution is cross-platform . And will not be vulnerable to the program crashing and not resetting the lock.
File lock is better way to do- imo. When you create the file in User's Home directory, this will still work in a multi-user environment.
I came across - JUnique - haven't had a chance to use it
http://www.sauronsoftware.it/projects/junique/manual.php
I know that this question is pretty old, but I have to solve the same problem at the moment. I prefer the socket solution because I have never thought that such kind of task should have anything to do with the file system. It is better to solve the problem in memory and not in the file system I think.