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
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.
Pretty much what I'm trying to do is make a custom installer, I have buttons and that working fine but I want to run another class called CopyDir.java when I click on the button so that it copies the necessary files to the correct directory. Problem is, is that I'm a bit stumped on how to do this.
public class Frame extends JFrame implements ActionListener {
JPanel pane = new JPanel();
JButton PC = new JButton("Install Mod (PC)");
JButton Steam = new JButton("Install Mod (Steam)");
JLabel Text = new JLabel("Welcome to the BTD 5 Mod Installer");
JLabel Text2 = new JLabel("Click on the button that matches your version of BTD 5");
JLabel Text3 = new JLabel("To install it for the version that you are using");
JLabel Text4 = new JLabel("© Nixxx60/Nanikos");
Frame() {
super("BTD 5 Mod Installer");
setBounds(100, 100, 400, 150);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container con = this.getContentPane();
con.add(pane);
PC.setMnemonic('P');
PC.addActionListener(this);
pane.add(PC);
PC.requestFocus();
con.add(pane);
Steam.setMnemonic('P');
Steam.addActionListener(this);
pane.add(Steam);
Steam.requestFocus();
setVisible(true);
pane.add(Text);
pane.add(Text2);
pane.add(Text3);
pane.add(Text4);
}
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if (source == PC) {
JOptionPane.showMessageDialog(null, "Mod has been installed on PC/Cracked Edition!", "BTD 5 Installer",
JOptionPane.PLAIN_MESSAGE);
setVisible(true);
}
if (source == Steam) {
JOptionPane.showMessageDialog(null, "Mod has been installed for Steam Edition!", "BTD 5 Installer",
JOptionPane.PLAIN_MESSAGE);
setVisible(true);
}
}
public static void main(String args[]) {
new Frame();
}
}
Also, here is the code for the "CopyDir.java" Class.
package Nanikos.BTD5.Main;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class CopyDir {
public static void main(String args[]) throws Exception
{
copyFiles(new File("C:\\Users\\User\\Desktop\\BTD5 Mod Installer\\Mod Files\\PC Assets"),new File("C:\\Program Files (x86)\\Steam\\steamapps\\common\\BloonsTD5"));
System.out.println("Files Copied");
}
public static void copyFiles(File src,File des) throws Exception
{
if(src.isDirectory())
{
if(!des.exists()) des.mkdir();
String [] filePaths=src.list();
for(String filePath: filePaths)
{
File srcFile =new File(src, filePath);
File desFile =new File(des, filePath);
copyFiles(srcFile,desFile);
}
}
else
{
FileInputStream from =null;
FileOutputStream to =null;
from = new FileInputStream(src);
to = new FileOutputStream(des);
byte [] buffer=new byte[4096];
int byteReads;
while( (byteReads=from.read(buffer))!=-1 )
{
to.write(buffer,0,byteReads);
}
from.close();
to.close();
}
}
}
What you want is to launch your class as a Thread
To launch your class CopyDir as a thread, make it implement Thread, change your main method signature to this :
public void run() {
//Your code
}
Also, to pass parameters to your thread, add a constructor in your CopyDir class that takes the parameters you have and stores them as attributes, to be able to get it from your method.
Then, to launch the thread from your event listeners :
CopyDir myCopyThread = new CopyDir(inputPath,outputPath);
myCopyThread.start();
This code will create a thread that starts running CopyDir in the run() method
I have game program where I want the player to choose the file directory to save his game. I am using JFileChooser for this works perfectly fine but it won't close.
here is the code:
public NewGameState(Game game) {
super(game);
open = new JButton();
fc = new JFileChooser();
fc.setCurrentDirectory(new java.io.File("."));
fc.setDialogTitle("Choose file for the new world");
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
}
public void tick() {
input();
selection();
}
public void render(Graphics g) {
drawSelection(g);
drawGUI(g);
}
private void input(){
if(game.getKeyManager().up){
selection --;
}else if(game.getKeyManager().down){
selection ++;
}
if(game.getKeyManager().space){
if(selection == 0){
fileChooser(); //calling fileChooser method when pressing space
}else if(selection == 1){
}else if(selection == 2){
}
}
}
private void selection(){
//blahbahabahaa
}
}
//fileChooser
private void fileChooser(){
fc.showOpenDialog(null);
}
I thought that space is true and it keeps executing the code every tick it turn out it won't stop reading the code which stops the ticking proccess. It keeps reading the method over and over. Other answers are using panel which I'm not using panel in this program I'm using canvas and jframe only
if this is what you are looking for just to be able to close the File Chooser Dialog after selecting the file or saving the file. Just still try to make the code more explanatory i think this should based on my understanding of what u explained
int c = fileWindow.showSaveDialog(this);
if(c==JFileChooser.APPROVE_OPTION)
files.append(fileWindow.getSelectedFile()+"\n");
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);
}
}
});
I'm having an issue with JTabbedPane, in that the contents of individual tabs aren't showing up (Every time I click a new tab, the active tab changes but the contents do not, so I see the same content no matter which tab is selected.).
I'm trying to write an IDE for my own programming language, but have never worked with JTabbedPane before. My tabbed pane consists of JEditTextArea's (user-written component) housed in JScrollPanes. Here is the responsible class
package tide.editor;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.Toolkit;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
import org.syntax.jedit.*;
import org.syntax.jedit.tokenmarker.*;
#SuppressWarnings("serial")
public class Editor extends JFrame implements ActionListener {
//Version ID
final static String VERSION = "0.01a";
//The editor pane houses the JTabbedPane that allows for code editing
//JPanel editorPane;
JTabbedPane tabbedPanel;
//The JTextPanes hold the source for currently open programs
ArrayList<JEditTextArea> textPanes;
//The toolbar that allows for quick opening, saving, compiling etc
JToolBar toolBar;
//Buttons for the toolbar
JButton newButton, openButton, saveButton, compileButton, runButton;
public Editor()
{
super("tIDE v" + VERSION);
setSize(Toolkit.getDefaultToolkit().getScreenSize());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
init();
setVisible(true);
textPanes.get(0).requestFocus();
}
public void init()
{
//Initialise toolbar
toolBar = new JToolBar();
toolBar.setFloatable(false);
newButton = new JButton("New");
newButton.addActionListener(this);
openButton = new JButton("Open");
openButton.addActionListener(this);
saveButton = new JButton("Save");
saveButton.addActionListener(this);
compileButton = new JButton("Compile");
compileButton.addActionListener(this);
runButton = new JButton("Run");
runButton.addActionListener(this);
toolBar.add(newButton);
toolBar.add(openButton);
toolBar.add(saveButton);
toolBar.add(compileButton);
toolBar.add(runButton);
tabbedPanel = new JTabbedPane();
textPanes = new ArrayList<JEditTextArea>();
JEditTextArea initialProgram = createTextArea("program.t");
tabbedPanel.addTab(initialProgram.getName(), new JScrollPane(initialProgram));
getContentPane().add(tabbedPanel, BorderLayout.CENTER);
add(toolBar, BorderLayout.NORTH);
}
public static void main(String[] args)
{
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Editor();
}
});
}
JEditTextArea createTextArea(String name)
{
JEditTextArea editPane = new JEditTextArea(name);
editPane.setTokenMarker(new TTokenMarker());
textPanes.add(editPane);
return editPane;
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == newButton)
{
String filename = "program2";
boolean fileExists = true;
//Ensures that no duplicate files are created
while (fileExists)
{
fileExists = false;
//Get new file name from user
filename = JOptionPane.showInputDialog(null, "Enter a name for the file", "program.t");
//Cancel was clicked in the new file dialog
if (filename == null)
return;
for (JEditTextArea panes: textPanes)
{
if (panes.getName().equals(filename) || panes.getName().equals(filename.concat(".t")) || panes.getName().concat(".t").equals(filename))
fileExists = true;
}
}
//add extension if it is missing
if(!filename.endsWith(".t"))
filename = filename.concat(".t");
//Add the new "file" to the editor window in a new tab
tabbedPanel.addTab(filename, new JScrollPane(createTextArea(filename)));
tabbedPanel.setSelectedIndex(tabbedPanel.getSelectedIndex()+1);
}
if (e.getSource() == openButton)
{
File f = null;
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle("Choose target file location");
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
fileChooser.setAcceptAllFileFilterUsed(false);
FileNameExtensionFilter filter = new FileNameExtensionFilter(
"t source or bytecode(.t, .tbc)", "t", "tbc");
fileChooser.setFileFilter(filter);
if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION)
{
f = fileChooser.getSelectedFile();
}
//Cancel button was clicked on the open file dialog
if (f == null)
return;
//Load the contents of the selected file into the editor
else
{
JEditTextArea textArea = null;
StringBuilder inputText = null;
try {
Scanner sc = new Scanner(f);
//Add a new text area to the editor
textArea = createTextArea(f.getName());
tabbedPanel.add(new JScrollPane(textArea), textArea.getName());
//The newly added tab is set as the active tab
tabbedPanel.setSelectedIndex(tabbedPanel.getTabCount()-1);
textArea.requestFocus();
inputText = new StringBuilder();
while (sc.hasNext())
{
inputText.append(sc.nextLine() + "\n");
}
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
//Set the contents of the current text area to that of the opened file
textArea.setText(inputText.toString());
}
}
}
}
1) remove code lines from FileIO related try - catch blok
textArea = createTextArea(f.getName());
tabbedPanel.add(new JScrollPane(textArea), textArea.getName());
//The newly added tab is set as the active tab
tabbedPanel.setSelectedIndex(tabbedPanel.getTabCount()-1);
textArea.requestFocus();
prepare those Object before of after Input / OutputStreams
2) close() all Objects from Input / OutputStreams, in the finally block (try - catch - finally)
3) JTextComponets implements read() and write(), accepting all separators, then there no reason programatically call for "\n"
4) use SwingWorker code for FileIO
This might not be solution for the root cause, but there might be some inconsistency in your code which is causing paint issues on the TestAreas, So I would suggest you to register a TabChageListener and then repaint the ScrollPane for that specific tab, this should work:
tabbedPanel.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
int selectedIndex = tabbedPane.getSelectedIndex();
// get the ScrollPane for this selectedIndex and then repaint it.
}
});
I've been struggling with this very problem for the last couple of hours.
In fact, it doesn't matter how many JEditTextArea you instantiate, they all rely on the same SyntaxDocument, thus the same text. That's just the way it's coded in JEditTextArea.
In constructor public JEditTextArea(TextAreaDefaults defaults) you will need to find the line:
setDocument(defaults.document);
and replace it with:
setDocument(new SyntaxDocument());
and it will instantiate a brand new Document every time you make a new JEditTextArea.