Get key combinations - java

How can I get key combination of keys on keyboard E.G. (Ctrl+somekey, Alt+somekey) with Java?
I use KeyEvent listener, MouseEvent listener for all keys on keyboard. I can catch all key event on keyboard by using that listener. But, I cannot catch key combination such as (Ctrl+Alt+Del)....etc.

public void keyPressed(KeyEvent kevt) {
if(kevt.getKeyChar()=='c') {
if(kevt.isAltDown())
//Code if Alt+c pressed
if(kevt.isControlDown())
//Code if Ctrl+c pressed
if(kevt.isShiftDown())
//Code if Shift+c pressed
if(kevt.isAltDown()&&kevt.isControlDown()&&(!kevt.isShiftDown()))
//Code if Alt+Ctrl+c pressed
if(kevt.isAltDown()&&kevt.isShiftDown()&&(!kevt.isControlDown()))
//Code if Alt+Shift+c pressed
if(!(kevt.isAltDown())&&kevt.isControlDown()&&(kevt.isShiftDown()))
//Code if Shift+Ctrl+c pressed
if(kevt.isAltDown()&&kevt.isControlDown()&&kevt.isShiftDown())
//Code if Alt+Ctrl+Shift+c pressed
}
Use the above code, use any character
If you want to check if Alt+C+E is pressed do the following
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.swing.*;
public class Sample implements KeyListener {
private JTextField lbl=new JLabel("Hello");
private JPanel pnl=new JPanel(new BorderLayout());
private JFrame frm=new JFrame ("Sample");
int []arr;int i=0;
public Sample() {
pnl.add("North", lbl);
frm.setContentPane(pnl);
frm.pack();
frm.setVisible(true);
lbl.addKeyListener(this);
arr= new int[3];
public void keyPressed(KeyEvent key) {
arr[i]=key.getKeyCode();
i++;
if((arr[0]==VK_ALT||arr[1]==VK_ALT||arr[2]==VK_ALT)&& (arr[0]==VK_C||arr[1]==VK_C||arr[2]==VK_C)&&(arr[0]==VK_E||arr[1]==VK_E||arr[2]==VK_E)) {
//Code you want
}
}
public void keyReleased(KeyEvent evt) {
arr[i]=null;
}
public void keyTyped(KeyEvent kvt) {
}
}
}

Many of these answers seem very complicated, just thought I'd add my solution.
I wrote a KeyBinder class:
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Hashtable;
public abstract class KeyBinder implements KeyListener
{
private Hashtable<Integer, Boolean> keyMap;
private int[] keyCodes;
public KeyBinder(final int... keyCodes)
{
this.keyMap = new Hashtable<>();
this.keyCodes = keyCodes;
}
#Override
public void keyTyped(final KeyEvent e) { }
#Override
public void keyPressed(final KeyEvent e)
{
getKeyMap().put(e.getKeyCode(), true);
if (getKeysDown())
{
onKeysDown();
}
}
#Override
public void keyReleased(final KeyEvent e)
{
getKeyMap().put(e.getKeyCode(), false);
}
private Hashtable<Integer, Boolean> getKeyMap()
{
return this.keyMap;
}
public boolean getKeysDown()
{
for (final int key : this.keyCodes)
{
if (getKeyMap().containsKey(key))
{
if (!getKeyMap().get(key))
{
return false;
}
} else {
return false;
}
}
return true;
}
public abstract void onKeysDown();
}
And then on my control:
final KeyBinder binder = new KeyBinder(KeyEvent.VK_ALT, KeyEvent.VK_A)
{
#Override
public void onKeysDown()
{
System.out.println("Alt+A");
}
};
startButton.addKeyListener(binder);
Easy :)

