I'm currently trying to use FileChooserBuilder from Netbeans Platform API. Following code is complete netbeans module action. When run, it doesn't show at the center of window/screen but somewhere in bottom left corner of the screen. Is there any possibility to make this dialog display in the middle of the screen?
public final class LoadProjectAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
File home = new File(
System.getProperty("user.home")
+ File.separator + "lib");
FileChooserBuilder fileChooserBuilder = new FileChooserBuilder(
LoadProjectAction.class);
fileChooserBuilder.setTitle("Load project");
fileChooserBuilder.setDefaultWorkingDirectory(home);
fileChooserBuilder.setApproveText("Load");
fileChooserBuilder.setDirectoriesOnly(true);
File directory = fileChooserBuilder.showOpenDialog();
if (directory != null) {
return; // nothing to do
}
// do some processing here
}
}
Thanks for your ideas.
Found the solution:
You have to obtain JFileChooser instance and set right parent component in it's showOpenDialog method (it's then positioned relatively to application's main window). But as NetBeans tries to work quite safely with the threads - it allows only one thread access the components, so the EventQueue.invokeLater has to be used.
public final class LoadProjectAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
// output window
InputOutput io = IOProvider.getDefault().getIO("File search", true);
io.select();
// start in user home directory
File initialDirectory = new File(
System.getProperty("user.home")
+ File.separator + "lib");
FileChooserBuilder fileChooserBuilder = new FileChooserBuilder(
"LoadProjectAction");
fileChooserBuilder.setTitle("Load project");
fileChooserBuilder.setDefaultWorkingDirectory(initialDirectory);
fileChooserBuilder.setApproveText("Load");
fileChooserBuilder.setDirectoriesOnly(true);
JFileChooser jfc = fileChooserBuilder.createFileChooser();
int value = jfc.showOpenDialog(WindowManager.getDefault().getMainWindow());
if (value != JFileChooser.APPROVE_OPTION) {
return; // nothing to do
}
// process selection
}
});
}
}
Related
Synopsis
I am developing a Java Swing project, and I have been debugging successfully within IntelliJ IDEA by running the main method directly. After closing the frame, the debugger exits normally.
However, after adding a JFileChooser dialog to the project, the debugger does not exit normally. I have to click the stop button every time now, which causes the JVM to exit with a non-zero status.
Minimal, Reproducible Example
This is the section of code that is causing the problem; it is an ActionListener that I am adding to two buttons which launch the JFileChooser:
/**
* Generic action listener that is used for both file selection dialog buttons
*/
private final ActionListener fileSelectionButtonActionListener = new ActionListener()
{
#Override
public void actionPerformed(final ActionEvent event)
{
final String target = ((JButton) event.getSource()).getName();
assert (target.equals("file") || target.equals("directory"));
JFileChooser fileChooser = new JFileChooser(new File(".").getAbsoluteFile());
fileChooser.setDialogType(JFileChooser.OPEN_DIALOG);
if(target.equals("directory")) {
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
}
final int result = fileChooser.showOpenDialog(new JFrame());
if(result == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile();
if(target.equals("file")) {
fileTextField.setText(selectedFile.getAbsolutePath());
} else {
directoryTextField.setText(selectedFile.getAbsolutePath());
}
}
}
};
Debugging Steps
I have tried moving the JFrame creation from the parameter of the showOpenDialog method to a variable declaration and added frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); but that did not fix the issue. It's almost like the frame is still hanging around in memory, and that's why the JVM won't close.
Question
How can I make the JVM close appropriately while using JFileChooser?
The problem is, indeed, that the JFrame is still in memory, causing the JVM to hang. However, the solution is a JFrame is not needed.
Instead of setting a new JFrame() as the parent of the dialog, set the parent to the dialog window itself:
/**
* Generic action listener that is used for both file selection dialog buttons
*/
private final ActionListener fileSelectionButtonActionListener = new ActionListener()
{
#Override
public void actionPerformed(final ActionEvent event)
{
final String target = ((JButton) event.getSource()).getName();
assert (target.equals("file") || target.equals("directory"));
JFileChooser fileChooser = new JFileChooser(new File(".").getAbsoluteFile());
fileChooser.setDialogType(JFileChooser.OPEN_DIALOG);
if(target.equals("directory")) {
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
}
--> final int result = fileChooser.showOpenDialog(fileChooser); <--
if(result == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile();
if(target.equals("file")) {
fileTextField.setText(selectedFile.getAbsolutePath());
} else {
directoryTextField.setText(selectedFile.getAbsolutePath());
}
}
}
};
Change the line where you get the result: final int result = fileChooser.showOpenDialog(fileChooser);. Doing that fixes the issue.
I have to write a program that essentially makes a report card, but it cannot do so until until it reads in a file either through command line arguments or by the user picking one from their browser, which means I need to use JFileChooser. I have the GUI set-up for the JFileChooser but that's all I can figure out. The dialog window opens when I click open but after picking a file the window I created (GUI) does not close. Also the program runs through all of my other methods before a file is even loaded causing other problems. I tried using a do-while loop but it just runs through the loop before I can ever open a file.
import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MP1 extends JFrame implements java.awt.event.ActionListener{
static StudentAssignments geen165 = new StudentAssignments();
static boolean fileReady = false;
/**
* #param args the command line arguments
*/
public static void main(String [] args) {
do{
if(args.length == 0 || args[0].isEmpty()){//reads in input from file
//select
MP1 doIt = new MP1();
doIt.setVisible(true);
}
else{
geen165.readGradeFile(args[0]);//reads in input file from command
//argument
}
}while(!fileReady);
//test methods
JOptionPane.showMessageDialog(null, geen165.getGradeReport());
geen165.addAssignments(3, 98, 100);
geen165.saveGradeFile("NewGrades.txt");
JOptionPane.showMessageDialog(null, geen165.getGradeReport());
geen165.removeAssignment(0, 2);
JOptionPane.showMessageDialog(null, geen165.getGradeReport());
}
//JFile Chooser GUI
public MP1(){
prepareGui();
}
private void prepareGui(){
setSize(500,500);
Container window = getContentPane();
window.setLayout(new FlowLayout());
JButton open = new JButton("Open");
JButton cancel = new JButton("Cancel");
JLabel status = new JLabel("You've selected: ");
//sets file when open is pressed
open.addActionListener((ActionEvent e) -> {
JFileChooser chooser = new JFileChooser();
int returnVal = chooser.showOpenDialog(window);
if(returnVal == JFileChooser.APPROVE_OPTION){
File fileName = chooser.getSelectedFile();
status.setText("You've selected: " + fileName.getName());
geen165.readGradeFile(fileName.getName());
fileReady=true;
}
});
//exits program if cancel is pressed
cancel.addActionListener((ActionEvent e) -> {
System.exit(1);
});
window.add(open);
window.add(cancel);
window.add(status);
setDefaultCloseOperation(HIDE_ON_CLOSE);
}
#Override
public void actionPerformed(ActionEvent e) {
throw new UnsupportedOperationException("Not supported yet."); //To change
//body of generated methods, choose Tools | Templates.
}
}
Any suggestions?
You are complicating a simple issue. There is no need for you to build a window and everything only to use JFileChooser. A simple solution that works is
import javax.swing.*;
public class MP1 extends JFrame {
public static void main(String[] args) {
String myFile="";
if (args.length == 0 || args[0].isEmpty()) {//reads in input from file
//select
JFileChooser chooser = new JFileChooser();
int returnVal = chooser.showOpenDialog(null);
if (returnVal!=JOptionPane.CANCEL_OPTION) {
myFile = chooser.getSelectedFile().getPath();
} else {
JOptionPane.showMessageDialog(null, "Thanks for playing!");
System.exit(0);
}
} else {
myFile = args[0];
}
JOptionPane.showMessageDialog(null, "You have selected "+myFile+". Go play!");
}
}
Notice that I check whether there is a parameter. If not, I immediately go and execute the JFileChooser. There is no need for overhead.
I removed all your class activity, because I do not have the files.
BTW, I have not tested it, but I believe that your problem comes from your new frame not being modal. Hence, the boolean variable is changed before you can do anything. But that is just an idea.
I think you need to know how JFileChooser works.
JFileChooser fc = new JFileChooser();
int optionSelected = fc.showOpenDialog(YourClassName.this);
if (optionSelected == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
... // Do what you want with the file
}
JFileChooser
In my code I am asking the user to choose an image. My JFileChooser window worked fine. Then I restarted my computer and now whenever that window comes up it is not clickable in any way. I can't open a file, I can't cancel, I can't chooser folders or files. Here is the necessary code.
JFileChooser jfc = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter("Image Files", "jpg", "png", "jpeg");
jfc.setFileFilter(filter);
jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
jfc.setVisible(true);
int ret = jfc.showOpenDialog(null);
if (ret == JFileChooser.CANCEL_OPTION) {
return;
}
File file_1 = jfc.getSelectedFile();
file_path = file_1.getAbsolutePath();
Breakpoints show that the program never leaves this line:
int ret = jfc.showOpenDialog(null);
As I said the same exact code was working fine moments ago. Not sure what is causing this situation.
In my main program I click "Add image" which calls the previously mentioned code. I try clicking on the window "Open" opened by "showOpenDialog" but it doesn't matter where I click. Nothing changes. The main program resumes once I close the "Open" window from my task manager. Also in my task manager "Open" window doesn't say not responding, it looks fine and closes at an instance and furthermore inside the text field the text cursor is blinking.
EDIT: Same exact code works on a separate project that consists of only this code.
EDIT 2: Some additional codes.
Here is the complete load_file() function.
public class Image {
private static String file_path;
private static ImageFrame frame;
public static boolean isImgLoaded = false;
public static void load_file(){
JFileChooser jfc = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter("Image Files", "jpg", "png", "jpeg");
jfc.setFileFilter(filter);
jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
jfc.setVisible(true);
int ret = jfc.showOpenDialog(null);
if (ret == JFileChooser.CANCEL_OPTION) {
return;
}
File file_1 = jfc.getSelectedFile();
file_path = file_1.getAbsolutePath();
ImageFrame frm = new ImageFrame();
frm.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frm.setVisible(true);
frame = frm;
isImgLoaded = frame.get_component().is_img_loaded();
frame.addWindowListener(new java.awt.event.WindowAdapter() {
#Override
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
closeFrame();
}
});
}
Here is the button code that calls the function when pressed. shlErgo is my shell that the UI is built on.
Button btnAddImage = new Button(shlErgo, SWT.NONE);
btnAddImage.setBounds(230, 10, 75, 25);
btnAddImage.setText("Add Image");
btnAddImage.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
if (!Image.isImgLoaded){
Image.load_file();
}
else{
Error.translate(2);
}
}
});
This question already has answers here:
open resource with relative path in Java
(13 answers)
Closed 9 years ago.
Using the code example provided in the accepted answer of Playing audio using JavaFX MediaPlayer in a normal Java application? I am able to play mp3s from a directory on my computer when I pass a absolute path as a String to a File contructor.
My issue is that I am trying to access the mp3 files from a directory that I have imported into eclipse. I want to do this so that I can export my project as a .jar and have other people be able to use it. When I pass the relative path String ( /ProjectName/Mp3Directory ) and run it I get
Cannot find video source directory: /ProjectName/Mp3Directory
I have also tried to create a URL from the relative path, then converting that to a URI and passing it to the File constructor, but I could not get that to work either.
What can I do to get the following code to find my imported directory containing the mp3s (Mp3Directory) and sucessfully run?
package application;
import java.io.*;
import java.net.URL;
import java.util.*;
import javafx.application.Platform;
import javafx.beans.value.*;
import javafx.embed.swing.JFXPanel;
import javafx.event.*;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.media.*;
import javafx.util.Duration;
import javax.swing.*;
/** Example of playing all mp3 audio files in a given directory
* using a JavaFX MediaView launched from Swing
*/
public class JavaFXVideoPlayerLaunchedFromSwing {
private static void initAndShowGUI() {
// This method is invoked on Swing thread
JFrame frame = new JFrame("FX");
final JFXPanel fxPanel = new JFXPanel();
frame.add(fxPanel);
frame.setBounds(200, 100, 800, 250);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
Platform.runLater(new Runnable() {
#Override public void run() {
initFX(fxPanel);
}
});
}
private static void initFX(JFXPanel fxPanel) {
// This method is invoked on JavaFX thread
Scene scene = new SceneGenerator().createScene();
fxPanel.setScene(scene);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override public void run() {
initAndShowGUI();
}
});
}
}
class SceneGenerator {
final Label currentlyPlaying = new Label();
final ProgressBar progress = new ProgressBar();
private ChangeListener<Duration> progressChangeListener;
public Scene createScene() {
final StackPane layout = new StackPane();
// determine the source directory for the playlist
final File dir = new File("/ProjectName/mp3Directory");
if (!dir.exists() || !dir.isDirectory()) {
System.out.println("Cannot find video source directory: " + dir);
Platform.exit();
return null;
}
// create some media players.
final List<MediaPlayer> players = new ArrayList<MediaPlayer>();
for (String file : dir.list(new FilenameFilter() {
#Override public boolean accept(File dir, String name) {
return name.endsWith(".mp3");
}
})) players.add(createPlayer("file:///" + (dir + "\\" + file).replace("\\", "/").replaceAll(" ", "%20")));
if (players.isEmpty()) {
System.out.println("No audio found in " + dir);
Platform.exit();
return null;
}
// create a view to show the mediaplayers.
final MediaView mediaView = new MediaView(players.get(0));
final Button skip = new Button("Skip");
final Button play = new Button("Pause");
// play each audio file in turn.
for (int i = 0; i < players.size(); i++) {
final MediaPlayer player = players.get(i);
final MediaPlayer nextPlayer = players.get((i + 1) % players.size());
player.setOnEndOfMedia(new Runnable() {
#Override public void run() {
player.currentTimeProperty().removeListener(progressChangeListener);
mediaView.setMediaPlayer(nextPlayer);
nextPlayer.play();
}
});
}
// allow the user to skip a track.
skip.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent actionEvent) {
final MediaPlayer curPlayer = mediaView.getMediaPlayer();
MediaPlayer nextPlayer = players.get((players.indexOf(curPlayer) + 1) % players.size());
mediaView.setMediaPlayer(nextPlayer);
curPlayer.currentTimeProperty().removeListener(progressChangeListener);
curPlayer.stop();
nextPlayer.play();
}
});
// allow the user to play or pause a track.
play.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent actionEvent) {
if ("Pause".equals(play.getText())) {
mediaView.getMediaPlayer().pause();
play.setText("Play");
} else {
mediaView.getMediaPlayer().play();
play.setText("Pause");
}
}
});
// display the name of the currently playing track.
mediaView.mediaPlayerProperty().addListener(new ChangeListener<MediaPlayer>() {
#Override public void changed(ObservableValue<? extends MediaPlayer> observableValue, MediaPlayer oldPlayer, MediaPlayer newPlayer) {
setCurrentlyPlaying(newPlayer);
}
});
// start playing the first track.
mediaView.setMediaPlayer(players.get(0));
mediaView.getMediaPlayer().play();
setCurrentlyPlaying(mediaView.getMediaPlayer());
// silly invisible button used as a template to get the actual preferred size of the Pause button.
Button invisiblePause = new Button("Pause");
invisiblePause.setVisible(false);
play.prefHeightProperty().bind(invisiblePause.heightProperty());
play.prefWidthProperty().bind(invisiblePause.widthProperty());
// layout the scene.
layout.setStyle("-fx-background-color: cornsilk; -fx-font-size: 20; -fx-padding: 20; -fx-alignment: center;");
layout.getChildren().addAll(
invisiblePause,
VBoxBuilder.create().spacing(10).alignment(Pos.CENTER).children(
currentlyPlaying,
mediaView,
HBoxBuilder.create().spacing(10).alignment(Pos.CENTER).children(skip, play, progress).build()
).build()
);
progress.setMaxWidth(Double.MAX_VALUE);
HBox.setHgrow(progress, Priority.ALWAYS);
return new Scene(layout, 800, 600);
}
/** sets the currently playing label to the label of the new media player and updates the progress monitor. */
private void setCurrentlyPlaying(final MediaPlayer newPlayer) {
progress.setProgress(0);
progressChangeListener = new ChangeListener<Duration>() {
#Override public void changed(ObservableValue<? extends Duration> observableValue, Duration oldValue, Duration newValue) {
progress.setProgress(1.0 * newPlayer.getCurrentTime().toMillis() / newPlayer.getTotalDuration().toMillis());
}
};
newPlayer.currentTimeProperty().addListener(progressChangeListener);
String source = newPlayer.getMedia().getSource();
source = source.substring(0, source.length() - ".mp4".length());
source = source.substring(source.lastIndexOf("/") + 1).replaceAll("%20", " ");
currentlyPlaying.setText("Now Playing: " + source);
}
/** #return a MediaPlayer for the given source which will report any errors it encounters */
private MediaPlayer createPlayer(String aMediaSrc) {
System.out.println("Creating player for: " + aMediaSrc);
final MediaPlayer player = new MediaPlayer(new Media(aMediaSrc));
player.setOnError(new Runnable() {
#Override public void run() {
System.out.println("Media error occurred: " + player.getError());
}
});
return player;
}
}
Maybe try allowing the user to select the folder that contains the mp3s in it with something like this inside your createScene method:
final JFileChooser fc = new JFileChooser();
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
// final File dir = new File("/ProjectName/mp3Directory");
File dir = null;
int selection = fc.showDialog(null, "Open");
if(selection == JFileChooser.APPROVE_OPTION) {
dir = fc.getSelectedFile();
} else {
System.out.print("Please select a directory to continue");
System.exit(0);
}
Relative paths shouldn't start with a slash. "/ProjectName" equates to a folder named ProjectName in the root of the current drive. So you could try "ProjectName/mp3Directory"... Although for something that will work in both Eclipse and from a runnable JAR you should get the folder in which the application is running and make a relative path from there (see the answer to Get the application's path for more information):
URL url = getClass().getResource("").toURI().toURL();
String applicationDir = url.getPath();
if(url.getProtocol().equals("jar")) {
appDir = new File(((JarURLConnection)url.openConnection()).getJarFileURL().getFile()).().getFile()).getParent();
}
String mp3Dir = appDir + "ProjectName" + System.getProperty("file.separator") + "mp3Directory";
Even though it wasn't really a direct answer to your question, I think that for an all-purpose application where you don't want to force users to put their MP3 files in a particular folder, axiopisty's suggestion to use a file chooser (in conjunction with saving the choice using a settings file or the Preferences API) would be the way to go.
I've got an SWT application with a bunch of graphical elements. I'd like for the user to be able to drag an element to their Desktop / Windows Explorer / OS X Finder. When they drop the element, I need the path that they dropped it to, so that I can create a file in that location which represents the element.
I don't think I can use a FileTransfer, because there is no source file. There is a source object which can create a file, but only once it knows where to put it.
Inlined below is a simple example of what I'm trying to achieve, there is a text box with a label to drag from. If the user drags to some folder or file, I'd like to get the path that they dragged to. If they dragged to a file, I'd like to replace the contents of that file with whatever is in the text box. If they dragged to a folder, I'd like to create a file called "TestFile" with the contents of whatever is in the text box.
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
public class DesktopDragExample {
public static void main(String[] args) {
// put together the SWT main loop
final Display display = Display.getDefault();
display.syncExec(new Runnable() {
#Override
public void run() {
Shell shell = new Shell(display, SWT.SHELL_TRIM);
initializeGui(shell);
//open the shell
shell.open();
//run the event loop
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
});
}
// create the gui
private static void initializeGui(Composite parent) {
GridLayout layout = new GridLayout(2, false);
parent.setLayout(layout);
// make the instructions label
Label infoLbl = new Label(parent, SWT.WRAP);
GridData gd = new GridData();
gd.grabExcessHorizontalSpace = true;
gd.horizontalAlignment = SWT.FILL;
gd.horizontalSpan = 2;
infoLbl.setLayoutData(gd);
infoLbl.setText(
"You should be able to drag to the desktop, Windows Explorer, or OS X Finder.\n" +
"If you drag to a file, it will replace the contents of that file with the contents of the text box.\n" +
"If you drag to a folder, it will create a file named 'TestFile' whose contents are whatever is in the text box.");
// make the text element
final Text text = new Text(parent, SWT.SINGLE | SWT.BORDER);
gd = new GridData();
gd.grabExcessHorizontalSpace = true;
gd.horizontalAlignment = SWT.FILL;
text.setLayoutData(gd);
// make the label element
Label label = new Label(parent, SWT.NONE);
label.setText("Drag me");
// listener for drags
DragSourceListener dragListener = new DragSourceListener() {
#Override
public void dragStart(DragSourceEvent e) {
e.detail = DND.DROP_COPY;
}
#Override
public void dragFinished(DragSourceEvent e) {
System.out.println("--dragFinished--");
System.out.println("e.data=" + e.data);
}
#Override
public void dragSetData(DragSourceEvent e) {
System.out.println("--dragSetData--");
System.out.println("e.data=" + e.data);
}
};
// the DragSource
DragSource dragSource = new DragSource(label, DND.DROP_COPY);
dragSource.setTransfer(new Transfer[]{FileTransfer.getInstance()});
dragSource.addDragListener(dragListener);
}
private static void draggedTo(String path, String textBoxContents) {
System.out.println("Dragged the contents '" + textBoxContents + "' to '" + path + "'");
}
}
Here are some other people with the same problem, but looks like no solution so far:
Drag from SWT to Desktop, ..want destination path as String
The only way to do it is by creating a temporary file and then using the FileTransfer. I suspect that's what you'd have to do in native code anyways. I'll see if I have enough time to sketch the sample...
You don't get the file location from and write the file yourself. Dragging to the Desktop implies a FileTransfer (you can check what type of transfer is supported in dragSetData).
This means that SWT expecting a String[] of file paths in DragSourceEvent.data. If you set this in the dragSetData method, then SWT copies those files to your drop target - e.g. the Desktop.
#Override
public void dragSetData(DragSourceEvent e) {
System.out.println("--dragSetData--");
System.out.println("Is supported: " + FileTransfer.getInstance().isSupportedType(e.dataType));
FileTransfer f = FileTransfer.getInstance();
String[] filePaths = {"C:\\CamelOut\\4.xml" } ;
e.data = filePaths;
}
};