Many jbuttons with the same onkeypress function - java

I have many jbuttons (around 50+) which can be clicked.
After clicking one the program will check for key inputs and set the button text as the pressed key.
Instead of copy pasting 50 codeblocks to each onkeypressed and onclick event of one button i wanted to use a function in each event.
My code so far (reduced):
private JButton attackMoveBtn = new JButton();
private boolean isAlreadyClicked = false;
private void attackMoveBtnKeyPressed(java.awt.event.KeyEvent evt) {
if(attackMoveBtn.getText().equals(Strings.setHotkey)){
isAlreadyClicked = false;
attackMoveBtn.setText(String.valueOf(evt.getKeyChar()));
}
}
private void attackMoveBtnMouseClicked(java.awt.event.MouseEvent evt) {
if(evt.getButton() == 3){
isAlreadyClicked = false;
attackMoveBtn.setText("");
}else{
if(!isAlreadyClicked){
isAlreadyClicked = true;
attackMoveBtn.setText(Strings.setHotkey);
}else{
isAlreadyClicked = false;
attackMoveBtn.setText("Mouse "+evt.getButton());
}
}
}
The only thing that would change for the next button is the JButton itself (attackMoveBtn would become moveBtn for example)
I tried to use String compName = evt.getComponent().getName(); to retrieve the name of the button i pressed but i cannot use "attackMoveBtn".setText() because dynamic var names are not really supported by java.
Is there a way to get which button was pressed? I could then call a function with the buttonObject as a parameter like myOnKeyPressFunction(JButton myButton)
My question would be how i can do dynamic variable names or if my approach is wrong and i should use a different pattern.

"Is there a way to get which button was pressed? I could then call a function with the buttonObject as a parameter like myOnKeyPressFunction(JButton myButton)"
Just use getSource of the event which returns Object and cast JButton to it
JButton button = (JButton)evt.getSource();
myOnKeyPressFunction(button);
Fyi, buttons are to be used with ActionListener to. If you are using the GUI Editor tool, when right click on the button from the design view, select, event->action->actionPerformed and an ActionListener will be added for you.
"i am using netbeans graphic editor to build my gui (i suck at gui programming tbh)"
I strongly suggest you ditch the builder tool and go through some tutorial and learn to hand code first. Go through Creating GUIs with Swing.

If its just JButtons using the ActionListener
public void actionPerformed(ActionEvent e){
JButton temp = (JButton)e.getSource();
//do whatever with temp
}
If you share the ActionListener with other objects
public void actionPerformed(ActionEvent e){
if(e.getSource() instanceof JButton){
JButton temp = (JButton)e.getSource();
//do whatever with temp
}
}

Related

Add KeyListener to Jframe issue

