Edit JTable which contains files' info - java

I've got a JTable that is filled by Vectors. These Vectors get their content by a loop, listing all files in a specific folder. Now I want to edit a Cell (via the GUI) that contains a filename and the real File on the HD should be renamed too. So how do I archive this?
Here's my code for the method that fills the JTable.
private void reloadFiles(){
vecVectors.clear();
if (Variables.pathToFiles != null) {
Variables.listOfFiles.clear();
Variables.listOfFiles = listFilesForFolder(Variables.pathToFiles);
for (File file : Variables.listOfFiles) {
Vector<String> temp = new Vector<String>();
temp.add(file.getName());
vecVectors.add(temp);
}
table.removeAll();
table = new JTable(vecVectors, vecHeaders);
this.remove(listScroller);
listScroller.removeAll();
listScroller = new JScrollPane(table);
listScroller.setPreferredSize(new Dimension(950, 450));
this.add(listScroller);
System.out.println("Reloaded");
}
}

Instead of using vectors to fill your table, you can use a more sophisticated table model implementation that allows you to work directly with File objects as rows in your table. I'm talking about either DataObjectTableModel or Rob Camick's RowTableModel.
So, let's say you have the table model implementation solved and each row in your table is a File object. Now, I wouldn't make any cell editable and let the table just display files info, considering:
There are many factors that can go wrong (i.e: invalid or existent file name)
It's not a TableModel responsibility to reflect the update in the HD.
It can be done using TableModelListener but the events are fired once the model has changed, so if you have troubles updating the file name in the HD then you have to revert the table model's changes. Not so easy though.
In order to re-name a file, I'd attach a MouseListener to the table and show a pop up dialog to let the user input the new file name. Finally use the File API to rename the file and update the table model reflecting these changes.
Snippet
final DataObjectTableModel<File> model = new DataObjectTableModel<File>(header) {
// Override getValueAt() and getColumnClass() here
};
final JTable table = new JTable(model);
table.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() >= 2 && !e.isPopupTrigger()) {
int selectedRow = table.rowAtPoint(e.getPoint());
if (selectedRow != -1) {
String newName = JOptionPane.showInputDialog (
null
, "Please input the new name"
, "Rename file"
, JOptionPane.INFORMATION_MESSAGE
);
if (newName != null) {
int modelIndex = table.convertRowIndexToModel(selectedRow);
File file = model.getDataObject(modelIndex);
// Maybe this part should be done
// using a SwingWorker to avoid blocking the EDT
String newPath = file.getParent() + File.separator + newName;
File newFile = new File(newPath);
if (file.renameTo(newFile)) {
model.deleteDataObject(modelIndex); // remove the old file
model.insertDataObject(newFile, modelIndex); // insert the new file in the same index
} else {
JOptionPane.showMessageDialog (
null
, "An error happened trying to rename file " + file.getName()
, "Error!"
, JOptionPane.WARNING_MESSAGE
);
}
}
} // if (selectedRow != -1)
} // if (e.getClickCount() >= 2 && !e.isPopupTrigger())
}
});

Related

Netbeans module development - How to modify opened file

