Change mnemonic modifier key in Java/Swing - java

Setting focus hot keys in Swing is very easy:
tfldPlantsNeeded = new JTextField( FIELD_LEN_MED );
lblPlantsNeeded = new JLabel( "Plants Needed" );
lblPlantsNeeded.setDisplayedMnemonic( 'p' );
lblPlantsNeeded.setLabelFor( tfldPlantsNeeded );
This will give focus to the tfldPlantsNeeded JTextField when the user presses ALT+p. It also highlights/displays the character that will trigger the focus change. (In this case, when ALT is pressed, the 'P' in "Plants" is underlined.)
This is great ... well, kinda. On a Mac, when the user presses ALT (which is also Option on the Mac keyboard) the mnemonic is highlited, but the focus change isn't triggered when p is pressed too. If, however, the user presses Control + Option + p, then it works as "expected" and focus is changed. (As an aside, if the user DOES press Option + p, the currently focused text field will get funny characters inserted.)
I know that I can do this myself by specifying custom keybindings via getInputMap and getActionMap, but is there a way to change the application global mnemonic modifier so that we can use the automatic keybindings and trigger character highlighting? (In my case, I would like to use Command or Meta as the mnemonic modifer key.)

Apparently this isn't as straightforward as you might think, but there is a way.
First of all, for menus (JMenu) there is a property which is controlled by the look and feel called Menu.shortcutKeyswhich you can set manually. This sets the mnemonic modifier for menus in the specific look and feel. If you want more information about this feel free to ask.
In order to set the mnemonic modifier for everything, you need to override the default toolkit (Toolkit). First of all, run a main method to find what it is with the following lines
System.out.println(System.getProperty("java.awt.headless"));
System.out.println(System.getProperty("awt.toolkit"));
If the first line is null of false (see java.awt.Toolkit getDefaultToolkit()) then the second line will give you the class name which is used as the default Toolkit for your system. I use Windows and the second line gives the output sun.awt.windows.WToolkit. Now create a class that overrides getFocusAcceleratorKeyMask in your default toolkit. For me it looks like this
public class MyToolkit extends WToolkit {
#Override
public int getFocusAcceleratorKeyMask() {
return InputEvent.CTRL_DOWN_MASK;
}
}
Finally, we have to tell the system to use it. In your application, put the line
System.setProperty("awt.toolkit", "packagename.MyToolkit");
where you need to set the correct package path to your class. Make sure this line is placed before starting any GUI related code, preferably in the first lines of main. This should now set CONTROL as the global mnemonic modifier (or use META_DOWN_MASK if that's what you want. Look at java.awt.event.InputEvent for MASK list.).

Related

Text field validation in JavaFX using marks

I'm using JavaFX for my application's GUI. I want to implement a validation method for all the textfields inside the sign up window. I want to check them all and than, whether they are true or false, I want to use a mark to show the user what field is incorrect. I also want to be able to show a small message box when I hover the mouse pointer over those marks.
Simple way is to create HBox , put TextField,Label in there ,label will be Bound on the textProperty/ or do it with listener
txtField.textProperty().addListener((v, oldValue, newValue) -> {
//code here if valid, set label visible false, else set label visible true(red image crossed or whatever)
});
, when value changes it will check if that is ACCEPTABLE/FAILED state , for instance empty box.States will be changed on property change , use array of your hboxes to check if they are valid or invalid at the time , you can check this based on visibility of Label or internal boolean state value.
For the hover over part , use Tooltip on label.
If you want to go lazyer way , take a look at controlsfx validation it will take care of graphics for you.And its already embedded in its component.Just create validation process
Good beginner reference might be newboston videos so you understand concept.In javafx you gonna use property binding ,listeners etc often , get familiar with them as you cant avoid it.
https://www.youtube.com/watch?v=s8GomyEOA8w
https://www.youtube.com/watch?v=6Zi2L0kHSx4
Since you've given no code I can't give you answer that involves actual coding, because I've got no way of knowing whether or not what I give you will be viable or conflict etc..
In regards to the validation that depends entirely on how your accessing a username/password to compare it to what the user has entered and with out knowing how you're thinking of doing it I cannot give you a good answer.
There are quite a few options to display your red x, you could draw it internally etc..
But the easiest is probably going to be creating an image and importing it to your project, you can set a label next to your JTextField and have the picture set to that lable. Once the user inputs the username/password if either or both are incorrect you could have a method that would set the label to be visible.
The message box is as simple as a tooltip that you could also place on the label which would tell the user that the information they entered is wrong.

How to make only the next line of JTextArea (+JScrollPane) editable

So im creating a server, and that works great, however I am a bit stuck on the GUI. You see, I would like it to look just like Command Prompt, where only the next line is editable, and it does not let you delete any other text. So right now I have:
JTextArea ta = new JTextArea();
JScrollPane sp = new JScrollPane(ta);
Then the frame stuff...
f.setTitle("Server");
f.setBounds(ss.width - 600, 50, 550, 350);
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);//added window listener so closes socket connection first
f.setAlwaysOnTop(true);
Then adding it:
f.add(sc);
jt.setBackground(Color.BLACK);
jt.setForeground(Color.WHITE);
//jt.setEditable(false);
Finally, the method I use to output to the TextArea:
public static void append(String text) {
jt.append(text);
jt.append("\n\n"+System.getProperty("user.name")+" / "+getIp()+" > ");
jt.setCaretPosition(jt.getDocument().getLength());
}
Now I need to assign a String to what the user types into the JTextArea after they press enter:>?
jt.addActionListener(...{
public void ActioEvent(ActionEvent e){
String text = JTextArea.getLines().getLastLine().getText().replace(System.getProperty("user.name")+" / "+getIp()+" > ", "");
}
});
Maybe something like that?
Then I need to have it so that only the part after the ">" is editable?
The way to do this is with a DocumentFilter. This is a fairly obscure and little-used part of Java, and is far from easy to use. However it allows you to insert a DocumentFilter between the UI (where rich text content is edited) and the underlying model (the content). You pass all the 'insert' and 'remove' operations through the filter, which can either accept, refuse or modify them. You can code the filter to only permit modifications to the command line, and not to the prompt.
As I say, this is a pretty hard piece of coding, and the Document/DocumentFilter structure has a lot of complexity that your particular application doesn't need. However it does provide you with the facilities you need.
There is a tutorial in the standard Java doc pages, but not an advanced one, and very few examples that I know of are out there on the web.
ProtectedTextComponent (thanks camickr) provides an example of how to do something similar.
Use a Collection a JTextField.
Let the user type on a JTextField, and once he presses enter, move the control to the next JTextField while making the above JTextField uneditable and also remove the JScrollPane from it.
Hope this helps.
I also agree that the JTextArea/JTextField approach is the common and simpler approach.
However if you want to complicate your life a little then you can check out Protected Text Component which will do most of the logic for you.
The current implemtation of the ProtectedDocument only allows you to add protection to the Document, not remove it so the first thing you will need to do is add a method to "Clear" all the protect pieces of text. This is easy enough, you just clear the entries in the Map used by the class.
Next you will need to replace the default "Enter" Action used by the JTextPane. You do this by playing with the Key Bindings of the text area. See Key Bindings for some basic information. In your custom Action you would first need to invoke the newly created "clear(...)" method. Then you would add you text to the text area. Finally you would protect all the text but the last "x" number of characters.

