How To Use JButton "If pressed and if released" - java

Im looking to use JButton in substitute of my Keylistener. Key listener has methods such as if pressed if released etc. Im looking to do the same thing with this JButton, Exp: If user clicks with mouse and holds mouse in clicked position code will execute until s/he releases the buttoning which execution of the code will cease.
What I tried? I tried to use JButton at first which didn't produce the result I wanted because form my understanding JButton requires a full "click" I have been playing with JToggleButton
if (JToggButton.getModel().isPressed()) which is still not working, can someone please point me in the right direction to produce the desired result?
SPECIFIC GOAL:
I want to use the a microphone method I built, I will click the Button that says Microphone and I will hold down the click until I'm ready to finish speaking into the Mic, think of Facebook how you hold down the mic with your thumb and when you release it the voice recording stops, so there would be 2 methods startLogic(); when pressed down and held and stopLogic(); when finally released when user is done speaking

Note that a simple but wrong solution is to use a MouseListener, wrong since this listener does not respond to button depression but rather mouse press, and this will miss button press if it is pressed by any means other than the mouse, such as the spacebar.
I would listen to the button's ButtonModel with a ChangeListener and respond to changes in its isPressed() state. This will work no matter what presses the button, be it the mouse or the spacebar. For example:
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
#SuppressWarnings("serial")
public class ButtonPressTest extends JPanel {
private JButton button = new JButton("Button");
private JTextArea textArea = new JTextArea(15, 15);
public ButtonPressTest() {
button.getModel().addChangeListener(new BtnModelListener());
textArea.setFocusable(false);
add(button);
add(new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
}
private class BtnModelListener implements ChangeListener {
private boolean pressed = false; // holds the last pressed state of the button
#Override
public void stateChanged(ChangeEvent e) {
ButtonModel model = (ButtonModel) e.getSource();
// if the current state differs from the previous state
if (model.isPressed() != pressed) {
String text = "Button pressed: " + model.isPressed() + "\n";
textArea.append(text);
pressed = model.isPressed();
}
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("ButtonPressTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ButtonPressTest());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Related

Enable only mouse event over a jbutton - Disable keyboard event for jbutton

I have a problem.
I created a game. When I open it I must press ENTER to start the game (just enter).
Now I upgraded the game with one button named "EXIT GAME". I don't know why my enter key doesn't work anymore because of this button. If i remove it then Ican press enter again and play the game.
I must set only click pressed event to that button or something like this? Please help me.
public class LeftPanel extends JPanel implements ActionListener {
JButton ExitGame;
public LeftPanel(Tetris tetris) {
this.tetris = tetris;
setPreferredSize(new Dimension(400, 480));
setBackground(Color.getHSBColor(17f, 0.87f, 0.52f));
add(new JButton("Exit Game"));
{
ExitGame.addActionListener(this);
}
}
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
Problem 1 - The JButton is the only focusable component within your UI. Therefore, when you start you program, it gains default focucs. While it has default focus. It will consume the Enter key strokes.
Problem 2 - JPanel is not focusable, meaning it can never receive key board focus. From your description, I would assume you are using a KeyListener, which leads to
Problem 3 - Using KeyListener...KeyListener will only respond to key events when the component it is registered to is focusable and has focus. You can over come this by using Key Bindings.
...Solutions...
Use JLabel instead of JButton. This will require you to register a MouseListener to the label in order to recieve notification of the mouse clicks, but it won't respond to key events...
Better still, add a "Start" button as well...
You can try:
public class LeftPanel extends JPanel implements ActionListener {
public LeftPanel(Tetris tetris) {
this.tetris = tetris;
setPreferredSize(new Dimension(400, 480));
setBackground(Color.getHSBColor(17f, 0.87f, 0.52f));
JButton ExitGame = new JButton("Exit Game");
ExitGame.addActionListener(this);
ExitGame.setActionCommand("Exit");
add(ExitGame );
}
public void actionPerformed(ActionEvent e) {
if("Exit".equals(e.getActionCommand())
System.exit(0);
}
}
This line looks like a syntax error:
add(new JButton("Exit Game"));
{
ExitGame.addActionListener(this);
}
I think it should be something like this:
ExitGame= new JButton("Exit");
this.add(ExitGame);
ExitGame.addActionListener(this);
I haven't tested this, but I think with some tweaking you should be able to get it to do what you want it to. I hope that works!
-Frank
public void actionPerformed(ActionEvent e) {
if("Exit".equals(e.getActionCommand())
System.exit(0);
}
As ActionlListener can be triggered by both Mouse and Keyboard, but now user only want to response mouse event, so change the action listener to mouselistener. Tested and passed.
public class LeftPanel extends JPanel implements ActionListener {
JButton ExitGame;
public LeftPanel(Tetris tetris) {
this.tetris = tetris;
setPreferredSize(new Dimension(400, 480));
setBackground(Color.getHSBColor(17f, 0.87f, 0.52f));
ExitGame= new JButton("Exit Game")
add(ExitGame);
ExitGame.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
System.exit(0);
}
});
}
}

Take input from mouse and keyboard at the same time in Java GUI

I need to make the GUI in java respond to mouse and keyboard input simultaneously.. I know I should add something to the loop in the action listener .. but did not find the right idea .. any suggestions please??
I need to make my GUI respond to the mouse motion and clicks and at the same time respond to the keyboard button pressed if mouse is over a button and pressed enter .. the GUI will respond to the keyboard and the mouse motion actions will continue normally !! .. Hope the problem is cleared!
You do not have to "add something in loop". You just have to add MouseListener and KeyListener to your GUI element (e.g. Frame) and implement the callback methods as you want.
Take a look, at Toolkit.addAWTEventLstener
This will allow you monitor all the events flowing the event queue.
The problem your going to have is identifying the components that are in the area of effect and overcoming the default behaviour of the components (pressing enter while a text field has focus will trigger a action event on it, but now you want to do something else)
To get the behavior of responding to a mouse over the button and enter being pressed I would:
Use Key Bindings attached to the JButton to allow it to respond to the enter key.
Make sure that when doing the above use the InputMap that is associated with the JComponent.WHEN_IN_FOCUSED_WINDOW constant so that the button doesn't actually have to have focus to respond but needs to be in the focused window.
Of course bind to the KeyStroke associated with KeyEvent.VK_ENTER.
In the key bindings action, check if the button's model is in the rollOver state by calling isRollOver() on the model.
and if so, respond.
Note that none of this above requires a MouseListener because I'm using the ButtonModel's isRollOver in place of that.
As an example, my SSCCE:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class MouseKeyResponse extends JPanel {
private JButton button = new JButton("Button");
public MouseKeyResponse() {
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("button clicked");
}
});
add(button);
setUpKeyBindings(button);
}
private void setUpKeyBindings(JComponent component) {
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = component.getInputMap(condition);
ActionMap actionMap = component.getActionMap();
String enter = "enter";
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), enter);
actionMap.put(enter, new EnterAction());
}
private class EnterAction extends AbstractAction {
#Override
public void actionPerformed(ActionEvent evt) {
if (button.isEnabled() && button.getModel().isRollover()) {
System.out.println("Enter pressed while button rolled over");
button.doClick();
}
}
}
private static void createAndShowGui() {
MouseKeyResponse mainPanel = new MouseKeyResponse();
JFrame frame = new JFrame("MouseKeyResponse");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Swing:the role of action listener

# In the problem which i am posting,in this i am unable to understand the code mentioned on line 1 and line 2, As what i know about them is that they are used to set the action listener for the button but the thing which is most confusing for me is that in the syntax sated on the line 1 and line 2 as, {JB1.addActionListener(this)} in this what is the role of "this".....so please tell the basic behind this.And how this whole syntax works...in detail. #
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class frametest1_1 implements ActionListener
{
JLabel JL;
public frametest1_1()
{
//create a JFrame container
JFrame JF=new JFrame("A BUTTON");
//Frame Layout This is contained in Java .awt.*; "ON USING THIS OPTION OUR BUTTON AND OTHER COMPONENT ARE ADJUSTED IN THE FRAME AUTOMATICALLY"
JF.setLayout(new FlowLayout());
//set the size of the container
JF.setSize(200, 200);
//set visible
JF.setVisible(true);
//make button
JButton JB1=new JButton("FIRST");
JButton JB2=new JButton("SECOND");
//add button to the JFrame container
JF.add(JB1);
JF.add(JB2);
//Create and add Label to the JFrame container
JL=new JLabel("PRESS A BUTTON");
JF.add(JL);
//set action command :now this will help in determining that which button is presses, is it FIRST or SECOND
JB1.setActionCommand("one");
JB2.setActionCommand("two");
//The action responded is added to the actionlistener
JB1.addActionListener((ActionListener) this); // line 1
JB2.addActionListener((ActionListener) this); // line 2
}
public void actionPerformed(ActionEvent ae)
{
if(ae.getActionCommand().equals("one"))
JL.setText("First Button Pressed"); // to set text on the label
else
JL.setText("Second button Pressed"); // to set the text on the label
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new frametest1_1();
}
});
}
}
1. Consider that Listener is someone who reacts to some action.
2.ActionListener is an Interface which has a call back method, named actionPerformed, inside which is the code that will run when certain action is done on the controller.
3. This line JB1.addActionListener((ActionListener) this); means as follows
JB1 - Button
ActionListener - Interface
addActionListener - Registering the Button with the Listener.
4. addActionListener will bind/register the Button with the Listener (here its ActionListener).
5. In an MVC architecture Button is the controller, when certain action is done on it, then who all are to be informed to do certain things is done by registering it to the listener.
6. And this Listener will have the callback method which will be overridden by the class that implements the listener.
7. Moreover in your example, you can also do it like this...
JB1.addActionListener(this);
'this' refers to the current instance of the enclosing class (frametest1_1), the instance constructed in the run() method.
Some further reading on 'this':
Using the this Keyword
Provided code is terribly ugly from object-oriented design point of view - hence your confusion. It's definitely bad idea to have one class responsible for:
containing main method
holding references to JFrame components (i.e. JLabel)
implementation of ActionListener concept
thus violating Single responsibility principle, though such ugly examples can be found even in official tutorials on Swing.
Slightly better implementation of exactly the same functionality would be the following:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class frametest1_1 {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
runFrameTest();
}
});
}
public static void runFrameTest() {
//create a JFrame container
JFrame JF=new JFrame("A BUTTON");
//Frame Layout This is contained in Java .awt.*; "ON USING THIS OPTION OUR BUTTON AND OTHER COMPONENT ARE ADJUSTED IN THE FRAME AUTOMATICALLY"
JF.setLayout(new FlowLayout());
//set the size of the container
JF.setSize(200, 200);
//set visible
JF.setVisible(true);
//make button
JButton JB1=new JButton("FIRST");
JButton JB2=new JButton("SECOND");
//add button to the JFrame container
JF.add(JB1);
JF.add(JB2);
//Create and add Label to the JFrame container
final JLabel JL=new JLabel("PRESS A BUTTON");
JF.add(JL);
//set action command :now this will help in determining that which button is presses, is it FIRST or SECOND
JB1.setActionCommand("one");
JB2.setActionCommand("two");
ActionListener labelUpdater = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if(ae.getActionCommand().equals("one"))
JL.setText("First Button Pressed"); // to set text on the label
else
JL.setText("Second button Pressed"); // to set the text on the label
}
};
//The action responded is added to the actionlistener
JB1.addActionListener(labelUpdater); // line 1
JB2.addActionListener(labelUpdater); // line 2
}
}
Hope this helps in understanding ...