#Override
public void keyPressed(KeyEvent evt) {
if (evt.getKeyCode()==KeyEvent.VK_CONTROL) { ctrl = true; }
else if (evt.getKeyCode()==KeyEvent.VK_SHIFT) { shift = true; }
else if (evt.getKeyCode()==KeyEvent.VK_ALT) { alt = true; }
else {
keyHit = KeyEvent.getKeyText( evt.getKeyCode() );
System.out.println("Key Hit is "+keyHit);
}
processLocalKeyEvent(evt);
}
#Override
public void keyReleased(KeyEvent evt) {
if (evt.isControlDown() && keyHit != "") ctrl = true;
if (evt.isAltDown() && keyHit != "") alt = true;
if (evt.isShiftDown() && keyHit != "") shift = true;
if (ctrl) sb.append("Ctrl");
if (shift) sb.append("Shift");
if (alt) sb.append("Alt");
if (!ctrl && !shift && !alt) {
sb.append(keyHit);
} else {
sb.append("_"+keyHit);
}
if (ctrl || shift || alt) {
Thread thread = new Thread();
try {
thread.sleep(300);
rfbProto.capture();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else if ((ctrl || shift || alt) && keyHit=="") {
rfbProto.capture();
} else if ((!ctrl || !shift || !alt) && keyHit!="") {
rfbProto.capture();
}
ctrl = false;
shift = false;
alt = false;
keyHit = "";
sb = new StringBuffer();
processLocalKeyEvent(evt);
}

private void jTable1KeyReleased(java.awt.event.KeyEvent evt) {
System.out.println(evt.getKeyCode()); //showing code of released button
if(evt.isControlDown() && evt.getKeyCode()==40) // 40 is code for arrow down
{
//if ctrl is pressed and arrow down is released
System.out.println("Released " + evt.getKeyCode());
}
Simple version

Related

How can we do undo and redo functionality for a swt texteditor

I have created a swt textbox and trying to do undo and redo functionality but when i press "ctrl+z" the listener itself is not working .so how can we do undo and redo operations.the code to implement undo and redo is as follows
private static class CTabItemControl extends Composite {
private static class UndoRedoStack<T> {
private Stack<T> undo;
private Stack<T> redo;
public UndoRedoStack() {
undo = new Stack<T>();
redo = new Stack<T>();
}
public void pushUndo(T delta) {
undo.add(delta);
}
public void pushRedo(T delta) {
redo.add(delta);
}
public T popUndo() {
T res = undo.pop();
return res;
}
public T popRedo() {
T res = redo.pop();
return res;
}
public T peekUndo() {
T res = undo.peek();
return res;
}
public void clearRedo() {
redo.clear();
}
public void clearUndo() {
undo.clear();
}
public boolean hasUndo() {
return !undo.isEmpty();
}
public boolean hasRedo() {
return !redo.isEmpty();
}
}
//private StyledText editor;
private UndoRedoStack<ExtendedModifyEvent> stack;
private boolean isUndo;
private boolean isRedo;
public CTabItemControl(Composite parentComposite,final CTabItem tabitem){
super(parentComposite, SWT.NONE);
setLayout(new GridLayout(1, false));
editor = new StyledText(this, SWT.MULTI | SWT.V_SCROLL);
editor.setLayoutData(new GridData(GridData.FILL_BOTH));
editor.setFont(new Font(Display.getDefault(),"Cambria", 10, SWT.NORMAL));
editor.addListener(SWT.KeyDown, new Listener(){
public void handleEvent(Event event) {
event.doit = true;
if(!tabitem.getText().contains("*"))
{
tabitem.setText('*'+tabitem.getText());
System.out.println("inserted *");
}
}
});
editor.addExtendedModifyListener(new ExtendedModifyListener(){
//editor.addKeyListener(this);
public void modifyText(ExtendedModifyEvent event) {
if (isUndo) {
stack.pushRedo(event);
} else { // is Redo or a normal user action
stack.pushUndo(event);
if (!isRedo) {
stack.clearRedo();
}
}
}
});
editor.addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
// Listen to CTRL+Z for Undo, to CTRL+Y or CTRL+SHIFT+Z for Redo
boolean isCtrl = (e.stateMask & SWT.CTRL) > 0;
boolean isAlt = (e.stateMask & SWT.ALT) > 0;
if (isCtrl && !isAlt) {
boolean isShift = (e.stateMask & SWT.SHIFT) > 0;
if (!isShift && e.keyCode == 'z') {
{
System.out.println("call undo");
undo();
}
} else if (!isShift && e.keyCode == 'y' || isShift
&& e.keyCode == 'z') {
redo();
}
}
if(e.stateMask == SWT.CTRL && e.keyCode == 'a'){
editor.selectAll();
}
}
public void keyReleased(KeyEvent e) {
// ignore
}
});
//this.editor = editor;
stack = new UndoRedoStack<ExtendedModifyEvent>();
}
private void revertEvent(ExtendedModifyEvent event) {
System.out.println("calling revertevent");
editor.replaceTextRange(event.start, event.length, event.replacedText);
// (causes the modifyText() listener method to be called)
editor.setSelectionRange(event.start, event.replacedText.length());
}
private void undo() {
System.out.println("calling undo");
if (stack.hasUndo()) {
isUndo = true;
revertEvent(stack.popUndo());
isUndo = false;
}
}
private void redo() {
if (stack.hasRedo()) {
isRedo = true;
revertEvent(stack.popRedo());
isRedo = false;
}
}
public void clearUndoRedo() {
stack.clearUndo();
stack.clearRedo();
}
public boolean hasUndo() {
return stack.hasUndo();
}
public String peekUndo() {
return stack.peekUndo().toString();
}
}
When you press Ctrl + Z or Ctrl + Y, you get 2 key events, one for Ctrl and one for another key. So it is better to check for the character of the second event
e.character == 0x1a
for Ctr + Z, and
e.character == 0x19
for Ctrl + Y