Deselect JToggleButton if file exists

as I mentioned in a post before, I'm porting my program to Java, to make it available for Mac OS and Linux users.
At the start of the program, I'd like to check if adb is installed to the system using this code:
private void checkADBExists()
// Checks if adb binaries exist and sets jTogglebutton1 correspondingly...
{
File adb = new File("/usr/bin/adb");
if (!adb.exists())
{
jToggleButton1.isSelected();
} else {
jToggleButton1.isSelected()= false;
}
}
Here's my problem:
If the file doesn't exist, the JToggleButton isn't selected, even though it should be and I get an error deselecting it.
Any help is much appreciated.
Thanks in advance,
Beats
Many of Swing's core components follow a simple getter/setter pattern.
That is, you can "get" a property value and "set" a property value (note, not all getters have a corresponding setter though).
In the case of a boolean property, the convention is to use "is" instead of "get", it just rolls off the tongue better.
So, in your case, all you are doing is getting the value if the selected property, not really what you want to do.
Instead use jToggleButton1.setSelected(true) or jToggleButton1.setSelected(false) based on your needs
You might like to take a look at How to Use Buttons, Check Boxes, and Radio Buttons for some more details
JToggleButton().isSelected() return a value not a variable. By JToggleButton().isSelected() = false, you are trying to assign a value to a value, it doesn't make sense, much like writing a statement 2 = 2;. use JToggleButton.setSelected(true) to set the toggle button as selected and JToggleButton.setSelected(false) to deselect.

