I'm trying to use Javas JFileChooser in my LibGDX scene2d project, but as soon as I launch JFileChooser my program freezes.
Here is the code I use to launch file chooser:
private String getPath(){
String path = "";
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int returnVal = fc.showOpenDialog(null);
if (returnVal == JFileChooser.APPROVE_OPTION) {
file = fc.getSelectedFile();
try {
path = file.getAbsolutePath();
} catch (Exception ex) {
System.out.println("problem accessing file" + file.getAbsolutePath() + "\n" + ex.getMessage());
}
} else {
System.out.println("File access cancelled by user.");
}
return path;
}
is it swing and libgdx compability problem or is there something I am missing? Same code works perfectly with nativa java projects.
Except instead of: fc.showOpenDialog(null);
I use: fc.showOpenDialog(button); // button is the JButton that triggers the event.
any idea what am I doing wrong?
EDIT: I don't really mind if it wont work on other platforms than Windows.
BUT if I choose to go with cross platform solution, and use LibGDX's method, do I have to create file chooser class with UI from scratch all by myself?
Ok based on your comments from the answer above I get a sense that what you are trying to do is invoke a swing window INSIDE your LibGDX game window, which is an open GL rendering scene.
Let me stop you right there. The swing toolkit invokes its own rendering engine, because it's not intended for this purpose at all - it's intended for desktop applications. So when you instantiate the dialogue, all sorts of other oracle java stuff gets instantiated along with it, like the Graphics2D class. You can't just add this class to a scene2D stage and expect that it draws. They don't implement the same interfaces or inherit from the same base classes. The draw(Graphics2D graphics) method that your JFileChooser implements is not the same as whatever draw(SomeClass foo) method that your libGDX classes implement.
So if you want to make a file chooser window, you need to start looking at the libGDX widget libraries. There might be something that someone has put together already, but my approach for my next libGDX project is going to be to extend these classes for my own UI libraries. I don't know what your project is, or what your timeline is like, but it's certainly a better approach then trying to adapt the swing toolkit to render in an OpenGL rendering scene.
edit
After some quick reading, I'm going to go one further and hazard a guess that the way the swing toolkit gets rendered is entirely dependent on the implementation of the JVM for a specific platform. Now this is where my CS knowledge starts to be a little limited, but I would hazard another guess that this is way way different than the LWJGL implementation of OpenGl by way of using Java wrappers for C libraries.
Personally I dislike the existing FileChooser UIs inside LibGDX. So I created a solution which works using the JFileChooser. Here is some quick and dirty code:
new Thread(new Runnable() {
#Override
public void run() {
JFileChooser chooser = new JFileChooser();
JFrame f = new JFrame();
f.setVisible(true);
f.toFront();
f.setVisible(false);
int res = chooser.showSaveDialog(f);
f.dispose();
if (res == JFileChooser.APPROVE_OPTION) {
//Do some stuff
}
}
}).start();
This will open the FileChooser in front of the LibGDX window without blocking the main Thread. Just tested this on Windows 7, 8, 10 and it only works in window mode ofc.
Coming late to the party but if the point of the question is to invoke a "native" ie. non-gdx file chooser from a libgdx project I made a library to do so here: https://github.com/spookygames/gdx-nativefilechooser.
Example from the readme:
// Configure
NativeFileChooserConfiguration conf = new NativeFileChooserConfiguration();
// Starting from user's dir
conf.directory = Gdx.files.absolute(System.getProperty("user.home"));
// Filter out all files which do not have the .ogg extension and are not of an audio MIME type - belt and braces
conf.mimeFilter = "audio/*";
conf.nameFilter = new FilenameFilter() {
#Override
public boolean accept(File dir, String name) {
return name.endsWith("ogg");
}
};
// Add a nice title
conf.title = "Choose audio file";
fileChooser.chooseFile(conf, new NativeFileChooserCallback() {
#Override
public void onFileChosen(FileHandle file) {
// Do stuff with file, yay!
}
#Override
public void onCancellation() {
// Warn user how rude it can be to cancel developer's effort
}
#Override
public void onError(Exception exception) {
// Handle error (hint: use exception type)
}
});
On the desktop, this example will currently launch an AWT FileDialog (not exactly what is asked) yet a Swing version is currently on the master branch and should be incorporated to the next version of the lib.
Related
I'm using Java Swing (GUI) and I want to add a button to my project for opening files.
I don't like the JFileChooser since it opens a small window for browsing through the files of the directories. Can I use something else instead of the JFileChooser under Java Swing?
I've tried to use elements of SWT but it didn't work, meaning is the use of the button object and then use it inside the JFrame, but that failed, so I guess SWT and Swing don't mix together?
Here is the example of Java Swing with JFileChooser and I'm looking for something like this to put in my JFrame.
JFileChooser with the native PLAF seems to fulfill the stated requirement.
import javax.swing.JFileChooser;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class NativeFileChooser {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
} catch(Exception e) {
e.printStackTrace();
}
JFileChooser jfc = new JFileChooser();
jfc.showOpenDialog(null);
}
});
}
}
Still not quite to your liking? Then you might start with this one & change it to need:
..so I guess SWT and Swing don't mix together?
It is generally not a good idea to mix Swing/AWT/SWT components in the same top-level container. It is not a problem to open an AWT FileDialog over a Swing based JFrame since they are both top-level containers. I am pretty sure the same would apply to Swing/SWT or AWT/SWT.
If you do not need the flexibility of the JFileChooser, you can opt for the FileDialog which uses the native OS file dialog. See also Code ranch topic and this answer on SO
I have a kiosk GUI application I'm working on and it requires me to block users from being able to Alt-Tab out of the fullscreen window. I posted a question about this a while back and a member helped me with some code, which worked perfectly under a Windows environment.
Here it is:
public class TabStopper implements Runnable {
private boolean isWorking = false;
private MenuFrame parent;
public TabStopper(MenuFrame parent) {
this.parent = parent;
new Thread(this, "TabStopper").start();
}
public void run() {
this.isWorking = true;
Robot robot;
try {
robot = new Robot();
while (isWorking) {
robot.keyRelease(KeyEvent.VK_ALT);
robot.keyRelease(KeyEvent.VK_TAB);
parent.requestFocus();
Thread.sleep(10);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void stop() {
this.isWorking = false;
}
public boolean isWorking() {
return this.isWorking;
}
}
However, I need this to be able to work in Linux as well. I made an executable jar from the source and brought it into Linux. Everything worked except the Alt and Tab keys were being constantly pressed. The buttons on my GUI were constantly being cycled and I was able to open a terminal (I set a backdoor in the application during testing in case something like this happens) which wouldn't let me type anything because Tab lists all the files in the current directory.
Could anyone tell me if there would be a fix that would work in both Linux and Windows environments. However, if I had to choose, I would go for Linux.
EDIT: I can also confirm that the Alt key is being "pressed". What's with this weird behaviour?
Forget grabbing Alt+Tab with hacks like this. It is a bad hack and it is error-prone. There are also so many other hotkey combinations.
For linux you have two options:
Use a minimal window manager or no window manager at all. For example, with fluxbox you can remove all key bindings alltogether and you can also make your application maximise by default, etc. You can empty the desktop menus such that the user gains no control even when your application crashes. This is a clean solution that really solves your problem instead of some parts of it. There are many ways to fiddle with the system other than Alt+Tab.
Grab input controls completely. This is what games do. For example libSDL does it for you and there are java wrappers for the functionality as well. This should also work as expected, except you use a window manager that does not allow input control grabbing per default (I don't know of any).
I ran into an issue with JFileChooser and wanted to see if there is a workaround.
If the JFileChooser is created and the setFileSelectionMode is FILES_AND_DIRECTORIES, when a user clicks a shortcut button on the left (in XP) such as Desktop or My Documents or drop down to Desktop, the field is not placed in the File Name JTextPane. And when clicking the "Select/Accept" button, nothing happens (because isDirectorySelected() returns false for some reason).
Overriding the approveSeletion does not work because the Event Handler function in BasicFileChooser does not call it.
How would I make it so the Desktop can be selected without having to navigate to it manually, but by clicking the shortcut on the left?
Thanks
In Windows, the desktop is not backed by any file in the file system - it's a shell namespace. So there really isn't anything that JFileChooser could return to you. Yes, I know that there is a folder that contains the desktop for the user - but remember that the desktop actually displays as a composite of the user's desktop and the All Users desktop folder - plus other things that are added by the shell but not part of any folder (like the trash bin). So returning a File object that represents the 'desktop' is pretty much a non-starter.
Long and short: Ask yourself why you need to do this - chances are that you are going to wind up deep into native code territory, dealing with namespace PIDLs and all sorts of nastiness that you may not want to get into (for the life of me, I cannot understand why M$ had to make this stuff so amazingly difficult to use)...
Here's an intro to Windows shell namespaces so you'll have a feel for what's involved:
http://msdn.microsoft.com/en-us/library/cc144090%28v=vs.85%29.aspx
Found the following code in the BasicFileChooserUI:
if (fc.getFileSelectionMode() == JFileChooser.FILES_AND_DIRECTORIES
&& fc.getFileSystemView().isFileSystem(dir)) {
setFileName(dir.getAbsolutePath());
}
So it looks like "special folders" are purposely ignored. The code is in a private method so it would be hard to create you own UI.
As a hack you might be able to add a PropertyChangeListener to the file chooser:
public void propertyChange(final PropertyChangeEvent e)
{
String prop = e.getPropertyName();
if (JFileChooser.DIRECTORY_CHANGED_PROPERTY.equals(prop))
{
JFileChooser fileChooser = (JFileChooser)e.getSource();
File currentDirectory = (File)e.getNewValue();
String directory = currentDirectory.toString();
if (directory.endsWith("Desktop")
|| directory.endsWith("My Documents"))
{
File selectedFile = fileChooser.getSelectedFile();
if (selectedFile == null || ! selectedFile.equals(currentDirectory))
{
fileChooser.removePropertyChangeListener( this );
fileChooser.setSelectedFile( currentDirectory );
fileChooser.addPropertyChangeListener( this );
}
}
}
}
I have a Java Swing application which shows a list of the files/Folders that have been uploaded to the server. I have a requirement to download selected file(s)/folder(s) to native file system using Drag and Drop . I have searched links but almost every link describes the Drag and Drop within a Java Swing application. My requirement is to Drag the file from the Java Swing application and Drop it to the native file system.
I need help to know how I can get the location where user has dropped the selected file(s)/folder(s) to the native file system.
For example, let's suppose the user has dragged the file and dropped directly to the C:\Back_Up folder by restore the window of Java Application. How can I identify the location that user has dropped the file to, i.e. C:\Back_Up?
AFAIK, it's not possible to get the information, where a dragged object has been dropped. Guess, your idea was to know the drop point and copy the file to that position in a second step.
But I think, it doesn't work this way and, even worse, the whole think could be pretty OS dependant. I bet, you have to put the entire file on the transfer. I know that it's possible with SWT, but SWT ships with some native libraries...
Here's at least one link that shows an example for the other way round: Drag and drop of a group of files into a tree
Thanks Andreas..
We have a JAVA component as a Table from which we drag the file and dropped to native file system. We have code like
A> Component is JXTree. We have set following property to support Drag And Drop.
Component.setDropMode(DropMode.INSERT);
Component.setDragEnabled(true);
DragSource ds = DragSource.getDefaultDragSource();
DragGestureRecognizer dgr = ds.createDefaultDragGestureRecognizer( Component,
DnDConstants.ACTION_MOVE, new FileDragGestureListener());
B> We have written a class which implements Drag Gesture Listener.
public class FileDragGestureListener extends DragSourceAdapter implements DragGestureListener {
public void dragGestureRecognized(DragGestureEvent dge) {
We get selected row from table.
Download the selected File to Native file System's TEMP directory.
FileSystemView fsv = FileSystemView.getFileSystemView();
Icon icn = fsv.getSystemIcon(File);
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension dim = tk.getBestCursorSize(icn.getIconWidth(), icn.getIconHeight());
BufferedImage buff = new BufferedImage(dim.width, dim.height,
BufferedImage.TYPE_INT_ARGB);
if (DragSource.isDragImageSupported()) {
evt.startDrag(DragSource.DefaultCopyDrop, buff, new Point(0, 0),
new TextFileTransferable(File),
this);
} else {
cursor = tk.createCustomCursor(buff, new Point(0, 0), "sString");
evt.startDrag(cursor, null, new Point(0, 0),
new TextFileTransferable(File),
this);
}
}
class TextFileTransferable implements Transferable {
File temp;
public TextFileTransferable(File temp) throws IOException {
this.temp = temp;
}
public Object getTransferData(DataFlavor flavor) {
List list = new ArrayList();
list.add(temp);
return list;
}
public DataFlavor[] getTransferDataFlavors() {
DataFlavor[] df = new DataFlavor[1];
df[0] = DataFlavor.javaFileListFlavor;
return df;
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
if (flavor == DataFlavor.javaFileListFlavor) {
return true;
}
return false;
}
}
So this is how we can able to download the file up to %TEMP% then we can not move that file to a location where is has been dropped.
Please suggest where i am wrong OR what best approach to implement this Drag And Drop.
Thanks
I believe Java Desktop API could accomplish this. Not sure about details, though...
Maybe if you knew in general what directories people would be dropping into, your application could create file objects pointed at those directories and then use the Observer design pattern to tell your application when something got dropped into them (by polling the contents, maybe) although if other programs/people dropped things into those directories you'd get notified of that too, but then you could compare the time that notification came in with the time you could know that you did some dropping. This would reduce it to the arguably low probability (yet uncomfortably still possible) case of someone else dropping into directory A at almost the exact same time you dropped into directory B.
Good luck!
Some clue can be obtained from JDesktop Integration Components: https://jdic.dev.java.net/
How do I change the JFileChooser behavior from double-click selection to single-click selection mode?
I'm developing an application to run with either a single-click interface (nothing requires a double-click, just like the KDE interface mode) or a double-click interface (the default Windows interface mode or the regular GNOME interface mode). I want the Java application to behave just like the rest of the system to respect the user current configuration and environment.
The ideal solution should be to set up a configuration value somewhere in the JFileChooser class to have it work either under single-click ordouble-click mode.
Since it seems there is no such a configuration, here is an approximate solution based on Richie_W's idea. I had to extend it a bit in order to allow the user to navigate in many directories and also to avoid reentrant events that get fired when setting the selection. However, as Oscar pointed out, it is not possible to navigate using the keyboard (it always chooses whatever is under focus). If you don't use the keyboard, it works.
JFileChooser _fileChooser=new JFileChooser();
if (ConfigurationManager.isSingleClickDesired()) {
//We will be interested in files only, but we need to allow it to choose both
_fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
_fileChooser.addPropertyChangeListener(new PropertyChangeListener() {
//To prevent reentry
private boolean handlingEvent=false;
public void propertyChange(PropertyChangeEvent e) {
//Prevent reentry
if (handlingEvent)
return;
else
//Mark it as handling the event
handlingEvent=true;
String propertyName = e.getPropertyName();
//We are interested in both event types
if(propertyName.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY) ||
propertyName.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)){
File selectedFile = (File) e.getNewValue();
if (selectedFile!=null) {
if (selectedFile.isDirectory()) {
//Allow the user to navigate directories with single click
_fileChooser.setCurrentDirectory(selectedFile);
} else {
_fileChooser.setSelectedFile(selectedFile);
if (_fileChooser.getSelectedFile()!=null)
//Accept it
_fileChooser.approveSelection();
}
}
}
//Allow new events to be processed now
handlingEvent=false;
}
});
}
Ps->Sorry for not great looking code format, but StackoverFlow has broken Firefox and Iceweasel code format support under KDE and Gnome.