I have a jframe of which I have made in Netbeans, this jframe is being "launched" by another java class, but for the current question that doesn't matter. What matters is the fact that I can't seem to figure out how to add my key listener to this jframe of mine. I have implemented the key listener, added the required functions (key typed, key pressed and key released). But I can't figure out how to actually add/initiate the actual key listener, to make it work.
As of right now I have tried two different things, first I have tried to add the line addKeylistener(new JFrameList()); in the start of the code, where the actual jframe is being initiated, but doing so the actual frame won't even show. Apart from this I have tried to add the same line within another function callJframFForm(), which is called from another class at the same time as the jframe is called. But this just returns the error non-static method addKeyListener(KeyListener) cannot be referenced from a static context. I am not sure what other ways I could add the key listener and thus am looking for a little help.
Currently my code looks like the one below.
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class JFrameList extends javax.swing.JFrame implements KeyListener{
public static String keyPresCod = "";
public JFrameList() {
initComponents();
addKeyListener(new JFrameList()); //This is where I am currently trying to call from, but frame won't show
}
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new JFrameList().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
// End of variables declaration
static void callJframFForm(){
try {
//This is where I have also tried to add the initialization line
} catch(Exception e) {
e.printStackTrace();
}
}
#Override
public void keyTyped(KeyEvent e) {
int codeFKey = e.getKeyCode();
if (codeFKey == KeyEvent.VK_A) {
System.out.println("Button A clicked");
keyPresCod = "A";
} else if (codeFKey == KeyEvent.VK_B) {
System.out.println("Button B clicked");
keyPresCod = "B";
} else {
System.out.println("Different key pressed");
keyPresCod = "Another key";
}
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
}
Problem
addKeyListener(new JFrameList())
This creates a new JFrameList object and uses it's listener. This means any keystrokes are being stored in the new object's member. To see the results, you would have to do
JFrameList list = new JFrameList();
addKeyListener(list);
//use list variable to access keyPressed code
Of course this isn't the behavior you want. You want the keys strokes to be stored in the current instance, not a new object. This means you should be doing
addKeyListener(this)
Although you may notice the listener only works "sometimes", or maybe not at all depending on how you're testing it.
Swing uses a focus system to manage which listeners should be receiving events, and since you are adding the listener to a JFrame, the listener will receive events only when the frame is in focus.
Solution
You should use key bindings rather than a key listener.
If you choose to continue using the listener, you should add it to your buttons, not your frame:
jButton1.addKeyListener(this);
jButton2.addKeyListener(this);
Instead of checking the key code of the event, you could grab the source of the event (your button) by calling event.getSource().
Key bindings allows you to set flexible focus settings for your components. All you need to do is access the input map of the component:
String actionCommand = "Press Button A";
jButton1.setActionCommand(actionCommand);
jButton1.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("A"), actionCommand);
jButton1.getActionMap(actionCommand, this);
Your JFrameList should now implement ActionListener rather than KeyListener, as it will be receiving your events as actions:
class JFrameList extends JFrame implements ActionListener {
private JButton jButton1;
public JFrameList() {
jButton1 = new JButton("A");
//set action command, add to input map, add to action map
}
public void actionPerformed(ActionEvent event) {
JButton button = (JButton) event.getSource();
System.out.println(button.getActionCommand() + " was performed.");
}
}
Alternative
JButton has built-in mnemonic handling. You can specify a mnemonic via JButton#setMnemonic(int), where the argument is a key code:
jButton1.setMnemonic(KeyEvent.VK_A);
This is the standard way of handling hotkeys in graphical interfaces. Simply hold down the Alt key (windows) then press the key you set the mnemonic to.
Key Events are only dispatched to the component with focus. You didn't post the entire code but I'm guessing that focus is on the button that you add to the frame, so the button gets the KeyEvent.
Not sure what you are trying to do with the KeyListener. You can't tell which button was clicked by looking at the character typed in the KeyEvent.
If you want to know what button is clicked then you need to add an ActionListener to each button. Read the section from the Swing tutorial on How to Use Buttons for more information and examples.

Java GUI adding buttons with a for loop

Hi i am making a lotto gui where the user picks 4 numbers from a selection of 28. The way i am currently doing it is as follows
private void no1InputButtonActionPerformed(java.awt.event.ActionEvent evt) {
numberSelectionList.add("1");
}
private void no2InputButtonActionPerformed(java.awt.event.ActionEvent evt) {
chosenNumDisplayLabel.setText(chosenNumDisplayLabel.getText()+" 2");
}
private void no3InputButtonActionPerformed(java.awt.event.ActionEvent evt) {
chosenNumDisplayLabel.setText(chosenNumDisplayLabel.getText()+" 3");
}
etc up through the 28 numbers.
Is there a way to add the actions to each button through a for loop
as this seems more logical?
Also is there a way to add each number picked into an array?
Create a single Action that can be shared by all buttons. The Action will then simply get the text of the button and then do some processing.
Check out setText method with panel and button. This example will show you how to:
create a single ActionListener to be shared by each button
"append" the text to the text field instead of replacing the text
use Key Bindings so the user can also just type the number
On each button you can set an action command:
button.setActionCommand("1");
And you can get the value after that using your ActionEvent:
evt.getActionEvent();
More complete:
ActionListener listener = new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
System.out.println(e.getActionCommand()+" clicked");
}
};
int howMuchYouWant = 32;
for(int i = 0; i<howMuchYouWant; i++)
{
JButton button = new JButton(""+(i+1));
button.setActionCommand(""+i);
button.addActionListener(listener);
//add to whatever gui you want here
}