How does one know what are the valid commands in Swing's getActionCommand()?

How to know which commands are available? I tried looking up in the Java SDK, but didn't find a thing about it.
The only way I can think of is this way
class ButtonListener implements ActionListener {
ButtonListener() {
}
public void actionPerformed(ActionEvent e) {
System.out.println(e.getActionCommand());
}
}
but I guess those values must be hardcoded in some part of the framework. Where can I find them?
Thanks
EDIT
Take as example the following code taken from here:
public void actionPerformed(ActionEvent e) {
if ("disable".equals(e.getActionCommand())) {
...
}
...
}
The site's author knew there was an action command that was "disable". Where did he get that information from?
You may be thinking of the Action interface, named instances of which are used to establish default key bindings in various L&Fs. The article Key Bindings includes a convenient utility to examine them.
Addendum: As a concrete example, the JButton in ClickCount takes its name and action command from the nested ClickHandler because the hideActionText property of Action is false by default. As another example, Key Bindings shows that buttons have a named action for "pressed" and "released" that is created by createButtonListener() in BasicButtonUI. BasicButtonListener in turn uses a nested UIAction to handle the two commands, as shown here.
You do it by using setActionCommand()
JButton jb = new JButton("MyButton");
jb.setActionCommand("MyButtonCommand");
EDIT:
The site's author got "disable" from this line of code
b1.setActionCommand("disable");
It's whatever you set.
http://download.oracle.com/javase/1.4.2/docs/api/java/awt/Button.html#setActionCommand%28java.lang.String%29
My guess is the default is the name of the button.
Your edit:
It could have come from two places.
It was the name of the button (new JButton("disable")), which by default is the action command.
It was the command given by setActionCommand("disable")
It is very important to illustrate that by design it doesn't matter what the source was. We don't care if it's a button, drop down, menu, or anything. All that matters is the "disable" command was given. It's the command pattern. :-)
There are no 'valid' commands. The command is intended for use by your application and has no effect on how the button is handled by Swing.
In the second code example you posted it is being setin the code at the following line
b1.setActionCommand("disable");
For buttons the default is to use the text of the button, if the action command is not set

How can I create an AutoComplete popup in a JTextPane in Java?

I am creating a SQL editor. I am using JTextPane for the editor. I want to implement AutoCompletion for table name etc. like Eclipse.
I think the appropriate class for displaying info on top of another component is JPopupMenu, which already handles layering correctly to display itself. JPopupMenu has a show() method that takes its 'parent' component as an argument, and it will show itself in that component's coordinate space. Since you want to display a selection of terms for the user to choose from, a menu seems appropriate.
To check for text changes, you'd add a DocumentListener to the document that's wrapped by the JTextPane; you can access it using getDocument().
To find out where the cursor (actually, the caret) is, you can use getCaretPosition(). That returns the caret's position within the text stream as an int. You can use modelToView() to translate that position to actual (x,y) coordinates. That in turn will tell you where to show your menu.
You can use addKeyListener() to catch keyboard events on your JTextPane, like hitting Ctrl-Space.
The combination of all that should allow you to do what you're looking to do.
You can also use http://fifesoft.com/autocomplete/. You can install it on any JTextComponent.
For things like this you probably should consider layered panes so your auto-complete suggestions appear in the correct place and z-order.
Furthermore you will have to look for changes in the JTextPane to know when the user is typing and you will need a parser that understands what is typed so you can offer the feature only at appropriate points.
It's not quite clear what exactly your problem is and what you got so far.
I achieved this by adding a key listener to the JTextPane and checking for CTRL + Space keystrokes. When the appropriate key combo was detected the listener went off and looked up the list of possible matches based on the characters directly to the left of the cursor at the time of the key press and found the best matches and displayed them to the user in a JPopup. If there was an exact match then it simply replaced the partial text with the match. If no matches were found an option was given to the user to add the text that they had already typed, edit it and record it into the list of acceptable data.
We use jide. They have a lot of components that help you do this kind of thing really easily

Categories

Resources