KeyEvent not being generated by JFrame java? - java

I have a java program with a JFrame and 3 JButtons in it. I have added a keylistener to jframe. When i run the program a jframe window is opened and the first button is selected by default. My problem is that a KeyEvent is not being generated by this JFrame.
Now, besides adding a KeyListener to the jframe, i also added a KeyListener to the buttons.
Now the keyevent is being generated by the buttons.
How do I make the JFrame generate KeyEvent instead of the JButton generating them ??
Actually, my main purpose is building keyboard shortcuts for the buttons.

Have a look here How to Use Key Bindings.
An alternative to keylistener.
Here is a little Example it has a Button with focus and process a KeyEvent (F2).
On F2-clicked the Key-Binding process a ButtonClick which performed a System.out print.
public class Example {
static public void main( String[] s ) {
EventQueue.invokeLater( new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.getContentPane().setLayout( new BorderLayout() );
frame.setBounds( 50, 50, 600, 600 );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
final JButton button = new JButton( new AbstractAction("MyButton") {
#Override
public void actionPerformed( ActionEvent e ) {
System.out.println("Button Clicked");
}
});
frame.getContentPane().add( button );
frame.getRootPane().setDefaultButton( button );
KeyStroke f2 = KeyStroke.getKeyStroke("F2");
frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(f2, "clickButton");
frame.getRootPane().getActionMap().put("clickButton", new AbstractAction() {
#Override
public void actionPerformed( ActionEvent e ) {
button.doClick();
}
});
frame.setVisible( true );
// the Button has the focus
button.requestFocus();
// generate a KeyEvent 'F2'
KeyboardFocusManager.getCurrentKeyboardFocusManager().dispatchKeyEvent( new KeyEvent( frame, KeyEvent.KEY_PRESSED, 0, f2.getModifiers(), f2.getKeyCode(), f2.getKeyChar() ) );
}
});
}
}

The key event is called on the currently focused component (which is usually not the JFrame)

Related

How can I set a Component focused whenever the JFrame is focused (e.g. by clicking or with Alt+Tab)?

I want to have a JFrame. When it's focused (by clicking on it with the mouse, used with Alt+Tab, or somehow else - like by doing it in the program with it's own methods) a specific Component shall be focused directly.
In my Case it would be the following:
Clicked on JFrame -> JTextField is focused and the user can write in it directly.
Greets, JC
Use a WindowFocusListener and requestFocusInWindow.
myFrame.addWindowFocusListener(new WindowAdapter() {
#Override
public void windowGainedFocus(WindowEvent event) {
someTextField.requestFocusInWindow();
}
});
From https://stackoverflow.com/a/6723316/15093679, you can do:
in = new JTextField(40);
f.addWindowListener( new WindowAdapter() {
public void windowOpened( WindowEvent e ){
in.requestFocus();
}
});
Where f is your JFrame and in is your JTextField.
Hope this works.

Can you put an action listener inside an action listener?

When I press button labeled "one", my popup window freezes up, and I think it's because I'm trying to put a button with an action listener into the action listener of another button. Is that possible?
//code...
one = new JButton("Customize Race");
one.setBounds(30,200,200,75);
one.addActionListener(new ActionListener(){
#Override
public void actionPerformed( ActionEvent e ) {
one.setVisible(false);
Boolean pic = true;
String Player1 = "Player1";
while (pic == true)
{
p1 = new JButton(Player1);
p1.setBounds(50, 50, 200, 100);
p1.addActionListener(new ActionListener(){
#Override
public void actionPerformed( ActionEvent e ) {
// code that will pull up menu to
customize string value of Player1
}
});
next1 = new JButton("Next =>");
next1.setBounds(50, 375, 450, 50);
next1.addActionListener(new ActionListener(){
#Override
public void actionPerformed( ActionEvent e ) {
Boolean pic = false;
}
});
panel.add(p1);
panel.add(next1);
}
p1.setVisible(false);
}
});
panel.add(one);
frame.setVisible(true);
Can you put an action listener inside an action listener?
Yes you can create a component in your ActionListener and add an ActionListener to the new component.
That is not the problem.
my popup window freezes up,
while (pic == true)
The problem is you have a while loop that continues to execute.
Your ActionListener is continually creating components and adding them to the frame and the loop never ends.
Get rid of the while loop!!!
Also, when you add components to a visible frame the code should be:
panel.add(....);
panel.revalidate();
panel.repaint();
The revalidate() invokes the layout manager so the component can be positioned properly and the repaint() just makes sure all the components are repainted.

Maintaining Focus While Not On Top Java