JRadioButton cannot be cast to JButton in EventListener

I'm having an issue where I get a lot of red lines in my interactions output when I click a JRadioButton in my code. The program is asking the user to select one of four answers to a question "What is your favourite fruit?" Here is an extract from the code:
//constructor
public Form(){
EventListener listener = new EventListener();
private class EventListener implements ActionListener{
public void actionPerformed(ActionEvent e){
if ((JButton)e.getSource() == fruitButton) {
selectA = new JRadioButton("Apples");
selectA.addActionListener(listener);
selectB = new JRadioButton("Bananas");
selectB.addActionListener(listener);
selectC = new JRadioButton("Cherries");
selectC.addActionListener(listener);
selectD = new JRadioButton("Other");
selectD.addActionListener(listener);
if ((JButton)e.getSource() == quitButton) {
System.exit(1);
}
if (selectAButton.isSelected() || selectBButton.isSelected() || selectCButton.isSelected() || selectDButton.isSelected()) {
southPanel.add(submitButton);
}
}}
However, when I run the code whenever I click one of the select JRadioButtons I get lots of red lines in the interactions output, starting with:
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: javax.swing.JRadioButton cannot be cast to javax.swing.JButton
I have JButtons in the same Event Listener (there's a quit button for example) but no matter what I do I cannot seem to get the submit button to add at the bottom once a radio button has been selected. Please help!
Check if the event source is indeed a JButton before you cast it:
if(e.getSource() instanceof JButton && (JButton)e.getSource() == quitButton) {
System.exit(1);
}

Using getSource for actions on components of unknown types

I want to track specific components clicked in a specific order.
I am using getSource and flags like this:
public void actionPerformed(ActionEvent e) {
JButton q = (JButton)e.getSource();
JRadioButton w = (JRadioButton)e.getSource();
if (q.equals(mybutton)) {
if (flag == false) {
System.out.print("test");
flag = true;
}
}
This works perfectly for JButtons, the problem is using it for JRadioButtons as well. If I use getSource on them both, click a button and it will result in an cast exception error since the button can't be cast to a Radiobutton.
How can I work around this problem?
You can use the == to compare references as the references wont change.
if(e.getSource() == radBtn1){
// do something
}
I have used this in the past and it worked like a charm for me.
As for the class cast issue, you need to use instanceof to check to what class the source of the event belongs. If the cause was a JButton and you cast it to JRadioButton blindly, it will result in an exception. You need this:
Object source = e.getSource();
if (source instanceof JButton){
JButton btn = (JButton) source;
} else if (source instanceof JRadioButton){
JRadioButton btn = (JRadioButton) source;
}

JComboBox actions

Is there a way to distinguish between a JComboBox's index being changed programatically using setSelectedBoundValue and by clicking on the JComboBox?
This is ugly and truly a hack, but works!
The ActionEvent contains a field modifiers which in this case is the mouse button id. So using that may help you distinguish between setSelectedIndex or setSelectedValue and mouse clicks (by the way setSelectedBoundValue is not a method on JComboBox):
box.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getModifiers() != 0) {
// ~ mouse button pressed ;)
}
}
});
setSelectedBoundValue
Never heard of that method?
Is there a way to distinguish between a JComboBox's index being changed programatically
Not really. You can remove the listener:
comboBox.removeActionListener(...);
comboBox.setSelectedItem(...);
comboBox.addActionListener(...);
You can set your own class variable.
manualSelection = true;
comboBox.setSelectedIndex(...);
manualSelection = false;

Categories

Resources