Fire a JButton with spacebar, or enter key, or mouse click

I'm trying to get a simple JFrame with a single button to fire an event when any of these events happen:
The Enter key is pressed AND the JButton has focus
The Spacebar is pressed AND the JButton has focus
The JButton is clicked.
It seems that the Enter and Spacebar come "for free" along with the default mouse click using addActionListener on the JButton; trouble is, I've read that the the key bindings are dependent on the Look and Feel used.
I've tried to get universal behavior across LaF by adding Enter and Spacebar to the JButton's action map, and even added a random key ("m") to make sure the ActionMap was doing the work (it was), but now the mouse click is lost. The only way I seem to be able to get all the keys and mouse click is to use both action map and addActionListener.
Is there a way to get these key and mouse bindings to work consistently across all LaF without trying to detect every possible LaF that may come along? Can I register a single action listener that will fire on both key and mouse events?
My favorite solution would be to add a mouse click to the JButton action map and detect which key or mouse click happened inside the inside the action.
I'm still learning the ropes here, so this probably isn't the best or most efficient way to do things; I'm sure it's over-engineered. This is sort of training exercise where I'm experimenting with everything I can get my hands on. Any and all coding style comments are welcome!
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
public class Example extends JFrame {
// ============================
private class BtnListener extends AbstractAction {
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent ae) {
System.out.println("\nclick button listener triggered");
System.out.println(ae.getSource().getClass().toString());
}
} // class BtnListener
private static final int NO_MODIFIER = 0;
private static final boolean ON_KEY_PRESS = false;
private static final KeyStroke ENTER_PRESSED = KeyStroke.getKeyStroke(
KeyEvent.VK_ENTER, NO_MODIFIER, ON_KEY_PRESS);
private static final KeyStroke M_PRESSED = KeyStroke.getKeyStroke(
KeyEvent.VK_M, NO_MODIFIER, ON_KEY_PRESS);
private static final KeyStroke SPACEBAR_PRESSED = KeyStroke.getKeyStroke(
KeyEvent.VK_SPACE, NO_MODIFIER, ON_KEY_PRESS);
private JButton btnButton;
private final AbstractAction btnListener = new BtnListener();
private JPanel buttonPanel;
private JFrame frmMain;
public static void main(String[] args) {
Example ex = new Example();
ex.displayFrame();
}
Action btnActionListener = new AbstractAction() {
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
System.out.println("\nkey button action triggerred");
System.out.println(e.getSource().getClass().toString());
if (e.getSource() instanceof JButton) {
System.out.println("button");
} else {
System.out.println("Something else");
}
}
};
public Example() {
initialize();
}
public void displayFrame() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Throwable e) {
e.printStackTrace();
}
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
frmMain.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void initialize() {
frmMain = new JFrame();
btnButton = new JButton("Abutton");
// Comment this out, you lose the mouse click
btnButton.addActionListener(btnListener);
// Comment out ActionMaps, but keep addActionListner (above), and
// only lose M_PRESSED
InputMap buttonFocusedMap = btnButton
.getInputMap(JComponent.WHEN_FOCUSED);
buttonFocusedMap.put(ENTER_PRESSED, "blah");
btnButton.getActionMap().put("blah", btnActionListener);
buttonFocusedMap.put(SPACEBAR_PRESSED, "blort");
btnButton.getActionMap().put("blort", btnActionListener);
buttonFocusedMap.put(M_PRESSED, "gaaak");
btnButton.getActionMap().put("gaaak", btnActionListener);
// Is there a way to add a mouse click to the ActionMap?
buttonPanel = new JPanel();
buttonPanel.add(btnButton);
frmMain.getContentPane().add(buttonPanel);
frmMain.setBounds(100, 100, 500, 432);
frmMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
BasicButtonListener, used by BasicButtonUI, ensures that all buttons (check, radio, toggle) are bound to Space when focused. This works across platforms, even though individual Look & Feels may render various button model states uniquely. Pressing Space evokes the pressed UIAction, and releasing Space evokes the released UIAction. The same occurs when the mouse is pressed and released within the button's bounds; drag outside the button while pressed to see the armed state change.
In either case, the combination of pressed and released invokes your button's actionPerformed() method.
One convenient way to bind Enter to an Action, irrespective of focus, is via the root pane's setDefaultButton() method. This example illustrates all three ways to click a button.
What you can (and probably should) do is create an AbstractAction. You can use the AbstractAction both for your ActionMap as well as for clicking (do JButton.setAction(...))

Performing action when closing JFrame

In my program I have a main JFrame that holds a button. When this button is clicked a new JFrame appears in which I can change some information. Whenever I finish editing I press a save button on the new JFrame which saves the changes and disposes the JFrame. Now when this is done, I'd like to perform an action in the main JFrame as well, but only if something changed. If I open the new JFrame and just close it again without using the save button, I don't want to do anything in the main frame.
I've tried searching the web for a solution, but just don't seem to be anything useful out there..
An example of the code I've got so far:
Main Frame...
public class MainFrame extends JFrame
{
public MainFrame()
{
super("Main Frame");
JButton details = new JButton("Add Detail");
add(details);
details.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
new DetailFrame().setVisible(true);
}
});
}
}
Detail Frame...
public class DetailFrame extends JFrame
{
public DetailFrame()
{
super("Detail Frame");
JButton save = new JButton("Save");
add(save);
save.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
// Save whatever content
dispose();
}
});
}
}
So when I click the "Save" button on the Detail Frame, I want to do something in the Main Frame, whereas when the "x" is clicked on the Detail Frame, I don't want to do anything..
Hope someone is able to help me, and sorry for my english..
You can pass a MainFrame handle to the DetailFrame constructor. Then, on clicking the Save button, the DetailFrame would call a function in MainFrame and pass the changes to it.
Another way is to create a public boolean variable in DetailFrame and set it to true when the Save button is clicked. This way MainFrame will know whether the DetailFrame was closed or Save'd.
EDIT: Some more ideas:
Use JDialog instead of JFrame. JDialog.setVisible is modal, i.e. it will block the calling function until the dialog is closed; this way you can process the results of the dialog in the same "Details" button listener.
To access the dialog after it is called, store the dialog in a separate variable. First construct the dialog, then show it, and then process the result by analyzing its variables.
Store the results of editing in other public variables of DetailFrame (or let's call it DetailDialog). This should happen only when the "Save" button is clicked. This may even allow to go without the boolean variable (depends on the types of values you are editing).
DetailDialog dlg = new DetailDialog();
dlg.setVisible(true);
if(dlg.approvedResult != null) {
// process the result...
}
EDIT: Sorry, JDialog is not modal by default. Need to call a special super constructor to make it modal.
Also, here you will have to pass the reference to MainFrame to the dialog constructor, but you still can declare it as a simple JFrame and avoid unnecessary dependencies.
To get the reference to the enclosing MainFrame from within the anonymous ActionListener, use MainFrame.this.
To be able to change the button text after it was created, you will have to store the button in a member variable.
Main Frame...
public class MainFrame extends JFrame
{
private JButton details = new JButton("Add Detail");
public MainFrame()
{
super("Main Frame");
getContentPane().add(details);
details.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
DetailDialog dlg = new DetailDialog(MainFrame.this);
dlg.setVisible(true);
if(dlg.approved){
details.setText("Edit Detail");
}
}
});
}
}
Detail Dialog... (not Frame)
public class DetailDialog extends JDialog
{
public boolean approved = false;
public DetailDialog(JFrame parent)
{
super(parent,"Detail Dialog",true); // modal dialog parented to the calling frame
JButton save = new JButton("Save");
getContentPane().add(save);
save.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
// Save whatever content
approved = true;
dispose();
}
});
}
}
Create the detail frame in the main frame, and add a windowlistener to it, using the windowadapter class. Implement the windowclosing event by checking for changes, handle those, and then dispose the detail frame. This is all done in the mainframe.
The detail frame should have do nothing on close set to prevent the detail frame being disposed before you recorded the changes.
You may wish to implement checking for changes in the detailframe as a method returning a class holding the interesting data. That way your windowlistener can be small an to the point.
Forget the 2nd JFrame. use a modal dialog instead. It will block input until dismissed. Once dismissed, the only thing to do is decide whether to update the original data. JOptionPane has some inbuilt functionality that makes that easy. If the user presses Cancel or the esc key, the showInputDialog() method will return null as the result.
import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
class EditInfo {
public static void main(String[] args) {
Runnable r = new Runnable() {
public void run() {
final JFrame f = new JFrame("Uneditable");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new JPanel(new BorderLayout(10,10));
final JTextField tf = new JTextField("Hello World!", 20);
tf.setEnabled(false);
p.add(tf, BorderLayout.CENTER);
JButton edit = new JButton("Edit");
edit.addActionListener( new ActionListener(){
public void actionPerformed(ActionEvent ae) {
String result = JOptionPane.showInputDialog(
f,
"Edit text",
tf.getText());
if (result!=null) {
tf.setText(result);
}
}
} );
p.add(edit, BorderLayout.EAST);
p.setBorder(new EmptyBorder(10,10,10,10));
f.setContentPane(p);
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
If it is necessary to edit a number of fields all at once in the JOptionPane, use a JPanel to contain them all, and put them in a showMessageDialog() call. Check the integer based return result to determine if the user OK'd the changes.

Categories

Resources