I've created a JFram开发者_C百科e with 3 Jbuttons. I'd like the button to launch different .exe file located in the same folder. Is this possible? If yes, what should i write for the actionListener? On the other hand, instead of launching an exe file, is it possible to launch a main class using a JButton? If yes, what should i write for the actionListener?
Note: The .exe file is created from a java main program.
JButton button1 = new JButton("Program1"); //The JButton name.
frame.add(button1); //Add the button to the JFrame.
button1.addActionListener().... // how to launch the .exe file
Thanks in advance
Runtime.getRuntime().exec( ... );
or use the ProcessBuilder class.
You should be able to find example on the web that use these classes.
Edit: For example to start the Notepad exe in Windows you could do:
Process process = Runtime.getRuntime().exec( "cmd.exe /C start notepad" );
If you want to execute a class then you need to invoke the JVM the same way you would invoke it from the command line.
You may be interested looking into executing an external process.
This would require either Runtime.getRuntime().exec or the newer ProcessBuilder
I think that you would use Runtime.exec() or a ProcessBuilder similar to how you'd call an exe program if you weren't calling it from a GUI. Some things to take care about are that you'd likely want to call the Runtime.exec() on a background thread off of the Swing main thread, the EDT, such as provided by a SwingWorker object. Otherwise your GUI could freeze while the exe program takes over the Swing thread. Also you'll also want to head all of the warnings about calling Runtime.exec() shown in this great article, When Runtime.exec() won't, possibly one of the best articles written on the subject --highly recommended!
Question: What do you mean by this statement as it isn't clear to me?:
Note: The program.exe file is created from a java main program.
Here is an alternative answer without creating a new process through Runtime.getRuntime().exec(...) - and you can maintain your System.in/out channels, too. However, if you are new to the world of java programming and trying to learn the ropes, I would suggest following camickr's advice and not messing with the ClassLoader as described below.
I am assuming the class you need to run is self contained (uses no inner classes) and not already in your classpath or jarfile so you could just create an instance and call its main(). If there are multiple class files involved, just repeat the method for loading them.
So, in the ActionListener that your JButton addActionListener()-ed to ...
public void actionPerformed (ActionEvent e) {
String classNameToRun = e.getActionCommand(); // Or however you want to get it
try {
new MyClassLoader().getInstance(classNameToRun).main (null);
} catch (ClassNotFoundException ce) {
JOptionPane.showMessageDialog (null, "Sorry, Cannot load class "+classNameToRun,
"Your title", JOptionPane.ERROR_MESSAGE);
}}
You will need a new class MyClassLoader already in your classpath. Here is a pseudocode:
import java.io.*;
import java.security.*;
public class MyClassLoader extends ClassLoader {
protected String classDirectory = "dirOfClassFiles" + File.separator,
packageName = "packageNameOfClass.";
/**
* Given a classname, get contents of the class file and return it as a byte array.
*/
private byte[] getBytes (String className) throws IOException {
byte[] classBytes = null;
File file = new File (classDirectory + className + ".class");
// Find out length of the file and assign memory
// Deal with FileNotFoundException if it is not there
long len = file.length();
classBytes = new byte[(int) len];
// Open the file
FileInputStream fin = new FileInputStream (file);
// Read it into the array; if we don't get all, there's an error.
// System.out.println ("Reading " + len + " bytes");
int bCount = fin.read (classBytes);
if (bCount != len)
throw new IOException ("Found "+bCount+" bytes, expecting "+len );
// Don't forget to close the file!
fin.close();
// And finally return the file contents as an array
return classBytes;
}
public Class loadClass (String className, boolean resolve)
throws IOException, ClassNotFoundException,
IllegalAccessException, InstantiationException {
Class myClass = findLoadedClass (packageName + className);
if (myClass != null)
return myClass;
byte[] rawBytes = getBytes (className);
myClass = defineClass (packageName + className,
rawBytes, 0, rawBytes.length);
// System.out.println ("Defined class " +packageName + className);
if (myClass == null)
return myClass;
if (resolve)
resolveClass (myClass);
return myClass;
}
public Object getInstance (String className) throws ClassNotFoundException {
try {
return loadClass (className, true).newInstance();
} catch (InstantiationException inExp) { inExp.printStackTrace();
} catch (IllegalAccessException ilExp) { ilExp.printStackTrace();
} catch (IOException ioExp) { ioExp.printStackTrace();
}
return null;
}
}
Notes: This works well when the class you are trying to load is residing on your local machine and you are running java from the command line. I was never successful trying to get an applet to download a classfile from some servlet and load it - security will not allow that. In that case, the workaround is just to run another applet in another window, but that's another thread. The above classloading solves the problem of having to jar up every single classfile that you might be needing - just to start the GUI. Good luck, - M.S.
精彩评论