I am writing my own Netbeans plugin to edit opened files. I have managed to get some information about currently active file using
TopComponent activeTC = TopComponent.getRegistry().getActivated();
FileObject fo = activeTC.getLookup().lookup(FileObject.class);
io.getOut().println(fo.getNameExt());
io.getOut().println(fo.canWrite());
io.getOut().println(fo.asText());
But I have no idea how to modify this file. Can someone help me with this?
And second question, how to get text selection ranges? I want to run my command only on selected text.
For modifying the file you could use the NetBeans org.openide.filesystems.FileUtil.toFile() and then the regular Java stuff to read and write files and for getting the selected text of the current editor window you would have to do something like:
Node[] arr = activeTC.getActivatedNodes();
for (int j = 0; j < arr.length; j++) {
EditorCookie ec = (EditorCookie) arr[j].getCookie(EditorCookie.class);
if (ec != null) {
JEditorPane[] panes = ec.getOpenedPanes();
if (panes != null) {
// USE panes
}
}
}
For more code examples see also here
After several hours of research I found out that:
The code I posted in Question can be used to obtain basic information about active file.
To get caret position or get selection range you can do:
JTextComponent editor = EditorRegistry.lastFocusedComponent();
io.getOut().println("Caret pos: "+ editor.getCaretPosition());
io.getOut().println("Selection start: "+ editor.getSelectionStart());
io.getOut().println("Selection end: "+ editor.getSelectionEnd());
To modify content of active file (in a way that the modification can be undo by Ctrl+z) you may use this code:
final StyledDocument doc = context.openDocument();
NbDocument.runAtomicAsUser(doc, new Runnable() {
public void run() {
try {
doc.insertString(ofset, "New text.", SimpleAttributeSet.EMPTY);
} catch (Exception e) {
}
}
});

How to save txt on custom path