Listener inside a loop won't allow to change an outsider boolean flag

Following my previous post here , I wrote a listener :
#Override
public void keyTyped(KeyEvent keyEvent)
{
PolygonFiller polyFiller = new PolygonFiller();
char key = keyEvent.getKeyChar();
final boolean runForever = true;
switch(key)
{
/**
* Fill the polygons
*/
case FILL_POLYGON:
{
if (greenLightForFilling == true)
{
while (runForever)
{
fillPolygon(polyFiller);
KeyListener listener = new KeyListener()
{
public void keyPressed(KeyEvent keyEvent)
{
char keyOther = keyEvent.getKeyChar();
if (keyOther == 'F' || keyOther == 'f')
// can't use break;
runForever = false;
}
#Override
public void keyReleased(KeyEvent arg0) {}
#Override
public void keyTyped(KeyEvent arg0) {}
};
}
}
break;
} // end FILL_POLYGON
case FILL_POLYGON_LOWERCASE:
{
if (greenLightForFilling == true)
{
fillPolygon(polyFiller);
}
break;
}
/**
* save all polygons in a .scn file
*/
case SAVE_POLYGONS :
{
if (greenLightForFilling == true)
{
saveWorkspace();
}
break;
} // end SAVE_POLYGONS
case SAVE_POLYGONS_LOWERCASE:
{
if (greenLightForFilling == true)
{
saveWorkspace();
}
break;
}
/**
* Delete everything & load all polygons from .scn file
*/
case LOAD_POLYGONS:
{
loadWorkspace();
break;
}
case LOAD_POLYGONS_LOWERCASE:
{
loadWorkspace();
break;
}
default: break;
} // end switch
}
The goal :
break from the loop , when I get a second f or F (I already got one f/F when I entered to loop) .
Do I need to attach the second listener to something ?
But I can't change the runForever to false , since it's written outside .
Even if I change it to final , I can't change its value to false either .
Any way around this ?
Note : I already have a key-listener for entering the switch-case!!
EDIT:
// Hot-keys hit by the user - used for keyboard listening
private static final char FILL_POLYGON = 'F';
private static final char SAVE_POLYGONS = 'S';
private static final char LOAD_POLYGONS = 'L';
private static final char FILL_POLYGON_LOWERCASE = 'f';
private static final char SAVE_POLYGONS_LOWERCASE = 's';
private static final char LOAD_POLYGONS_LOWERCASE = 'l';
#Override
public void keyTyped(KeyEvent keyEvent)
{
PolygonFiller polyFiller = new PolygonFiller();
char key = keyEvent.getKeyChar();
final Settable runForever = new Settable();
switch(key)
{
/**
* Fill the polygons
*/
case FILL_POLYGON:
{
if (greenLightForFilling == true)
{
KeyListener listener = new KeyListener()
{
public void keyPressed(KeyEvent keyEvent)
{
char keyOther = keyEvent.getKeyChar();
if (keyOther == 'F' || keyOther == 'f')
runForever.set(false);
}
#Override
public void keyReleased(KeyEvent arg0) {}
#Override
public void keyTyped(KeyEvent arg0) {}
};
this.addKeyListener(listener);
while (runForever.get())
{
fillPolygon(polyFiller);
}
}
break;
} // end FILL_POLYGON
...
}
Final variables cannot be changed, but if they represent a mutable object, you can change the content of that object.
For example, if you make a Settable class, and use its instance instead of boolean, you could do this:
class Settable {
private boolean flag;
public boolean get() {return flag;}
public boolean set(boolean val) { flag = val; }
}
Now, use a final instance of Settable in your code; use set(...) instead of the assignment, and get() instead of a direct access:
final Settable runForever = new Settable();
runForever.set(true);
...
while (runForever.get()) {
...
if (keyOther == 'F' || keyOther == 'f') runForever.set(false);
...
}
please did you read comment by #kleopatra in your previous post, not good idea to ignore that
not never, not wrong direction, use KeyBindings and with Swing Action instead of KeyListener
accepted answer by #dasblinkenlight solved nothing in Swing, Swing and Java2D, use KeyBindings and with Swing Action,
for example
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class FullScreen {
private static final long serialVersionUID = 1L;
private JButton button = new JButton("Close Meeee");
private JPanel myPanel = new JPanel();
private JFrame frame = new JFrame();
public FullScreen() {
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
myPanel = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 300);
}
};
myPanel.setFocusable(true);
myPanel.add(button);
frame.add(myPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.setUndecorated(true);
frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
KeyStroke.getKeyStroke("ENTER"), "clickENTER");
frame.getRootPane().getActionMap().put("clickENTER", updateBol());
frame.pack();
frame.setVisible(true);
updateCol().setEnabled(false);
updateDol().setEnabled(false);
}
private Action updateBol() {
return new AbstractAction("updateBol") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("updateCol is " + updateBol().isEnabled());
System.out.println("updateBol is " + updateCol().isEnabled());
System.out.println("updateDol is " + updateDol().isEnabled());
updateCol().actionPerformed(e);
updateDol().actionPerformed(e);
}
};
}
private Action updateCol() {
return new AbstractAction("updateCol") {
private static final long serialVersionUID = 1L;
private Boolean _enabled = false;
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("updateCol is " + updateCol().isEnabled());
if (updateCol().isEnabled()) {
} else {
}
}
public void setEnabled(Boolean bol) {
_enabled = bol;
}
#Override
public boolean isEnabled() {
return _enabled;
}
};
}
private Action updateDol() {
return new AbstractAction("updateDol") {
private static final long serialVersionUID = 1L;
private Boolean _enabled = false;
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("updateDol is " + updateDol().isEnabled());
if (updateCol().isEnabled()) {
} else {
}
}
public void setEnabled(Boolean bol) {
_enabled = bol;
}
#Override
public boolean isEnabled() {
return _enabled;
}
};
}
public static void main(String[] args) {
Runnable doRun = new Runnable() {
#Override
public void run() {
FullScreen fullScreen = new FullScreen();
}
};
SwingUtilities.invokeLater(doRun);
}
}
You can make final array of boolean of size 1 to store your flag. Even if array is final, it's elements are not, so you can modify array's elements from anonymous classes.