I'm looking to do something which may be impossible; in Java (1.6 running on Windows 7, since this is platform-dependent), I want to have a window appear over another window, but not steal focus from the triggering component. In the example attached below, I'd like to be able to be able to click on the text field, have the new pop up appear in front, but maintain focus on the text field. What I instead notice is that I get the panel to the front, but do not get focus on the text field again.
I'm primarily wondering if this is possible (normally the front Window has focus in Windows, so I'm leaning towards probably not). If not, but someone has opinions on a good workaround, I'm open ears.
Example:
public class PopUpExample
{
// Global toolkit listener.
enum PopUp
{
INSTANCE;
private PopUpWindow m_popUp;
private JTextComponent m_textComponent;
public void initialize(PopUpWindow p)
{
m_popUp = p;
Toolkit.getDefaultToolkit().addAWTEventListener( new AWTEventListener()
{
public void eventDispatched(AWTEvent e)
{
// Ensure event is a focus gain event.
if (( e instanceof FocusEvent )
&& ((FocusEvent)e).getID()==FocusEvent.FOCUS_GAINED)
{
// If it is on a text field, make the pop up appear, but maintain focus on the text field
if ( (e.getSource() instanceof JTextComponent) )
{
m_textComponent = (JTextComponent)e.getSource();
// FIXME Code below here should set the button on top, yet leave the text field with focus.
m_popUp.setAlwaysOnTop( true );
m_popUp.setFocusable( false );
m_popUp.setVisible( true );
m_textComponent.requestFocus();
// end FIXME
}
// Otherwise, make the pop up disappear (if it isn't the pop up itself).
else if (((JComponent)e.getSource()).getRootPane().getComponent(0) instanceof PopUpWindow)
{
m_popUp.setVisible( false );
}
}
}
}, AWTEvent.FOCUS_EVENT_MASK);
}
}
// Pop up window that isn't focusable
class PopUpWindow extends JFrame
{
public PopUpWindow()
{
super();
BorderLayout layout = new BorderLayout();
this.setLayout( layout );
this.setMinimumSize( new Dimension( 100, 100 ) );
JButton button = new JButton("WantOnFront");
button.setFocusable( false );
this.add( button, BorderLayout.CENTER );
this.setFocusable( false );
}
}
// Main application window.
class GuiWindow extends JFrame
{
public GuiWindow()
{
super();
BorderLayout layout = new BorderLayout();
this.setLayout( layout );
this.setMinimumSize( new Dimension( 400, 400 ) );
JButton button = new JButton("defaultFocusButton");
this.add( button, BorderLayout.CENTER );
JTextField textField = new JTextField("WantToMaintainFocusWhenClicked");
this.add( textField, BorderLayout.SOUTH );
}
}
// Setup code
public PopUpExample()
{
new GuiWindow().setVisible( true );
PopUp.INSTANCE.initialize( new PopUpWindow() );
}
public static void main( String[] args )
{
new PopUpExample();
}
}
have the new pop up appear in front, but maintain focus on the text field.
JDialog dialog = new JDialog(...);
dialog.setFocusableWindowState( false );
...
dialog.setVisible( true );

how to know when an action happened in the my program

I write a program in java and used a several components that takes action(actionListener) in my program.
I want to know when any action happened by this component. For example when I clicked the button or a menu item , call a method.
public class ButtonFrame extends JFrame
{
private JButton plainJButton; // button with just text
private JButton fancyJButton; // button with icons
public ButtonFrame()
{
super( "Testing Buttons" );
setLayout( new FlowLayout() ); // set frame layout
plainJButton = new JButton( "Plain Button" );
add( plainJButton );
fancyJButton = new JButton( "Fancy Button");
add( fancyJButton );
// create new ButtonHandler for button event handling
ButtonHandler handler = new ButtonHandler();
fancyJButton.addActionListener( handler );
plainJButton.addActionListener( handler );
}
private class ButtonHandler implements ActionListener
{
public void actionPerformed( ActionEvent event )
{
JOptionPane.showMessageDialog( ButtonFrame.this, String.format(
"You pressed: %s", event.getActionCommand() ) );
}
}
}
Use event.getSource() to differentiate between registered components.
Example -
if(plainJButton == event.getSource()){
// do stuff (e.g. show message dialog, invoke method, and etc.)
}
else if(fancyJButton == event.getSource()){
// do stuff (e.g. show message dialog, invoke method, and etc.)
}
else{
// ut-oh..time to panic!
}
You can use getSource() on the event.

problem with getting JFrame bounds inside a timer in Netbeans

I want to animate a JFrame to become half-size when i press a button in my programme. I think the easiest way is putting the current bounds of JFrame into a timer and decrease bounds 1 by 1 when the timer running.But when I declare a new timer in netbeans IDE it will looks like this.
Timer t = new Timer(5,new ActionListener() {
public void actionPerformed(ActionEvent e) {
//inside this I want to get my Jframe's bounds like this
// int width = this.getWidth();---------here,"this" means the Jframe
}
}
});
But the problem is in here "this" not refering to JFrame.And also I cant even create a new object of my JFrame.Because it will give me another window.Can anyone help me solve this problem ?.
Try
int width = Foo.this.getWidth();
where Foo subclasses JFrame.
I want to animate a JFrame to become half-size when i press a button in my programme
So when you click the button you have access to the button. Then you can use:
SwingUtilities.windowForComponent( theButton );
to get a reference to the frame.
So now when you create the ActionListener for the Timer you can pass in the Window as an argument for the ActionListener.
Edit:
The suggestion by mre is simple and straight forward and easy to use in many cases (and probably the better solution in this case).
My suggestion is a little more complicated but it was introducing you to the SwingUtilities method which will eventually allow you to write more reusable code that could potentially be used by any frame or dialog you might create.
A simple example would be something like:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class AnimationSSCCE extends JPanel
{
public AnimationSSCCE()
{
JButton button = new JButton("Start Animation");
button.addActionListener( new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
JButton button = (JButton)e.getSource();
WindowAnimation wa = new WindowAnimation(
SwingUtilities.windowForComponent(button) );
}
});
add( button );
}
class WindowAnimation implements ActionListener
{
private Window window;
private Timer timer;
public WindowAnimation(Window window)
{
this.window = window;
timer = new Timer(20, this);
timer.start();
}
#Override
public void actionPerformed(ActionEvent e)
{
window.setSize(window.getWidth() - 5, window.getHeight() - 5);
// System.out.println( window.getBounds() );
}
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("AnimationSSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new AnimationSSCCE() );
frame.setSize(500, 400);
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
Of course you would want to stop the timer when the winow reaches a certain minimum size. I'll leave that code up to you.

Categories