I have a code that saves a textfile, but the path of that textfile and the name are hardcoded.
How can i make that the user select his/her own path and the name of the file?
int[][] sudokuNumbers = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
try (
PrintStream output = new PrintStream(new File("C:\\Users\\David\\Desktop\\Proyecto4.3\\output.txt"));) {
for (int i = 0; i < sudokuNumbers.length; i++) {
String s= "";
for (int j = 0; j < sudokuNumbers[i].length; j++) {
s+= "|" + sudokuNumbers[i][j] + "|";
}
output.println(s);
}
output.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
The task is relatively easy to carry out however you will need a couple methods to assist you. If a User is to supply a custom path (specific for them-self) then you will need to ensure that the path will be created so that it exists before the file is created and written to. Another thing to consider is that there may also be a requirement of Permissions to be granted to the application so as to carry out the task within the local file system (if this is where the file is to be created) or wherever else.
Obviously you will need to provide a means for the User to supply a path and file name. The best way to do this in my opinion is with a Folder Chooser dialog. The reason I say this is because it's not nearly as prone to mistakes (spelling, system format, etc.) as it would be if the User completely typed in the desired path and file name. Basically, the less control you give the User to the local file system the better off your application will be. Creating a folder (directory) based on the User Name within a preset file system location and utilizing a User name and date/time for file names is relatively common and can be all auto-generated, this eliminates the possibility of any file system errors. If possible, your application should maintain full control of such a task but understandably this can not always be the case for specific applications where User interaction with the file system is a requirement due to the fact that it's sole functionality is based on such interaction. For example, a File System Explorer where creating, cutting, copying, pasting, deleting, and editing of files and folders is its allowable purpose.
To demonstrate what I'm talking about I have quickly created a small Java runnable you can play with to see how the provided custom methods work. The code is well commented so that you can understand what is going on. Unfortunately all the commenting makes the code file look large when in fact it isn't if you were to remove them.
For simplicity, when we run the provided little console application it first asks for a User's Name. This Users Name will serve two specific purposes.
1) It will be used to create a specific Folder for that particular User only.
2) When a file is saved the file name will start with the User's name and then be followed with date/time data and finally contain the
".txt" file name extension.
Again, just for example purposes, as soon as a User enters his/her name into the console a Folders Selection dialog window will be displayed so that a main folder location can be selected where Users sub-folders will be created in and ultimately the Users data files will be saved under his/her folder name.
The file data is automatically saved once the home folder is selected and the console indicates of success once completed. Our little console application then simply ends.
Here is the Java runnable:
package choosefolder;
import java.awt.Component;
import java.awt.Container;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.time.LocalDateTime;
import java.util.Scanner;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
public class ChooseFolder {
// Declare & initialize required String variables.
// These are global to the entire Class.
private static String userName = "";
private static String savePath = "";
public static void main(String[] args) {
//Setup a Scanner to get User input from console.
Scanner input = new Scanner(System.in);
// Ask for and get the Users Name and convert it to lowercase
// so as to maintain nameing consistency. No sense having "John Doe"
// one day and "john Doe" the next. This would consider 2 different
// Users since the second name has a lowercase "j" in "John" and
// therefore create two separate folder. Converting all supplied names
// to lowercase eliminates this problem.
while (userName.equals("")) {
System.out.println("\nPlease Enter User Name:");
userName = input.nextLine().toLowerCase();
}
// Open a Folders selection dialog window and allow for
// selection of a home folder where all Users saved files
// will be saved. Once we get the selected folder we then
// add the Users name to the path and create it.
savePath = openFoldersDialog("", "Select Home Folder To Save User Folders & File In...") + "\\" + userName;
// Create a special path just for the Users Name (ie: C:\My Files\John Doe\).
if (!createPath(savePath)) {
// If false was returnd from the createPath() method
// then there was an error while creating the path.
// Read console output to get the Error.
System.out.println("\n\u001B[31mError creating Users Save Path! Exiting...\u001B[39;49m");
System.exit(0);
}
// Get the local date & time so we can add it to
// our file namewhen its created.
LocalDateTime dateTime = LocalDateTime.now();
// Create the new file path & file name. This will be the path
// and file name where our Users data will be saved. We take the
// Users path e created and then add the file name to the end. The
// file name consists of the supplied User's name, the date/time and
// the .txt file name extension. Unwanted characters are also removed
// from the Date/Time. So, our path may look something like:
// C:\My Files\John Doe-20160419T155758107.txt
String filePathAndName = savePath + "\\" + userName + "-" +
dateTime.toString().replace("-", "").
replace(":", "").replace(".", "") + ".txt";
// Here is your code. This is the data saved to file....
int[][] sudokuNumbers = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
try (
// Notice the filePathAndName variable which we declared and initialized above.
PrintStream output = new PrintStream(new File(filePathAndName));) {
for (int i = 0; i < sudokuNumbers.length; i++) {
String s= "";
for (int j = 0; j < sudokuNumbers[i].length; j++) {
s+= "|" + sudokuNumbers[i][j] + "|";
}
output.println(s);
}
output.close();
}
catch (FileNotFoundException e) {
System.out.println(e.getMessage());
}
finally {
// Notify in console of success.
System.out.println("\n\u001B[34mFile Saved SUCCESSFULLY in:\n\u001B[39;49m" + filePathAndName);
}
}
/**
* Opens a Folder (directory) selection dialog window. All parameters for this method are optional but if you supply
* something to the last parameter then you must supply something to the parameters preceding it even if it's a null
* string ("") (see usage examples below)
*
* Example Usage:
*
* openFolderDialog(); //Allowed
* openFolderDialog("C:\\"); //Allowed
* openFolderDialog("", "Select The Folder You Need"); //Allowed
* openFolderDialog("", "", "Select Folder"); //Allowed
* openFolderDialog("", "", ""); //Allowed
* openFolderDialog( , "Your Folders, "Select Folder"); //Not Allowed
* openFolderDialog( , , "Select Folder"); //Not Allowed
* openFolderDialog("C:\\", "Your Folders, ); //Not Allowed
*
* I think you get the idea here.
*
* #param dialogOptions OPTIONAL - 3 String Type Parameters
* startPath - String - Default is the running applications' home folder. The path
* supplied here tells the dialog where to start displaying folders from.
* If you just want to use default but would like to supply something to
* the other optional parameters then just supply a null string ("") here.
*
* dialogTitle - String - Dialog Window Title - Default is "Select Folder...". You can
* supply whatever title you like for the dialog window.
*
* openButtonCaption - String - The Select Button Caption - Default is "Select". You can supply
* whatever you like for a button caption and it can be more than one word
* but do keep in mind that the button increases in length to accommodate the
* the supplied string.
*
* #return The selected Folder (directory) full path as string. Returns Null is nothing was selected.
*/
public static String openFoldersDialog(String... dialogOptions) {
String startPath = "";
try {
startPath = new File(".").getCanonicalPath();
} catch (IOException ex) {}
String dialogTitle = "Select Folder...";
String openButtonCaption = "Select";
if (dialogOptions.length != 0) {
if (dialogOptions.length >= 1) {
if (!dialogOptions[0].isEmpty()) { startPath = dialogOptions[0]; }
}
if (dialogOptions.length >= 2) {
if (!dialogOptions[1].isEmpty()) { dialogTitle = dialogOptions[1]; }
}
if (dialogOptions.length == 3) {
if (!dialogOptions[2].isEmpty()) { openButtonCaption = dialogOptions[2]; }
}
}
File sp = new File(startPath);
JFileChooser fc = new JFileChooser(sp);
//Remove the "Files Type:" combo box and label from dialog.
removeJFCFilesTypeComponent(fc);
fc.setDialogTitle(dialogTitle);
fc.setAcceptAllFileFilterUsed(false);
fc.setRequestFocusEnabled(true);
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int userSelection = fc.showDialog(null, openButtonCaption); //.showSaveDialog(null);
if (userSelection == JFileChooser.APPROVE_OPTION) {
String f = fc.getSelectedFile().getPath();
return f;
}
return null;
}
/**
* Removes the Filter ComboBox from the supplied JFileChooser object.
* This helps make the JFileChooser dialog window look more like a
* folder selection dialog.
* #param filechooser The object name of the JFileChooser object.
*/
public static void removeJFCFilesTypeComponent(Container filechooser) {
Component[] components = filechooser.getComponents();
for (Component component : components) {
if (component instanceof JComboBox) {
Object sel = ((JComboBox) component).getSelectedItem();
if (sel.toString().contains("AcceptAllFileFilter")) {
component.setVisible(false);
// OR
//con.remove(component);
}
}
if (component instanceof JLabel) {
String text = ((JLabel) component).getText();
if (text.equals("Files of Type:")) {
component.setVisible(false);
// OR
//con.remove(component);
}
}
if (component instanceof Container) {
removeJFCFilesTypeComponent((Container) component);
}
}
}
/**
* Creates the supplied path into the local file system if it doesn't already exist. You must
* make sure permissions are properly in place before using this method otherwise the path may
* not be created within the file system.
* #param pathString The path to create (must not include a file name). Will not create path if it already exists.
* #return Boolean True if successful and Boolean False if not.
*/
public static boolean createPath(String pathString) {
if (pathString.isEmpty()) { return false; }
if (doesFolderExist(pathString)) { return true; }
try {
File foldersToMake = new File(pathString);
foldersToMake.mkdirs();
return true;
}
catch (Exception ex) {
System.out.println("*** CreatePath() - Exception Encountered:\n*** " + ex.getMessage());
return false;
}
}
/**
* This method simply return boolean true or false if the supplied path exists.
* #param folderPathString (String) The full path to check. No File Name is allowed
* to be in this path.
* #return
*/
public static boolean doesFolderExist(String folderPathString) {
boolean tf = false;
try {
if (folderPathString.isEmpty() || "".equals(folderPathString)) { return tf; }
File f = new File(folderPathString);
if(f.exists() && f.isDirectory()) { tf = true; }
}
catch (Exception e) {
System.out.println("*** DoesFolderExist() - Exception Encountered:\n*** " + e.getMessage());
tf = false;
}
return tf;
}
}
I hope this helps you (and others).

