i tried to build a FileChooser with java and RMI to browse the file system of a remote machine.
What I did until now is best shown in the following diagram. The exists() method-call is an example and all methods of RemoteFileView, RemoteFileSystemView and RemoteFile forward to the server.
In words:
I build a RemoteFileView (extends FileView), RemoteFileSystemView (extends FileSystemView) and a RemoteFile (extends File) and overrode all methods of the super-classes except File.hashCode() and FileSystemView.createFileSystemRoot(File) (this method is protected in FileSystemView). All overridden methods call methods on the RMI-Server where the FileView- and FileSystemView from the server call the server-methods (like the JFileChooser would do). I get the FileView and the FileSystemView on the server side from a dummy instantiated JFileChooser.
So now what the system does:
- Start RMI-Server
- Start RMI-Client
- JFileChooser gets the RemoteFileView
- JFileChooser gets the RemoteFileSystemView
- JFileChooser gets all the RemoteFiles from the server and shows folders as well as files in the JFileChooser
So the behavior is good until now. And now the problem (where I can’t get rid of):
The initial view of the JFileChooser (client) shows all Files of the home directory of the server. I can (per button click) switch to the parent directory until the system root (on windows for example the system drive „C:\“ ). From there (or from everywhere else) I can double-click on a folder to jump into it as long as this path exists on the client-system but the shown files and folders are from the server. If the path doesn’t exist on the client I can’t jump into it and browse this folder. So if anyone knows this behavior please help (I appreciate any solution :) ).
So I decided to code an own mouse listener that recognize double-clicks on the JFileChooser. But if I double-click on a folder (in the JFileChooser) nothing happens. If I highlight a folder (via click) and then double-click somewhere in the JFileChooser (not in the File-View or a button) the listener recognize my double-click and jumps into the highlighted folder (hope this is clear enough).
I think the FileView (on the JFileChooser) lies over the JFileChooser and should get it’s own listeners. Or I forgot something to code out.
The RMI-interface holds all methods which are called from the RemoteFileView, RemoteFileSystemView and the RemoteFile and from the behavior of the system this should be ok.
I can of course poste some codes as well as more informations about the whole program. Posting all codes would be too much I guess.
EDIT:
As this question may be "too broad" the more concrete version (which may solve my problem): Which listener fires on double click a folder in the JFileChooser? Can this listener be removed or set?
EDIT2:
I saw in this question: Repurposing JFileChooser that the JFileChooser fires on JFileChooser.APPROVE_SELECTION whenever a file is choosen by double click. So I implemented this code:
fileChooser.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Some action");
String command = e.getActionCommand();
if (command.equals(JFileChooser.APPROVE_SELECTION)) {
File file = fileChooser.getSelectedFile();
fileChooser.setCurrentDirectory(file);
fileChooser.rescanCurrentDirectory();
}
}
});
But unfortunately the action listener doesn't recognize any action inside the FileView (the component which shows the files) but does fire action events on button clicks (which I detected with the System.out..).
The problem as I described above are the components and their mouse listeners. So first you have to get your components and then add the listeners to it. So in a JFileChooser we got a JList and a JTable. Both views can be switched by button klick. The JList holds the files as well as the JTable.
I found kind of solution here: https://community.oracle.com/thread/1350166?start=0&tstart=0
So I used some codes from there and implemented my mouse listeners:
The Listener for the JList:
JList<?> list = SwingUtils.getDescendantOfType(JList.class, fileChooser, "Enabled", true);
MouseListener listener = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
File file = fileChooser.getSelectedFile();
if (e.getClickCount() == 2 && file != null) {
if (e.getSource() == list) {
// Do your stuff
operateOnFile(file);
}
else {
// Default operation
}
}
}
};
list.addMouseListener(listener);
And the listener for the JTable:
final Container filePane = SwingUtilities.getAncestorOfClass(sun.swing.FilePane.class, list);
filePane.addContainerListener(new ContainerAdapter() {
#Override
public void componentAdded(ContainerEvent e) {
JTable table = SwingUtils.getDescendantOfType(JTable.class, fileChooser, "Enabled", true);
if (table != null) {
for (MouseListener l : table.getMouseListeners()) {
if (l == listener) {
return;
}
}
table.addMouseListener(listener);
}
}
});
With this solution I got the behavior I wanted.
Related
I have been trying to follow these set of Java tutorials from this website
http://www.homeandlearn.co.uk/java/java.html
However the tutorials are in Netbeans and I am using Eclipse.
Till now there has been no difficulties until now.
http://www.homeandlearn.co.uk/java/opening_files.html
In the given tutorial using JFileChooser to open files through a JMenuItem called 'Open' is shown. However when i use the code given in the website the following error occurs
The method showOpenDialog(Component) in the type JFileChooser is not applicable for the arguments (new ActionListener(){})
This is the code for which the error is occuring.
JMenuItem mntmNewMenuItem = new JMenuItem("Open");
mntmNewMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
int returnVal = db.showOpenDialog(this);
}
});
So, my question is, what should i change in the above code stub to be able to use the file chooser?
If you want to view the entire code, i will put it in on your request.
Meaning of the error: the method showOpenDialog requires a parameter of type Component but is being called with an ActionListener. More exactly, the given parameter is of an anonymous class implementing ActionListener and not a Component:
new ActionListener() { ... }
inside the methods declared where I used . . . the keyword this points to the instance of that anonymous class.
See the documentation of showOpenDialog(), it requires a parent or null:
Pops up an "Open File" file chooser dialog. Note that the text that
appears in the approve button is determined by the L&F.
Parameters:
parent - the parent component of the dialog, can be null; see showDialog for details
And the relevant documentation of showDialog():
The parent argument determines two things: the frame on which the open
dialog depends and the component whose position the look and feel should
consider when placing the dialog.
...
If the parent is null, then the dialog depends on no visible window, and
it's placed in a look-and-feel-dependent position such as the center of
the screen.
Usually the passed parameter is the JFrame or JPanel that should visually contain the dialog, but it can be null:
int returnVal = db.showOpenDialog(null);
There is a java swing application that I need to automate one of the functions of. It's quite simple - the user clicks a button in the swing application and starts an action.
I made a small java application that includes the java swing application as a .jar and calls the action behind the button (read).
The problem is - in case of an exception, the swing .jar shows JOptionPane, which halts the automated execution. Is it possible to somehow override this behavior without altering the original jar?
Application structure:
Main.java
import com.swingapp.ui
public static void main(String[] args){
Swingapp.read();
}
Then the read() function in the Swingapp library:
public void read(){
try{
//do a bunch of stuff...
} catch (Exception ex){
JOptionPane.showMessageDialog(null, ex.getMessage()); // In case of an exception, the swing application will show a message dialog. This halts the automated execution of my java task, I'd like to just skip this
}
When exception happens in above application, user is expected to click "OK". But running this as automated task, nobody there to click okay
Since a JOptionPane gains focus as soon as it opens (I think the most right button gets the focus, but it does not matter in your case) you can do the following:
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent arg0) {
Component c = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
while(c != null) {
if (c instanceof JOptionPane) {
try {
new Robot().keyPress(KeyEvent.VK_ENTER);
} catch (AWTException e) {
e.printStackTrace();
break;
}
}
c = c.getParent();
}
}
}, AWTEvent.FOCUS_EVENT_MASK);
It will traverse up to see if anything in the current hierarchy is an instance of JOptionPane. If so -> simulate that the user pressed Enter (Return) which will close the dialog even if the focus is in an input field.
I have following solution for you. You need to registrate a listener to monitor all window events. Use Toolkit.getDefaultToolkit().addAWTEventListener(). If you get a window opened event, try to check whether the window is a JDialog and whether the dialog's contentPane contains an instance of JOptionPane. If yes you need traverse the component tree, find the first button and click it.
I am trying to code a small text editor and I was building the GUI.
I added a JMenu and added a JMenuItem to it. I gave the menu item the value of "open".
The reason is because I want that when "open" is pressed a JFileChooser appears on the screen
Here is what I have:
public void mousePressed(MouseEvent me) {
JFileChooser fs = new JFileChooser();
}
This method is in a class called listener which implements MouseListener. This is the step that I'm stuck at.
getContentPane()
..does not work:
Is it good code practice the way I'm approaching this? Is there a better way? If not how do I go around doing this?
While in general your approach could work, you might want to look into the Swing concept of Actions. JMenuItem has direct support for actions, you would not need a MouseListener (which is a bit to low-level for your usecase).
Try to look at the examples, it might look a little overwhelming at first, but in the end it is a nice and clean encapsulation of what you want. And it is reusable, meaning you could use the action on a different menu (maybe the context menu) as well.
And for your code, you are missing the call to fs.showOpenDialog(component).
Firstly, don't use a MouseListener for JMenuItem or JButton, this is not the appropriate means for managing these components, instead, use an ActionListener.
The main reason for this is that your menu item could be triggered via a keyboard shortcut or programmatically.
Secondly "does not work" is not information about what you problem is, but I assume it's because the method does not exist.
A simply solution would be to check the source the event to determine if it's a Component or not and use it instead, or null if the source of the event is not a Component...
public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
Component parent = null;
if (source instanceof Component) {
parent = (Component)source;
}
// Show file chooser dialog...
}
Take a look at How to use menus for more details
You may also find How to use actions of some interest
Have a look at the Javadoc on the JFileChooser class. It has an example of how to open it.
The following code pops up a file chooser for the user's home directory that sees only .jpg and .gif images:
JFileChooser chooser = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter(
"JPG & GIF Images", "jpg", "gif");
chooser.setFileFilter(filter);
int returnVal = chooser.showOpenDialog(parent);
if(returnVal == JFileChooser.APPROVE_OPTION) {
System.out.println("You chose to open this file: " +
chooser.getSelectedFile().getName());
}
I want to get my program to unhide main window when user presses some shortcut. Is there a way to get the global key events, not only the ones which happened when focus was inside application frame?
This might do what you want. Note that this code is checking for a Ctr-F keystroke. I use this code to open up a find dialog from anything in the application. I'm pretty sure that the app has to have focus though. Something to try at least...
AWTEventListener listener = new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent event) {
try {
KeyEvent evt = (KeyEvent)event;
if(evt.getID() == KeyEvent.KEY_PRESSED && evt.getModifiers() == KeyEvent.CTRL_MASK && evt.getKeyCode() == KeyEvent.VK_F) {
}
}
catch(Exception e) {
e.printStackTrace();
}
}
};
Toolkit.getDefaultToolkit().addAWTEventListener(listener, AWTEvent.KEY_EVENT_MASK);
EDIT: I think I understand what you want. Basically when the app does NOT have focus. If so then you'll probably have to hook into the OS events with a native API (JNI) but that forces you to a specific OS...
This might be useful. I'm not sure if there is one library that will work for Windows/Linux/Mac. For Windows you will need some external library that uses native code to create a keyboard hook. I have no idea how to do it on the other OSes.
A solution to do this by using a JFrame is to set his opacity to 0.0 and to add the Keylistener to it. But the user will see an icon in his shortcut bar...
I want to display a set of images (with associated text) on my window. I want to iterate through them using a previous and a next button. So far, I have only been able to associate the image with a JLabel. =/
How do I go about doing the rest? Should I use a different container for the complete set? Should I load the images on a data structure like an ArrayList, or is it enough to keep them on a folder? How can I add the event handling so that pushing the button displays the next or previous image?
Here is a screenshot of what I have so far.
Are you still here ?
I assume that you have found how to load the path of each of your images (if they are inside the same folder). You should store the path of the directory in a global variable, and then the name of each image into a Vector if you want to iterate through them. Just store the name of the files, not the entire images.
You also have to store the index of the current image as a global variable.
If you use a JFrame as your main window, you have to specify that it implements the class ActionListener this way:
public class MyClass extends JFrame implements ActionListener
Then you have to attach the event handler to your buttons (JButton). This must be placed inside the constructor of your window (MyClass):
nextButton.addActionListener(this);
previousButton.addActionListener(this);
Having implemented ActionListener, your class has to define the method actionPerformed. Inside it, you must change the content of the image according to the button that has been pressed.
public void actionPerformed(ActionEvent e)
{
Object o = e.getSource();
if(o == nextButton)
{
currentIndex++;
if(currentIndex == vectorImages.size())
{
currentIndex = 0;
}
//Change the image in the JLabel
label.setIcon(new ImageIcon(vectorImages.get(currentIndex)));
}
else
{
//Iterate backwards
}
}
Hope this helps...