I'm currently on NetBeans lessons on how to create Java programs with GUI. I've noticed in several GUI controls the text field and the combobox, the "Action" and the "Name" properties are always present. What is the purpose of these properties and how can I use them? For example, I'll use a text field here:
JTextField aTextField = new JTextField();
String act = "aksyon";
JTextField.setActionCommand(act);
What is the difference of setActionCommand() from setAction()? I thank you in advance for your help.
ActionCommand is the key used to determine the command String for the ActionEvent that will be created when an Action is going to be notified as the result of residing in a Keymap associated with a JComponent.
public void setActionCommand(String command)
Sets the command name for the action event fired by this button. By default this action command is set to match the label of the button.
read more here
Related
I have an JDialog containing a JEditorPane for showing non-user-editable HTML content, such as Help and Release Notes.
The JDialog has a "Close" button that is installed as the default button.
If the JEditorPane is left "focusable", then the Page Up/Down keys will scroll through the document, but pressing "Enter" does not fire the default button.
On the other hand, if the JEditorPane is set non-focusable, then Page Up/Down keys do not work, but pressing the "Enter" key does fire the default button, closing the dialog.
#SuppressWarnings("serial")
public class NoteViewer extends JFrame {
public static void main(String[] args) throws IOException {
final NoteViewer viewer = new NoteViewer(new URL("http://example.com/"));
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
viewer.setVisible(true);
}
});
}
public NoteViewer(URL url) throws IOException {
super("Note Viewer");
setSize(900, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JEditorPane notes = new JEditorPane(url);
notes.setEditable(false);
// notes.setFocusable(false);
getContentPane().add(new JScrollPane(notes), BorderLayout.CENTER);
JButton close = new JButton("Close");
close.addActionListener(EventHandler.create(ActionListener.class, this, "dispose"));
Box box = Box.createHorizontalBox();
box.add(Box.createHorizontalGlue());
box.add(close);
getContentPane().add(box, BorderLayout.PAGE_END);
getRootPane().setDefaultButton(close);
}
}
Uncomment the notes.setFocusable(false) line to see the different behavior.
I would like the JEditorPane to process the navigation keystrokes (such as Page Up/Down), but ignore (not consume) the "editing" keystrokes, such as Enter, so that the Root Pane will invoke the default button.
After much hacking and single-stepping, I've got the behaviour I'm looking for with this code:
notes.getInputMap().put(
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
"pressed");
but I am concerned that it is rather fragile. Do all platforms use VK_ENTER to invoke the default button? Do all platforms use "pressed" as the command-string to invoke the default button?
Finally, it is going about it the wrong way: instead of the JEditorPane ignoring the Enter key and letting the processing happen in an ancestor, this is the JEditorPane explicitly handling the enter key, which strikes me as wrong.
A non-editable JEditorPane should not capture all the editing keystrokes (A-Z, 0-9, Enter, Delete, etc.) and transform them into a warning beep, but rather leave them unhandled so that parent components get a chance. How can this be achieved in a general, non keystroke-by-keystroke input map fashion?
Do all platforms use "pressed" as the command-string to invoke the default button?
That is not what is happening.
You are mapping the Enter key to the "pressed" Action of the JEditorPane. However, there is no "pressed" Action so the Binding is ignored and the event is passed up to the root pane where the Enter key binding for the default button is used.
Normally "none" is used to indicate you want to ignore/remove the binding. Check out the section from the Swing tutorial on How to Remove Bindings for more information.
So I would say you solution is correct and should work on all platforms.
You may want to check out Key Bindings for a programs that displays all the key bindings for each component. You will see that there is no "pressed" action. JEditorPane actually uses "insert-break" to map to the Action.
A non-editable JEditorPane should not capture all the editing keystrokes (A-Z, 0-9, Enter, Delete, etc.) and transform them into a warning beep,
I don't have a "beeping" problem with a-z, 0-9. I do have a problem with the delete and backspace keys.
I'm using JDK8_45 on Windows 7.
Maybe you can prevent the dispatching of keys by using a KeyEventDispatcher. Maybe you check the source of the KeyEvent and if the source is the editor pane you only let the Enter key through? Might also need to allow the PageUp/PageDown events so scrolling will work.
Check out Global Event Dispatching for more information.
I think I just found a better way: set the JEditorPane as not editable and not focusable, and the JScrollPane as focusable.
JEditorPane notes = new JEditorPane(url);
notes.setEditable(false);
notes.setFocusable(false);
JScrollPane scroller = new JScrollPane(notes);
scroller.setFocusable(true);
getContentPane().add(scroller, BorderLayout.CENTER);
The Enter key is forwarded to the default button. Backspace, delete and friends don't generate any beeps.
Edit:
Doesn't allow selecting and copying of any text, so perhaps not the best solution.
As far as i have seen the event:
(1) private void jTabbedPane1StateChanged(javax.swing.event.ChangeEvent evt) {}
Checks whether a new tab is added or an exiting tab is deleted or not.
On googling , i found this code:
(2) ChangeListener changeListener = new ChangeListener() {
public void stateChanged(ChangeEvent changeEvent) {
// my code
}
};
jTabbedPane1.addChangeListener(changeListener);
I guess since it uses stateChanged event , it should do what the same a my first code.
By t way even after using both the codes i could not get the required resuts(ie An event that could be invoked when user changes the tab).
Can anyone suggest me a good event [i am using netbeans GUI environment] for effective action. (I dont want any mouseEvents)
Edit:
I want the following code to be excecuted if the tab changes:
String send3=( jTabbedPane1.getSelectedComponent().getComponentAt(0,0)).getName();
The above code dynamically gets the name of jTextarea (in the current tab) which is created dynamically in the jTabbedPanel.
I just checked my own source code where addChangeListener() works fine. The event is fired whenever the tab is changed by the user or programatically. In stateChanged() itself, the now selected tab is determined by
JTabbedPane p = (JTabbedPane)e.getSource();
int idx = p.getSelectedIndex();
In my UI i have 2 text field and and 2 buttons .I am using jface data binding to bind the text field and i am doing the validation and depending on the validation success the model is updated other wise it will not.I want my button to respond accordingly .Like if my model is not updated than i want to disable my button.One more thing that i do anot want to do hard coding .so is there any way to that without hard coding.
In other way I want to bind a button to text field so that when the text field has some unwanted value than the button should be disabled .In the other way i am doing data binding on text field which will take care when the text field does not have proper value than it will not update its model.Then i want to disable the button when the value is not proper can i do that.Any pointer on this helps me a lot.
You can make use of below listener. Add listener to your Observable
org.eclipse.core.databinding.observable.value.IValueChangeListener
After some research, I found that I have to observe the enable/disable property of the button and bind it with the current emf databinding context. Detail of the function which I have used is given below:
void bindEnablementButtonToValidationStatus(Button button, EMFDataBindingContext ctx) {
IObservableValue buttonEnable = SWTObservables.observeEnabled(button);
IObservableValue validationStatus = new AggregateValidationStatus(
ctx.getValidationRealm(),
ctx.getBindings(),
AggregateValidationStatus.MAX_SEVERITY);
ctx.bindValue(buttonEnable, validationStatus,
new EMFUpdateValueStrategy(
UpdateValueStrategy.POLICY_NEVER),
new EMFUpdateValueStrategy().setConverter(
new Converter(IStatus.class, Boolean.TYPE) {
public Object convert(Object fromObject) {
return new Boolean(((IStatus)fromObject).isOK());
}
}));
}
I am using JFileChooser as part of an export feature. I would like for the user to be able to either select a file from JFileChooser's file viewer or enter the name of a file in the filename text box. From what I've read it's possible to get that value using the getSelectedFile() method, so I have some listeners that call getSelectedFile() and attempt to do some checks before executing the export.
The problem I'm encountering is that the getSelectedFile() method is returning null when I enter the name into the filename text box manually. To add more confusion, the getSelectedFile() method does work in three different situations:
I populate it via setSelectedFile() (a user has clicked a value from a table and I use setSelectedFile())
I click an existing file in the file viewer
I hit ENTER after populating the filename text box
I have three file filters but have had the same behavior regardless of if they are enabled or not.
Listeners that call getSelectedFile() are as follows:
Event Listener for keyReleased
Event Listener for mousePressed.
PropertyChangeEvent listener on my jFileChooser
Action Listener on my jFileChooser
Is there a better way to listen to my jFileChooser to get the user input? I feel like I'm missing something very obvious ... any help is appreciated!
edit
A little more info ...
I have a JFileChooser component in a JSplitPane, which is in a JFrame. I'm not calling showOpenDialog to get input from the user. The component is accessible as part of the form.
What I would like to do is listen to the user input as he/she types. I have a 'start export' button that I would like to leave disabled until the user has entered a valid filename in the filename textbox in the JFileChooser component. To accomplish this I have a KeyEvent listener that I would like to use to get the filename as the user types it in.
further edit
Here is the action listener code:
jFileChooserExport.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jFileChooserExportActionPerformed(evt);
}
});
I also have a property change listener here:
jFileChooserExport.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
public void propertyChange(java.beans.PropertyChangeEvent evt) {
jFileChooserExportPropertyChange(evt);
}
});
Inside of both jFileChooserExportPropertyChange and jFileChooserExportActionPerformed I am trying to get the file the user has selected by invoking getSelectedFile(). In both cases, however, it remains null until the user does one of the three methods described above
Read the section from the Swing tutorial on How to Use File Choosers. The demo code there works fine for me.
Since none of below seems to work, you might want to try to add a PropertyChangeListener to your JFileChooser, listening for the SELECTED_FILE_CHANGED_PROPERTY
What might be possibly happening is that your file chooser may have multi selection enabled, in which case getSelectedFile will return null, but getSelectedFiles will return an array containing the selected file(s). You may either want to disable multi selection, or use the array (If you want the user to only select one file, set multiSelectionEnabled to false).
Another possibility, though, is if you try to get the selected file but fileChooser.showOpenDialog or fileChooser.showSaveDialog were neither called yet or did not return JFileChooser.APPROVE_OPTION
Also, I believe JFileChooser is case-sensitive, so if the file name is "Foo.bar" and you enter "FoO.bar", it will think you want something else.
Greetings to Swing Pros, here's a good (I hope) question for you.
The below are the task requirements and possible solutions I see. I would like someone having had such a hardcore experience to share some thoughts about this.
This does not require coding or anything like that, I just need general advice as to which approach is more reliable regarding the fact I need to work with private symbols which reside in sun.swing and/or javax.swing.plaf packages.
The task is to modify/alter JFileChooser behaviour (just a little bit, actually).
when the user presses enter in the file name JTextField, and the field contains a path to a dir, don't "select" the dir, but switch to it instead. Yes, the dialog is configured to accept directories, but we need to accept only clicks on the "Open" button, and (possibly) double-clicks in the file listing table.
prevent user from selecting a dir/file with more than 1GB data via hitting enter in the file name text field
Here're couple of general solution options:
a. listen on the property-based changes that JFileChooser provides (which AFAICS are triggered after-the-fact and won't provide the degree of control we need here).
b. tinker with the javax.swing.plaf.basic.BasicFileChooserUI (via refrection, breaking the private-level encapsulation) and alter the reference to
private Action approveSelectionAction = new ApproveSelectionAction();
so that our custom action does the extra checks for 1 and 2. This approach links with plaf package and may fail in case this action is somehow overridden in some class below this UI class.
c. traverse the JFileChooser component hierarchy, find the JTextField (which apparently should occur only once in the component tree), decorate all the action listeners hanging on that JTextField with our custom checks. My debugging session shows that this JTextField is some anonymous subclass of JTextField living in the sun.swing.FilePane.
This approach seems to be more OO-friendly, but there's a chance that for some OS this text field is absent, or some other JTextField is also present in the hierarchy.
Well, it seems that public JFileChooser API would not suffice to achieve that behaviour, while the other two options are either deep magic or unportable (long-term), or even both.
So, the question is: which approach would you choose and why?
Regarding option2, you don't need to use reflection to customize the accept Action. You can just override the approveSelection() method. Something like:
JFileChooser chooser = new JFileChooser( new File(".") )
{
public void approveSelection()
{
if (getSelectedFile().exists())
{
System.out.println("duplicate");
return;
}
else
super.approveSelection();
}
};
I recently encountered the same requirement, i.e., pressing Enter in the JTextField of a JFileChooser should cause the displayed dialog to traverse a directory instead of returning from the dialog. Only clicking on the Open button should cause the final selection.
The solution was fairly simple (at least for my application) and has two components to it (Pardon the messed up formatting. I'm new to this forum and I'm not sure why the code is not displaying correctly).
1 - Register an AWTListener to keep track of the last event type generated by the user
class MyChooser extends JFileChooser implements java.awt.AWTEventListener {
...
MyChooser(){
Toolkit.getDefaultToolkit().addAWTEventListener(this,
AWTEvent.MOUSE_EVENT_MASK + AWTEvent.KEY_EVENT_MASK);
...
}
int lastEventId;
public void eventDispatched(AWTEvent e) {
lastEventId=e.getID();
}
}
2 - Override the approveSelection() method of JFileChooser and check whether the approval request is a result of a mouse event (likely caused by the user clicking on the Open button) or a key event caused by the user pressing Enter. The 'lastEventId' variable provides access to this information. My own approveSelection then looks as follows:
public void approveSelection() {
File f=getSelectedFile();
if (f.exists() && isTraversable(f) && lastEventId ==
KeyEvent.KEY_PRESSED) {
setCurrentDirectory(f);
return;
}
super.approveSelection(); }