Search Box for Jpanel

I am in the middle of creating an app that allows users to apply for job positions and upload their CVs. I`m currently stuck on trying to make a search box for the admin to be able to search for Keywords. The app will than look through all the CVs and if it finds such keywords it will show up a list of Cvs that contain the keyword. I am fairly new to Gui design and app creation so not sure how to go about doing it. I wish to have it done via java and am using the Eclipse Window builder to help me design it. Any help will be greatly appreciated, hints, advice anything. Thank You.
Well, this not right design approach as real time search of words in all files of given folder will be slow and not sustainable in long run. Ideally you should have indexed all CV's for keywords. The search should run on index and then get the associated CV for that index ( think of indexes similar to tags). There are many options for indexing - simples DB indexing or using Apache Lucene or follow these steps to create a index using Maps and refer this index for search.
Create a map Map<String, List<File>> for keeping the association of
keywords to files
iterate through all files, and for each word in
each file, add that file to the list corresponding to that word in
your index map
here is the java code which will work for you but I would still suggest to change your design approach and use indexes.
File dir = new File("Folder for CV's");
if(dir.exists())
{
Pattern p = Pattern.compile("Java");
ArrayList<String> list = new ArrayList<String>(); // list of CV's
for(File f : dir.listFiles())
{
if(!f.isFile()) continue;
try
{
FileInputStream fis = new FileInputStream(f);
byte[] data = new byte[fis.available()];
fis.read(data);
String text = new String(data);
Matcher m = p.matcher(text);
if(m.find())
{
list.add(f.getName()); // add file to found-keyword list.
}
fis.close();
}
catch(Exception e)
{
System.out.print("\n\t Error processing file : "+f.getName());
}
}
System.out.print("\n\t List : "+list); // list of files containing keyword.
} // IF directory exists then only process.
else
{
System.out.print("\n Directory doesn't exist.");
}
Here you get the files list to show now for "Java". As I said use indexes :)
Thanks for taking your time to look into my problem.
I have actually come up with a solution of my own. It is probably very amateur like but it works for me.
JButton btnSearch = new JButton("Search");
btnSearch.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
list.clear();
String s = SearchBox.getText();
int i = 0,present = 0;
int id;
try
{
Class.forName(driver).newInstance();
Connection conn = DriverManager.getConnection(url+dbName,userName,password);
Statement st = conn.createStatement();
ResultSet res = st.executeQuery("SELECT * FROM javaapp.test");
while(res.next())
{
i = 0;
present = 0;
while(i < 9)
{
String out = res.getString(search[i]);
if(out.toLowerCase().contains(s.toLowerCase()))
{
present = 1;
break;
}
i++;
}
if(tglbtnNormalshortlist.isSelected())
{
if(present == 1 && res.getInt("Shortlist") == 1)
{
id = res.getInt("Candidate");
String print = res.getString("Name");
list.addElement(print+" "+id);
}
}
else
{
if(present == 1 && res.getInt("Shortlist") == 0)
{
id = res.getInt("Candidate");
String print = res.getString("Name");
list.addElement(print+" "+id);
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
});

JasperViewer - How to set file name and set the extension (format)?

I am developing Java desktop based application using Swing framework and JasperReports for reporting. I have some problems, when JasperViewer comes up and I want to save the report.
How can I set the name of the file (default is blank) in the save dialog and how to limit only Pdf format?
Here is my code:
JRBeanCollectionDataSource beanCollection=new JRBeanCollectionDataSource(matakuliahs);
Map<String,Object> map=new HashMap<String, Object>();
map.put("namaMahasiswa", mahasiswa.getNama());
InputStream input=getClass().getResourceAsStream("/reportsederhana/reportsederhana.jrxml");
JasperDesign design=JRXmlLoader.load(input);
JasperReport report=JasperCompileManager.compileReport(design);
JasperPrint jasperPrint=JasperFillManager.fillReport(report, map, beanCollection);
jasperPrint.setName("Laporan "+mahasiswa.getNama()); // it doesn't give the name
JasperViewer.viewReport(jasperPrint,false);
For setting the default extension(s) to save to, one idea is that you need to somehow get the JRViewer instance from a JasperViewer (instance) and then, on the void JRViewer instance, you can set some save contributions. Have a look at JRViewer.setSaveContributors(JRSaveContributor[] saveContribs).
For setting the file name, i am not entirely sure, but have a look at JRViewer.JRViewer(String, boolean).
Also check the JRViewer and the JasperViewer source code, it may come in handy.
It is an old post but I ran into the same problem...
I extended my viewer component from net.sf.jasperreports.view.JRViewer. After some code review I saw that it is only possible to control the 'lastFolder' but not the filename from outside. So you can set the last used folder if it is not set already by:
if (lastFolder == null) {
this.lastFolder = new File(System.getProperty("user.home"));
}
But, and thats the hint: All buttons of toolbar are public fields!
So for my solution I removed all ActionListeners of the save button (btnSave):
for (ActionListener actionListener : this.btnSave.getActionListeners()) {
this.btnSave.removeActionListener(actionListener);
}
And then added my own implementation. It is pretty like the original one only with the difference that I control the file name depending to the report name and current timestamp.
...
File file = new File(lastFolder.getPath() + System.getProperty("file.separator") + DateTime.now().toString() + "_" + jasperPrint.getName());
...
Additionally I set the pre-selected file extension from .jasperprint to .pdf which is more convenient.
...
fileChooser.setFileFilter((FileFilter) saveContributors.get(1));
...
The full ActionListener code is as follows:
this.btnSave.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setLocale(getLocale());
fileChooser.updateUI();
File file = new File(lastFolder.getPath() + System.getProperty("file.separator") + DateTime.now().toString() + "_" + jasperPrint.getName());
fileChooser.setSelectedFile(file);
for (int i = 0; i < saveContributors.size(); i++)
fileChooser.addChoosableFileFilter((FileFilter) saveContributors.get(i));
if (saveContributors.contains(lastSaveContributor))
fileChooser.setFileFilter(lastSaveContributor);
else if (saveContributors.size() > 1)
fileChooser.setFileFilter((FileFilter) saveContributors.get(1));
if (lastFolder != null)
fileChooser.setCurrentDirectory(lastFolder);
int retValue = fileChooser.showSaveDialog(JasperViewer.this);
if (retValue == 0) {
FileFilter fileFilter = fileChooser.getFileFilter();
file = fileChooser.getSelectedFile();
lastFolder = file.getParentFile();
JRSaveContributor contributor = null;
if (fileFilter instanceof JRSaveContributor) {
contributor = (JRSaveContributor) fileFilter;
} else {
int i = 0;
do {
if (contributor != null || i >= saveContributors.size())
break;
contributor = (JRSaveContributor) saveContributors.get(i++);
if (!contributor.accept(file))
contributor = null;
} while (true);
if (contributor == null)
contributor = new JRPrintSaveContributor(jasperReportsContext, getLocale(), null);
}
lastSaveContributor = contributor;
try {
contributor.save(jasperPrint, file);
} catch (JRException ex) {
logger.error("Could not save report.", ex);
JOptionPane.showMessageDialog(JasperViewer.this, trc("JasperViewer.error.save", "Could not save report."));
}
}
}
});

Printing chatter names from server file in a textfield Java

I would like to ask about how can I print the names of the chatters in a textfield that I created in my client file. Here is the code snippet of the server file that I have:
while (true) {
out.println("SUBMITNAME");
name = in.readLine();
if (name == null) {
return;
}
synchronized (names) {
if (!names.contains(name)) {
names.add(name);
}
break;
}
}
}
This piece of code gets the names of the chatters but I cannot display them in a textfield. Thank you very much for your help!
You can try jTextArea.append("ChatterName\n") or jTextArea.append("ChatterName<br/>"), (I think the break tag might be the issue).
But a JList IMO would be much nicer.
private DefaultListModel defaultListModel = new DefaultListModel() ;
private JList jList = new JList(defaultListModel) ;
defaultListModel.addElement(chatterName);
That appends a chatter name nicely to a JList.

Categories

Resources