I developed one swing application but each time you run application new window is opened.
I want that if one window is already opened other not allow to open.
Here is an example of a Java Single Application Instance:
A single instance application is one that only allows for 1 of the application to run no matter how many times the user tries to launch.
See also: A shorter example that does not notify the running instance.
The application tries to open a Socket on a specific port. In case another instance of your application is already running, opening the Socket fails.
This should already be sufficient for you, so you would not have to use the part of the code used to register new applications to the first one started.
Using a Socket has one great advantage compared to writing some sort of flag to the filesystem/registry/whatever:
It is removed even if your application crashes.
It actually sounds like you only want one application open at a time. In which case why not take out a file lock or similar when the application runs, and check that on start up. The headache (of course) is clearing up that lock in the event that your program doesn't exit cleanly.
My preferred solution is, as Peter Lang linked to, to use Sockets. When your app starts you can start a server socket listening for incoming connections on localhost (plus port of your choice). Before this happens in your code though you can try and make a connection to the server socket and if it is successful you know there is another instance already open, so you can quit the current instance with an appropriate message.
In your server socket implementation you can also add functionality that on receiving an incoming connection you actually force the current instance of the app to the foreground.
Do you mean run the GUI like a Singleton?, I have done this in the past by making a Static private "view manager" such that it is null and not created or visible until the first time the gui is created, after that just as with a classic singleton, the GUI is set to visible when the app is run again... I have a couple of Frameworks that follow this design--In these frameworks the GUI is not "primary" there are also command line and the like interfaces so the GUI is summoned via the command line...
public class Samp {
JFrame f=new JFrame();
File ff=new File("D:\\a.txt");
FileWriter fw;
public Samp() {
f.setBounds(0, 0, 200, 200);
try {
Scanner sc=new Scanner(ff);
if(!sc.hasNext()) {
fw=new FileWriter(ff);
fw.write("Running");
fw.close();
} else {
System.exit(0);
}
} catch(Exception e) {
System.out.println(e.getMessage());
}
WindowListener wndCloser = new WindowAdapter() {
public void windowClosing(WindowEvent e) {
try {
Scanner sc = new Scanner(ff);
if(sc.hasNext()) {
fw=new FileWriter(ff);
fw.write("");
fw.close();
}
} catch (Exception ex) { }
}
};
f.setVisible(true);
f.addWindowListener(wndCloser);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String args[]) {
new Samp();
}
}
Use Singletone Pattern as shown in the example!
Related
I'm making a small program in Java using the Robot class. The program takes over the mouse. while in the course of debugging if it starts acting in a way that I don't want it's hard to quit the program, since I can't move the mouse over to the terminate button in eclipse, and I can't use hotkeys to hit it because the mouse is constant clicking in another window, giving that window focus instead.
What I'd like to do is just hook up a keylistener so that when I hit q I can quit the program, but the only way I know how to do this involves making a window, and that window needs focus to capture the input. Is there a way to listen for keyboard or mouse input from anywhere, regardless of what has focus?
There is a library that does the hard work for you:
https://github.com/kwhat/jnativehook
This is not a trivial problem and Java doesn't give you a way to do it elegantly. You can use a solution like banjollity suggested but even that won't work all the time if your errant mouse clicks open another fullsized window currently open in your taskbar for example.
The fact is, Java by default gives developers very little control over the OS. This is due to 2 main reasons: security (as citied by java documentation) and the fact that different operating systems handle events completely differently and making one unified model to represent all of these would probably not make a whole lot of sense.
So to answer your question, I imagine what you want is some kind of behaviour for your program where it listens for keypresses globally, not just in your application. Something like this will require that you access the functionality offered by your OS of choice, and to access it in Java you are going to need to do it through a Java Native Interface (JNI) layer.
So what you want to do is:
Implement a program in C that will listen for global keypresses on your OS, if this OS is Windows than look for documentation on windows hooks which is well docuemented by Microsoft and MSDN on the web and other places. If your OS is Linux or Mac OS X then you will need to listen for global keypresses using the X11 development libraries. This can be done on an ubunutu linux distro according to a Howto that I wrote at http://ubuntuforums.org/showthread.php?t=864566
Hook up your C code to your Java code through JNI. This step is actually the easier step. Follow the procedure that I use in my tutorial at http://ubuntuforums.org/showthread.php?t=864566 under both windows and linux as the procedure for hooking up your C code to your Java code will be identical on both OSes.
The important thing to remember is that its much easier to get your JNI code working if you first code and debug your C/C++ code and make sure that it is working. Then integrating it with Java is easy.
Had same problem. In my case, robot just controlled a single Windows App, that was maximized. I placed these lines at top of main loop driving the robot:
Color iconCenterColor = new Color(255,0,0); // if program icon is red
if (iconCenterColor.equals(robot.getPixelColor(10,15)))
throw new IllegalStateException("robot not interacting with the right app.");
To cancel the robot, just alt-tab to another app. Works great for a simple one app driving robot.
Start the program from a command line in a terminal and use Ctrl-C to terminate it.
(As mentioned by #MasterID and shown on JNativeHook's documentation for native keyboard input detection {main GitHub project here}),
This code should be enough to listen to any key without app focus (press and/or release):
>>Remember to add the jnativehook library in your project to be able to use all its utilities.<<
public class yourClass implements NativeKeyListener {//<-- Remember to add the jnativehook library
public void nativeKeyPressed(NativeKeyEvent e) {
System.out.println("Key Pressed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
}
public void nativeKeyReleased(NativeKeyEvent e) {
System.out.println("Key Released: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
}
public void nativeKeyTyped(NativeKeyEvent e) {
System.out.println("Key Typed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
}
public static void main(String args[]){
//Just put this into your main:
try {
GlobalScreen.registerNativeHook();
}
catch (NativeHookException ex) {
System.err.println("There was a problem registering the native hook.");
System.err.println(ex.getMessage());
System.exit(1);
}
GlobalScreen.addNativeKeyListener(new yourClass());
//Remember to include this^ ^- Your class
}
}
For this particular problem, use the nativeKeyPressed method like this:
public void nativeKeyPressed(NativeKeyEvent e) {
System.out.println("Key Pressed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
if (e.getKeyCode() == NativeKeyEvent.VC_Q){
System.exit(1);
}
}
Note that JNativeHook by default shows a lot of stuff in your console that you might not want, to change that, just add this right before the try-catch that you used in the main function as shown (this is also going to turn off warning and error messages, more info here):
//(From here)
Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
logger.setLevel(Level.OFF);
logger.setUseParentHandlers(false);
//(To there-^)
try {
GlobalScreen.registerNativeHook();
}
catch (NativeHookException ex) {
System.err.println("There was a problem registering the native hook.");
System.err.println(ex.getMessage());
System.exit(1);
}
Disclaimer: I know this question was solved years ago, I just hope someone finds this a little easier to find/use.
Have your program open a second window which displays underneath your main window but is maximised, then your errant mouse clicks will all be received by the maximised window, and it can receive your keyboard input.
Here's a pure Java way to do it to solve the problem you've described (not the KeyListener problem... the quit test early when using robot problem):
Throughout your test, compare the mouse position with one that your test has recently set it to. If it doesn't match, quit the test. Note: the important part of this code is the testPosition method. Here's code that I used recently:
public void testSomething() throws Exception {
try {
// snip
// you can even extract this into a method "clickAndTest" or something
robot.mouseMove(x2, y2);
click();
testPosition(x2, y2);
// snip
} catch (ExitEarlyException e) {
// handle early exit
}
}
private static void click() throws InterruptedException {
r.mousePress(InputEvent.BUTTON1_DOWN_MASK);
Thread.sleep(30 + rand.nextInt(50));
r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
Thread.sleep(30 + rand.nextInt(50));
}
private static void testPosition(int x2, int y2) throws ExitEarlyException {
Point p = MouseInfo.getPointerInfo().getLocation();
if(p.x != x2 || p.y != y2) throw new ExitEarlyException();
}
I am making a personal planning program. I utilize XML documents to store user data and login data. This does not utilize a server and all accounts created in the program are localized to the computer it is stored on (in the XML documents.)
In the login XML document, I keep track of the users that are logged in so that one user can't have two windows at the same time to prevent any conflicts with data. This feature runs smoothly and I have no problem with it.
The only thing I want to know is if there is some way to catch an unexpected shut down of a program (such as a task-manager close or a forced close when shutting down the computer) so that I can "log" the user off of the XML document. Otherwise the user would never be able to get back on after an unexpected program close without going into the XML document and deleting the username from the logged in list.
It seems a shutdown hook does not work well with the event queue for a java GUI. much like this thread
I tried setting up my code exactly as shown and the shutdown hook doesn't work for me either. Are there any suggestions for ways of catching an unexpected shutdown without shutdown hooks?
this is my code:
import java.awt.EventQueue;
public class Gui {
private static Controller controller;
public static void main (String[] args) {
controller = new Controller();
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
controller.saveState();
controller.logUserOut();
}
});
EventQueue.invokeLater(
new Runnable() {
public void run() {
controller.start();
}
});
}
}
This is a closer look at my controller that logs the user out
public void logUserOut() {
loginDatabase.logUserOut(username);
saveLoginState();
}
All loginDatabase does is removes that username from the list of logged in users so that user is free to log in again
public void saveLoginState() {
XStream xStream = new XStream(new DomDriver());
OutputStream outFile;
try {
String filePath = "data" + File.separator + "loginDatabase.xml";
outFile = new BufferedOutputStream(new FileOutputStream(filePath));
xStream.toXML(loginDatabase, outFile); // This writes your state to the outputFile;
outFile.close(); //close the writer
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
This is my process for writing on the login state xml file. I suspect it might be too long for a Shutdown Hook even if it were actually being called as I expect.
Any suggestions? I thought for a long time about possibly using simple variables to solve the problem but because I have the program set so that the user can be logged into multiple accounts, the use of variables is impossible.
Also, will the controller object contained in the scope of the shutdown hook be the same controller that is modified in the event queue scope?
The shutdown hook can be a solution here. For details see e.g. this answer: https://stackoverflow.com/a/2541618/2045440
[Off topic] However, if you're at risk that unexpected termination of your application can result in lost of important data, maybe it would be worth to consider the more persistent way of processing this data (autosaving, backup files etc).
I resolved the problem by checking the task manager of the operating system. It allowed me to see if the user the xml document said was logged in actually had a program open. If not then I knew there was a problem. This is a fix for my particular program but it might be a help for others as well.
The link to that thread is here.
I did this program that opens multiple link with default browser:
ArrayList<String> linkList = new ArrayList<>();
for (int i = 0; i < linkList.size(); i++) {
ClassRunnable_OpenLink obj = new ClassRunnable_OpenLink ( linkList.get(i) );
Thread thread = new Thread(obj);
thread.start();
}
private class ClassRunnable_OpenLink implements Runnable {
private URL link;
private String string;
public ClassRunnable_OpenLink (String string) {
this.string = string;
}
private void OpenWithBrowser () {
try {
link = new URL ( string );
edu.stanford.ejalbert.BrowserLauncher launcher = null;
try {
launcher = new BrowserLauncher(null);
} catch ( BrowserLaunchingInitializingException | UnsupportedOperatingSystemException ex) { }
launcher.openURLinBrowser( link );
} catch ( MalformedURLException ex | IOException | URISyntaxException ex) { }
}
#Override
public void run() {
OpenWithBrowser( );
}
}
This works great only if browser (say it's firefox) is already opened, but if it's not, my program only opens the first link and then I have a firefox message that tells me the the browser is still running so I need to close it first.
Same thing with chromium.
So I thought, if I had a way to check when the browser is closed I could use ProcessBuilder to open new firefox process, but I don't know if it's the best way to do this. Besides my java program allows user to select default browser so it could be complicated to use ProcessBuilder in that case.
So do you a have any idea to solve my problem? Maybe I could set a delay between each Thread in this way the system has the time to execute browser process first time, then opening first link and after the browser is running, opening other links, but how about the delay time in seconds? I'm not able to know the time that browser needs to open so it's not a good idea.
I hope you can help me. Thanks
Since java 6 you don't have to use 3rd party implementations to open a webpage with the standard browser. Try
java.awt.Desktop.getDesktop().browse(uri);
Since this maps to the underlying OS functions chances are high multiple calls will work as expected.
A workaround to this (without knowing your exact expectations), could be to do the following:
After first URL open, you could build a delay of for example 10 seconds.
Then in any consecutive URL openings, you can assume that the browser is now surely open, and start opening the next URL's fast after each other.
One note though: Always add some delay to opening URL's (not sure if your framework already does this), because else the browser might crash from the number of URL openings.
UPDATE: You say that Thread.sleep() causes your program to block, this should never happen.
You should always seperate long-during actions from the rest of your program (The (Graphical) User Interface).
So it would be better to write your 'URL opener facility' in another thread.
You can read more about that here: http://docs.oracle.com/javase/tutorial/essential/concurrency/
i have coded a database update software which allows me to deploy a jade mobile agent in order to update the database. In order for it to run, i need to launch it using the AMS gui. I wanted to be able to launch it from gui. I have now done a nice swing gui and i only need to know the code which allows me to launch my mobile agent when the "Update" button is clicked. What is the code? Thanks in advance.
To launch an agent or do whatever related to JADE you need to write YOUR code using JADE libraries and API, irrespective of what Front End you have used (Swing in this case)
One suggestion would be, to keep the modularity, is create another file which does one of many such operations you want, and let your Swing GUI interact (say via sockets) to that file, triggering your operation.
That file, which would act as a server, would listen to the front end and do the respective work. But all commands are to be coded using JADE API. One such code is:
ContainerController cc = Runtime.instance().createAgentContainer(newProfileImpl());
Object arguments[] = new Object[1];``arguments[0]=new Object();
AgentController dummy = cc.createNewAgent("mob2","mobiletrial", arguments);
dummy.start();
This is a method I wrote for launching one agent from another.You'll have to edit it for multiple container use.
void launchAgent( final String AgentName, final String AgentType)
{
log(Level.FINER,"attempting to launch angent name: "+AgentName+" type: "+AgentType);
CreateAgent ca = new CreateAgent();
ca.setAgentName(AgentName);
ca.setClassName(AgentType);
ca.setContainer(new ContainerID(AgentContainer.MAIN_CONTAINER_NAME, null));
Action actExpr = new Action(this.getAMS(), ca);
ACLMessage request = new ACLMessage(ACLMessage.REQUEST);
request.addReceiver(this.getAMS());
request.setOntology(JADEManagementOntology.getInstance().getName());
request.setLanguage(FIPANames.ContentLanguage.FIPA_SL);
request.setProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST);
try {
getContentManager().fillContent(request, actExpr);
addBehaviour(new AchieveREInitiator(this, request) {
protected void handleInform(ACLMessage inform) {
log(Level.INFO,"Agent successfully created name:"+AgentName+" type: "+AgentType);
}
protected void handleFailure(ACLMessage failure) {
log(Level.SEVERE,"Agent launch failed name: "+AgentName+" type: "+AgentType);
}
} );
}
catch (Exception e) {
e.printStackTrace();
}
}
How do you close a java application from the code?
You call System.exit:
System.exit(0);
I believe that by most standards, System.exit() is a not very OOP way of closing applications, I've always been told that the proper way is to return from main. This is somewhat a bit of a pain and requires a good design but I do believe its the "proper" way to exit
If you're terminating a Swing app, I would do an EXIT_ON_CLOSE
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
before System.exit(0). This is better since you can write a Window Listener to make some cleaning operations before actually leaving the app.
That window listener allows you to exit the app from the code:
public void windowClosing(WindowEvent e) {
displayMessage("WindowListener method called: windowClosing.");
//A pause so user can see the message before
//the window actually closes.
ActionListener task = new ActionListener() {
boolean alreadyDisposed = false;
public void actionPerformed(ActionEvent e) {
if (frame.isDisplayable()) {
alreadyDisposed = true;
frame.dispose();
}
}
};
Timer timer = new Timer(500, task); //fire every half second
timer.setInitialDelay(2000); //first delay 2 seconds
timer.setRepeats(false);
timer.start();
}
public void windowClosed(WindowEvent e) {
//This will only be seen on standard output.
displayMessage("WindowListener method called: windowClosed.");
}
If you're running an application, System.exit will work.
System.exit(int);
In an applet, however, you'll have to do something along the lines of applet.getAppletContext().showDocument("landingpage.html"); because of browser permissions. It won't just let you close the browser window.
You use System.exit(int), where a value of 0 means the application closed successfully and any other value typically means something was wrong. Usually you just see a return value of 1 along with a message printed to sysout or syserr if the application did not close successfully.
Everything is fine, application shut down correctly:
System.exit(0)
Something went wrong, application did not shut down correctly:
System.err.println("some meaningful message"); System.exit(1)