Detect double click in mouseReleased method

I need to use mouseReleased method instead of mouseClicked so i need to find a way to Intercept double click. this is the code:
public void mouseReleased(MouseEvent e)
{
if (e.getClickCount() == 2)
System.out.println ("Double CLICK mouseReleased");
else
{
row= clientTable.rowAtPoint(e.getPoint());
col= clientTable.columnAtPoint(e.getPoint());
clientTable.sel(row, col);
}
}
The problem is that when I double-click I have also a single click event. Can anyone know ho to fix that? Thanks
1. Use the method getClickCount() method of ClassMouseEvent
2. This will help you to get the Type of the click.. Single , Double, Triple, etc..
See here for more details:
http://docs.oracle.com/javase/6/docs/api/java/awt/event/MouseEvent.html
public void mouseClicked(MouseEvent evt) {
if (evt.getButton()==MouseEvent.BUTTON1){
leftClick = true; clickCount = 0;
if(evt.getClickCount() == 2) doubleClick=true;
Integer timerinterval = (Integer)Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval");
timer = new Timer(timerinterval, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if(doubleClick){
System.out.println("double click.");
sb = new StringBuffer();
sb.append("Double Click");
clickCount++;
if(clickCount == 2){
rfbProto.capture();
clickCount=0;
doubleClick = false;
}
} else {
sb = new StringBuffer();
sb.append("Left Mouse");
System.out.println("single click.");
rfbProto.capture();
}
}
});
timer.setRepeats(false);
timer.start();
if(evt.getID()==MouseEvent.MOUSE_RELEASED) timer.stop();
}
}
there is no simpel fix to not have a single click when you double click
i wrote this once but it has a downside, your single click gets abit sluggish
example usage:
JLabel label = new JLabel("test");
label.addMouseListener(new SingleClickInhibitorMouseListener(some other mouselistener));
public class SingleClickInhibitorMouseListener implements MouseListener
{
public static final Integer CLICK_TRESHOLD = (Integer) Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval");
private Collection<MouseListener> mouseListeners = new ArrayList<MouseListener>();
public SingleClickInhibitorMouseListener( MouseListener listener )
{
mouseListeners.add(listener);
}
public void addMouseListener( MouseListener listener )
{
mouseListeners.add(listener);
}
public void removeMouseListener( MouseListener listener )
{
mouseListeners.remove(listener);
}
public void removeAllListeners()
{
mouseListeners.clear();
}
public void mouseSingleClick( MouseEvent e )
{
for (MouseListener mouseListener : mouseListeners)
{
mouseListener.mouseClicked(e);
}
}
public void mouseDoubleClick( MouseEvent e )
{
for (MouseListener mouseListener : mouseListeners)
{
mouseListener.mouseClicked(e);
}
}
public boolean hasDoubleClick = false;
public void mouseClicked( final MouseEvent me )
{
if ( me.getClickCount() == 1 )
{
new Thread(new Runnable()
{
public void run()
{
try
{
Thread.sleep(CLICK_TRESHOLD);
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
if ( hasDoubleClick )
hasDoubleClick = false;
else
mouseSingleClick(me);
}
});
}
catch (InterruptedException e)
{
mouseSingleClick(me);
hasDoubleClick = false;
}
}
}).start();
}
else
{
if ( me.getClickCount() == 2 )
hasDoubleClick = true;
mouseDoubleClick(me);
}
}
public void mousePressed( MouseEvent e )
{
for (MouseListener mouseListener : mouseListeners)
{
mouseListener.mousePressed(e);
}
}
public void mouseReleased( MouseEvent e )
{
for (MouseListener mouseListener : mouseListeners)
{
mouseListener.mouseReleased(e);
}
}
public void mouseEntered( MouseEvent e )
{
for (MouseListener mouseListener : mouseListeners)
{
mouseListener.mouseEntered(e);
}
}
public void mouseExited( MouseEvent e )
{
for (MouseListener mouseListener : mouseListeners)
{
mouseListener.mouseExited(e);
}
}
}

