I've got a problem with my program what I can't solve. I'm trying for hours and tried to google, etc... I've seen many programs, which is working, but I don't know why my solution does not. My goal (for now) is simple, I want to write to the cmd-line in case of a mouse click or a key press. The first one works, but the second is not. Can anyone tell my why?
import java.awt.EventQueue;
import javax.swing.JFrame;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class test {
private JFrame frame;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
test window = new test();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public test() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.getContentPane().addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
System.out.println("Mouse has clicked!");
}
});
frame.getContentPane().addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent arg0) {
System.out.println("A key has pressed.");
}
});
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Well, finally I had enough time trying to find the solution and now I'm discovered it. I do not know why, but it was not possible to add a keyListener to the JFrame. I could only add for a JButton or a JTextField, etc... This is strange for me, a little bit :c
Related
I wanted to write the code for the timer, but I guess I wrote something wrong or didn’t write it at all.
I searched for the same problem here. Most of the answers were about a right import, but it didn’t help as my import is right, in my opinion
import javax.swing.Timer;
timer = new Timer(delay, new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
update();
repaint();
}
});
ERROR MESSAGE: "The constructor Timer(int, new ActionListener(){}) is undefined."
I would appreciate your help. Thanks in advance!
Review the import statement as below,
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
public class Main {
public static void main(String[] arg) {
int delay =1000;
Timer timer = new Timer(delay , new ActionListener(){
#Override
public void actionPerformed(ActionEvent e)
{
update();
repaint();
}
private void repaint() {
// Do repainttask
}
private void update() {
// Do update task
}
});
}
Once the steps below are taken, the whole application is frozen and the modal dialog cannot be closed.
(This is related to another question but this time we have a reproducible scenario)
The steps:
Open dropdown
Select "Han-Ra" (the last value in the drop down)
After this, trying to resize or close the modal dialog will not succeed. It reproduces 1 out of 3 times (might be easier to reproduce if you do the selection by arrow down but happens with mouse selection also)
This happens on jdk 1.8 (tried 1.8.0_162 and 1.8.0_144) and jdk 10 (10.0.1) but not when using 1.7 (tried 1.7.0_80)
This is just the most obvious case we could find but it randomly (rarely) happens for most modal dialogs.
Anyone else had this problem and found a workaround? We'll report it to Oracle but we'd be more interested in a workaround.
import javax.swing.*;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
public class FreezePleeze {
public static final Object[] ALL_THE_SINGLE_LADIES = {"Rahan", "Crao", "Naouna", "Han-ra"};
public static void main(String[] args) {
new FreezePleeze();
}
public FreezePleeze() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JButton push_me = new JButton("Push me");
JFrame frame = new JFrame("Mmmmm");
JPanel containerPanel = new JPanel();
frame.add(containerPanel);
final JComboBox<Object> comboBox = new JComboBox<>(ALL_THE_SINGLE_LADIES);
containerPanel.add(comboBox);
frame.setSize(300, 300);
comboBox.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JDialog jDialog = new JDialog((JFrame) null, true);
jDialog.add(push_me);
if (comboBox.getSelectedIndex() == ALL_THE_SINGLE_LADIES.length - 1) {
jDialog.setLocationRelativeTo(frame);
jDialog.setSize(300, 300);
jDialog.setVisible(true);
}
}
});
comboBox.addPopupMenuListener(new PopupMenuListener() {
#Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
}
#Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
try {
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_WINDOWS);
robot.keyRelease(KeyEvent.VK_WINDOWS);
} catch (AWTException e1) {
e1.printStackTrace();
}
push_me.setText("Finished counting");
}
#Override
public void popupMenuCanceled(PopupMenuEvent e) {
}
});
frame.setVisible(true);
}
});
}
}
I can reproduce your problem. The solution is to submit the correct window to the constructor of your dialog:
Example:
JDialog jDialog = new JDialog(frame, true);
or, if you have no window instance when you create a dialog:
JDialog jDialog = new JDialog(FocusManager.getCurrentKeyboardFocusManager().getActiveWindow(),
ModalityType.APPLICATION_MODAL);
I have an undecorated JFrame with my own 'header' at the top. It works fine except for telling if the window is out of focus.
I've tried things like
if(!frame.hasFocus()
//Do stuff here
But this obviously won't work when I have other components in the window, such as a JTextField. I haven't found a way to do this so any help is appreciated.
Here is a sample code by which you can implement it:
import java.awt.event.FocusListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class SwingTest {
public static void main(String args[])
{
swing();
}
public static void swing()
{
JFrame g= new JFrame("First");
g.setVisible(true);
g.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
g.setSize(300, 300);
g.setLayout(null);
JLabel l=new JLabel("Times Windows Lost Focus : 0");
l.setBounds(20,10, 200, 60);
g.add(l);
g.addWindowFocusListener( new WindowFocusListener() {
int c=0;
#Override
public void windowLostFocus(WindowEvent e) {
c++;
}
#Override
public void windowGainedFocus(WindowEvent e) {
l.setText("Times Windows Lost Focus :"+c);
//System.out.println(c);
// TODO Auto-generated method stub
}
});;
}
}
Wrting a chat application, I want the user to be able to send images out of his/her clipboard. For this, I would like to catch any CTRL+Vkeyboard input. Since pasting text should be possible as by default, the original ctrl+v-function (pasting text) must not be overridden.
I see can two approaches, of which none works for me:
1st: Taken from the official Java documentation: KEY LISTENER
editorPane.addKeyListener(new KeyListener() {
#Override
public void keyPressed(KeyEvent e) {
e.getKeyChar()
// when I press ctrl+v, ^ this is falsely a white square character, looks like (U+25A1). Plain v without ctrl does work.
e.getKeyCode()
// ^ this is falsely 0
// (e.getModifiersEx() correctly returns InputEvent.CTRL_DOWN_MASK)
}
2nd: KEY BINDING
InputMap iMap = editorPane.getInputMap(condition);
ActionMap aMap = editorPane.getActionMap();
iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK), "ctrlV");
aMap.put("ctrlV", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// works, but overrides natural ctrl+v function!
}
});
Any ideas?
Note: I am using a "foreign" keyboard layout (German). But I can't see why this should make any difference - I would pretty much like to have my application work internationally.
Cheers
edit. Alt+SomeKey however is correctly recognized by the KeyListener
edit2. after changing keyboard layout to US, problem persists.
Stick to Keybindings: KeyListener is a low-level API, while Keybindings will provide you consistent, predictable and robust behaviour.
The solution here is quite easy. You can simply combine the actions yourself by adding a CombinedAction class that will execute the "original" action bound to CTRL+V and the "custom" action you want to execute.
See a small example below combining both actions (here my custom action is a Sysout):
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;
public class TestEditorPane {
private JEditorPane editorPane;
public static class CombinedAction implements ActionListener {
private final ActionListener action1;
private final ActionListener action2;
public CombinedAction(ActionListener action1, ActionListener action2) {
super();
this.action1 = action1;
this.action2 = action2;
}
#Override
public void actionPerformed(ActionEvent e) {
if (action1 != null) {
action1.actionPerformed(e);
}
if (action2 != null) {
action2.actionPerformed(e);
}
}
}
public TestEditorPane() {
}
private void initUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// JTEXTBOX
editorPane = new JEditorPane();
KeyStroke ctrlV = KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.CTRL_DOWN_MASK);
final ActionListener ctrlVAction = editorPane.getActionForKeyStroke(ctrlV);
editorPane.registerKeyboardAction(new CombinedAction(ctrlVAction, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("This is my action on CTRL+V");
}
}), ctrlV, JComponent.WHEN_FOCUSED);
// JSCROLLPANE
JScrollPane scroll1 = new JScrollPane(editorPane);
scroll1.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scroll1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
frame.add(scroll1);
frame.setSize(400, 400);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
TestEditorPane test = new TestEditorPane();
test.initUI();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
I have a JFileChooser in a JFrame. I've added an ActionListener to the JFileChooser so that the "Cancel" button works when clicked. I can also tab to the "Cancel" button, but when I then hit the "Enter" key, nothing happens (i.e., the ActionListener isn't called with the event command JFileChooser.CANCEL_SELECTION). What must I do with the JFileChooser so that hitting the "Enter" key when on the "Cancel" button is equivalent to clicking on the "Cancel" button?
Here's a simple example of the (mis)behavior I'm seeing:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
public final class TestApp {
public static void main(final String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
final JFileChooser chooser = new JFileChooser();
chooser.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
System.exit(0);
}
});
final JFrame frame = new JFrame();
frame.add(chooser);
frame.pack();
frame.setVisible(true);
}
catch (final Throwable t) {
t.printStackTrace();
}
}
});
}
}
To see the (mis)behavior, execute the program, tab to "Cancel", and then hit the "Enter" key. The program doesn't terminate on my platform -- although it does when I click on the "Cancel" button.
Extending JFileChooser and overriding cancelSelection() also doesn't work (apparently, that function isn't called when the "Enter" key is hit while on the "Cancel" button).
The (mis)behavior occurs on my Fedora 10 x86_64 system with Java 5, 6, and 7.
ADDENDUM: The following adds a KeyEventPostProcessor to the current KeyboardFocusManager and appears to do what I want:
import java.awt.Component;
import java.awt.KeyEventPostProcessor;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
public final class TestApp {
public static void main(final String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
final JFileChooser chooser = new JFileChooser();
chooser.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
System.out.println(e.paramString());
System.exit(0);
}
});
final KeyboardFocusManager kfm = KeyboardFocusManager
.getCurrentKeyboardFocusManager();
kfm.addKeyEventPostProcessor(new KeyEventPostProcessor() {
#Override
public boolean postProcessKeyEvent(final KeyEvent e) {
if (e.getID() == KeyEvent.KEY_RELEASED
&& e.getKeyCode() == KeyEvent.VK_ENTER) {
final Component comp = e.getComponent();
if (chooser.isAncestorOf(comp)) {
if (!(comp instanceof JButton)) {
chooser.approveSelection();
}
else {
final JButton button = (JButton) comp;
if ("Cancel".equals(button.getText())) {
chooser.cancelSelection();
}
else {
chooser.approveSelection();
}
}
}
}
return false;
}
});
final JFrame frame = new JFrame();
frame.add(chooser);
frame.pack();
frame.setVisible(true);
}
catch (final Throwable t) {
t.printStackTrace();
}
}
});
}
}
It seems like a lot of work, however, just to be able to distinguish between hitting the enter key on the "Cancel" button versus anywhere else.
Do you see any problems with it?
DISCOVERED SOLUTION: Setting the GUI Look and Feel to the native one for my system (Linux) does what I want without the need for anything else. This is what I was ignorant of and what I was looking for. The solution is to have the following
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
as the first executable statement of the main() method. One can then dispense with all focus listeners, key event processors, etc.
I've awarded the 100 points to the most helpful respondent.
The program doesn't terminate on my platform.
I see normal operation on Mac OS X 10.5, Ubuntu 10 and Windows 7 using (variously) Java 5 and 6. I replaced your exit() with println() to see the event:
System.out.println(rootDirChooser.getSelectedFile().getName() + e.paramString());
It may help to specify your platform and version; if possible, verify correct installation as well.
I'm not sure I understand your goal; but, as an alternative, consider overriding approveSelection():
private static class MyChooser extends JFileChooser {
#Override
public void approveSelection() {
super.approveSelection();
System.out.println(this.getSelectedFile().getName());
}
}
Addendum:
The goal is to have the action of hitting the "Enter" key while on the "Cancel" button be identical to clicking on the "Cancel" button.
As discussed in Key Bindings, you can change the action associated with VK_ENTER.
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
InputMap map = chooser.getInputMap(JFileChooser.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
map.put(enter, "cancelSelection");
If you want the change to occur only while the "Cancel" button has focus, you'll need to do it in a Focus Listener.
Addendum:
I found a solution that uses KeyboadFocusManager, instead. What do you think?
I can see pros & cons each way, so I've outlined both below. Using KeyboadFocusManager finds all buttons, but offers no locale independent way to distinguish among them; the Focus Listener approach can only see the approve button, and it's UI specific. Still, you might combine the approaches for better results. A second opinion wouldn't be out of order.
Addendum:
I've updated the code below to eliminate the need to know the localized name of the "Cancel" button and use key bindings.
import java.awt.EventQueue;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.KeyStroke;
import javax.swing.plaf.metal.MetalFileChooserUI;
public final class FileChooserKeys
implements ActionListener, FocusListener, PropertyChangeListener {
private final JFileChooser chooser = new JFileChooser();
private final MyChooserUI myUI = new MyChooserUI(chooser);
private final KeyStroke enterKey =
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
private void create() {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
chooser.addActionListener(this);
myUI.installUI(chooser);
myUI.getApproveButton(chooser).addFocusListener(this);
KeyboardFocusManager focusManager =
KeyboardFocusManager.getCurrentKeyboardFocusManager();
focusManager.addPropertyChangeListener(this);
frame.add(chooser);
frame.pack();
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(e.paramString());
}
#Override
public void focusGained(FocusEvent e) {
System.out.println("ApproveButton gained focus.");
}
#Override
public void focusLost(FocusEvent e) {
System.out.println("ApproveButton lost focus.");
}
#Override
public void propertyChange(PropertyChangeEvent e) {
Object o = e.getNewValue();
InputMap map = chooser.getInputMap(
JFileChooser.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
if (o instanceof JButton) {
if ("focusOwner".equals(e.getPropertyName())) {
JButton b = (JButton) o;
String s = b.getText();
boolean inApproved = b == myUI.getApproveButton(chooser);
if (!(s == null || "".equals(s) || inApproved)) {
map.put(enterKey, "cancelSelection");
} else {
map.put(enterKey, "approveSelection");
}
}
}
}
private static class MyChooserUI extends MetalFileChooserUI {
public MyChooserUI(JFileChooser b) {
super(b);
}
#Override
protected JButton getApproveButton(JFileChooser fc) {
return super.getApproveButton(fc);
}
}
public static void main(final String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new FileChooserKeys().create();
}
});
}
}