How to show autocomplete as I type in JTextArea?

I need to show suggestions (autocomplete) as the user types in a JTextArea, kind of like cell phone T9.
I don't know how to do this in myTextAreaKeyTyped() event.
This app is a typing helper. It shows variants of characters non-present on the keyboard.
E.G. You press 'A', it shows Â:1, Á:2 ,À:3… 'A' will be replaced if you press 1,2 or 3.
It's already done, but the variants are shown in a JLabel at the bottom of my JFrame, because I don't know how to do this.
Can you please help me out? Thanks in advance.
Here is a snippet to get yourself inspired. You will probably need to reorganize a bit the code to make it more maintainable, but it should give you the gist.
Basically, we listen for key events (I don't find it relevant to listen to document events, for example if the user pastes some text, I don't want the suggestion panel to appear), and when the caret has at least 2 characters behind, we make some suggestions, using a popupmenu containing a JList of suggestions (here suggestions are really not meaningful, but it would not be too hard to bind this to a dictionnary). As for the shortcuts you are mentionning, it should not be too hard to do so.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.BadLocationException;
public class Test {
public class SuggestionPanel {
private JList list;
private JPopupMenu popupMenu;
private String subWord;
private final int insertionPosition;
public SuggestionPanel(JTextArea textarea, int position, String subWord, Point location) {
this.insertionPosition = position;
this.subWord = subWord;
popupMenu = new JPopupMenu();
popupMenu.removeAll();
popupMenu.setOpaque(false);
popupMenu.setBorder(null);
popupMenu.add(list = createSuggestionList(position, subWord), BorderLayout.CENTER);
popupMenu.show(textarea, location.x, textarea.getBaseline(0, 0) + location.y);
}
public void hide() {
popupMenu.setVisible(false);
if (suggestion == this) {
suggestion = null;
}
}
private JList createSuggestionList(final int position, final String subWord) {
Object[] data = new Object[10];
for (int i = 0; i < data.length; i++) {
data[i] = subWord + i;
}
JList list = new JList(data);
list.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setSelectedIndex(0);
list.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
insertSelection();
}
}
});
return list;
}
public boolean insertSelection() {
if (list.getSelectedValue() != null) {
try {
final String selectedSuggestion = ((String) list.getSelectedValue()).substring(subWord.length());
textarea.getDocument().insertString(insertionPosition, selectedSuggestion, null);
return true;
} catch (BadLocationException e1) {
e1.printStackTrace();
}
hideSuggestion();
}
return false;
}
public void moveUp() {
int index = Math.min(list.getSelectedIndex() - 1, 0);
selectIndex(index);
}
public void moveDown() {
int index = Math.min(list.getSelectedIndex() + 1, list.getModel().getSize() - 1);
selectIndex(index);
}
private void selectIndex(int index) {
final int position = textarea.getCaretPosition();
list.setSelectedIndex(index);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
textarea.setCaretPosition(position);
};
});
}
}
private SuggestionPanel suggestion;
private JTextArea textarea;
protected void showSuggestionLater() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
showSuggestion();
}
});
}
protected void showSuggestion() {
hideSuggestion();
final int position = textarea.getCaretPosition();
Point location;
try {
location = textarea.modelToView(position).getLocation();
} catch (BadLocationException e2) {
e2.printStackTrace();
return;
}
String text = textarea.getText();
int start = Math.max(0, position - 1);
while (start > 0) {
if (!Character.isWhitespace(text.charAt(start))) {
start--;
} else {
start++;
break;
}
}
if (start > position) {
return;
}
final String subWord = text.substring(start, position);
if (subWord.length() < 2) {
return;
}
suggestion = new SuggestionPanel(textarea, position, subWord, location);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
textarea.requestFocusInWindow();
}
});
}
private void hideSuggestion() {
if (suggestion != null) {
suggestion.hide();
}
}
protected void initUI() {
final JFrame frame = new JFrame();
frame.setTitle("Test frame on two screens");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new BorderLayout());
textarea = new JTextArea(24, 80);
textarea.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
textarea.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
if (e.getKeyChar() == KeyEvent.VK_ENTER) {
if (suggestion != null) {
if (suggestion.insertSelection()) {
e.consume();
final int position = textarea.getCaretPosition();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
textarea.getDocument().remove(position - 1, 1);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
});
}
}
}
}
#Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_DOWN && suggestion != null) {
suggestion.moveDown();
} else if (e.getKeyCode() == KeyEvent.VK_UP && suggestion != null) {
suggestion.moveUp();
} else if (Character.isLetterOrDigit(e.getKeyChar())) {
showSuggestionLater();
} else if (Character.isWhitespace(e.getKeyChar())) {
hideSuggestion();
}
}
#Override
public void keyPressed(KeyEvent e) {
}
});
panel.add(textarea, BorderLayout.CENTER);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test().initUI();
}
});
}
}

Distinguish between a single click and a double click in Java

I search the forum and see this codes:
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
System.out.println(" and it's a double click!");
wasDoubleClick = true;
} else {
Integer timerinterval = (Integer) Toolkit.getDefaultToolkit().getDesktopProperty(
"awt.multiClickInterval");
timer = new Timer(timerinterval.intValue(), new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (wasDoubleClick) {
wasDoubleClick = false; // reset flag
} else {
System.out.println(" and it's a simple click!");
}
}
});
timer.setRepeats(false);
timer.start();
}
}
but the code runs incorrectly(Sometime it prints out " and it's a single click!" 2 times . It should print out " and it's a double click!"). Can anybody show me why? or can you give me some better ways to do this?
Thank you!
Sometime it prints out " and it's a single click!" 2 times . It should print out " and it's a double click!").
That is normal. A double click only happens if you click twice within the specified time interval. So sometimes if you don't click fast enough you will get two single clicks in a row.
Integer timerinterval = (Integer) Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval");
The above line of code determines how fast the double click must be.
For what its worth here is some code I have used to do the same thing. Don't know if its any better or worse than the code you have:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class ClickListener extends MouseAdapter implements ActionListener
{
private final static int clickInterval = (Integer)Toolkit.getDefaultToolkit().
getDesktopProperty("awt.multiClickInterval");
MouseEvent lastEvent;
Timer timer;
public ClickListener()
{
this(clickInterval);
}
public ClickListener(int delay)
{
timer = new Timer( delay, this);
}
public void mouseClicked (MouseEvent e)
{
if (e.getClickCount() > 2) return;
lastEvent = e;
if (timer.isRunning())
{
timer.stop();
doubleClick( lastEvent );
}
else
{
timer.restart();
}
}
public void actionPerformed(ActionEvent e)
{
timer.stop();
singleClick( lastEvent );
}
public void singleClick(MouseEvent e) {}
public void doubleClick(MouseEvent e) {}
public static void main(String[] args)
{
JFrame frame = new JFrame( "Double Click Test" );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.addMouseListener( new ClickListener()
{
public void singleClick(MouseEvent e)
{
System.out.println("single");
}
public void doubleClick(MouseEvent e)
{
System.out.println("double");
}
});
frame.setSize(200, 200);
frame.setVisible(true);
}
}
public void mouseClicked(MouseEvent evt) {
if (evt.getButton()==MouseEvent.BUTTON1){
leftClick = true; clickCount = 0;
if(evt.getClickCount() == 2) doubleClick=true;
Integer timerinterval = (Integer)Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval");
timer = new Timer(timerinterval, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if(doubleClick){
System.out.println("double click.");
sb = new StringBuffer();
sb.append("Double Click");
clickCount++;
if(clickCount == 2){
clickCount=0;
doubleClick = false;
}
} else {
sb = new StringBuffer();
sb.append("Left Mouse");
System.out.println("single click.");
}
}
});
timer.setRepeats(false);
timer.start();
if(evt.getID()==MouseEvent.MOUSE_RELEASED) timer.stop();
}

Categories