Handle RadioButton events after button clicked - java

help,
my questions are:
why isn't itemStateChanges triggered, I tried to put it in the inner class ButtonHandler and also in RadioButtonHandler Im having trouble with it, what is the right way to do it?
I want to trigger and check the marked JRadioButtons after the user click the "check" button.
What is the right way to check which button was clicked, I feel like comparing the strings is bad programming practise. Maybe using an ID ?
How should I make a "reset" button(start over), I want to uncheck all radio buttons and run the constructor once again.
Thank you for your help !
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
public class ExamFrame extends JFrame {
static ArrayList<Question> qArrList;
JRadioButton a1,a2,a3,a4;
public ExamFrame() {
super("Quiz");
setLayout(new GridLayout(0, 1));
GridBagConstraints gbc = new GridBagConstraints();
Exam exam = new Exam();
qArrList = exam.getExam();
int count=0;
for(Question q : qArrList){
count++;
JLabel questionLabel = new JLabel(count+". "+q.getQustion()); //swing constant ?
ArrayList<String> ansRand = q.getAllRandomAns();
a1 = new JRadioButton(ansRand.get(0));
a2 = new JRadioButton(ansRand.get(1));
a3 = new JRadioButton(ansRand.get(2));
a4 = new JRadioButton(ansRand.get(3));
add(questionLabel);
add(a1);add(a2,gbc);add(a3);add(a4);
ButtonGroup radioGroup = new ButtonGroup(); //logical relationship
radioGroup.add(a1);radioGroup.add(a2);radioGroup.add(a3);radioGroup.add(a4);
}
//buttons:
JButton checkMe = new JButton("Check Exam");
JButton refresh = new JButton("Start Over");
ButtonHandler handler = new ButtonHandler();
checkMe.addActionListener(handler);
refresh.addActionListener(handler);
add(checkMe);
add(refresh);
}
/** Listens to the radio buttons. */
public class ButtonHandler implements ActionListener
{
public void actionPerformed (ActionEvent e) {
if(e.getActionCommand().equals("Start Over")){ //id?
//how to do this?
}
else{
RadioButtonHandler handler = new RadioButtonHandler();
a1.addItemListener(handler);
System.out.println("success?");
}
JOptionPane.showMessageDialog(ExamFrame.this, String.format("You pressed: %s", e.getActionCommand()));
}
public void itemStateChanged(ItemEvent e) //can i add it here?
{
JOptionPane.showMessageDialog(ExamFrame.this, String.format("yes?"));
System.out.println("success!");
}
}
public class RadioButtonHandler implements ItemListener
{
public void itemStateChanged(ItemEvent e)
{
JOptionPane.showMessageDialog(ExamFrame.this, String.format("radio state changed"));
}
}
}

why "itemStateChanges" isn't triggered, i tried to put it in the inner
class "ButtonHandler" and also in "RadioButtonHandler" Im having
troubles with it, what is the right way to do it? I want to trigger
and check the marked JRadioButtons after the user click the "check"
button.
ButtonHandler is implemented with ActionListener only:
public class ButtonHandler implements ActionListener{}
The itemStateChanged(ItemEvent) function belongs to ItemListener. This function is triggered if state of a source component to which this listener is registered gets changed. So implement the ItemListener. However, one more thing to note, that JButton doesn't respond to ItemListener but JRadioButton will. Because this Item events are fired by components that implement the ItemSelectable interface. Some example of such components are: check boxes, check menu items, toggle buttons and combo boxes including Radio Buttons as mentioned above.
What is the right way to check which button was clicked, i feel like
comparing the strings is wrong programming. Maybe using an ID
Well using the event source function: e.getSource(), check whither the type of the source is your expected type and cast it to appropriate type. And then you can use getName(String) function and check the name you were expecting. Of-course you should assign the name using setName(String) after initialization of component. Or using the component reference directly if it is declared in the Class context and you have direct access to the component.
#Override
public void itemStateChanged(ItemEvent e) {
if(e.getSource() instanceof JCheckBox)
{
JCheckBox checkBox = (JCheckBox)e.getSource();
if(checkBox.getName().equals("expectedName"))
; // do my thing
}
}
How should i make a "reset" button(start over), i want to uncheck all
radio buttons and run the constructor once again.
Well you are working with ButtonGroup. And ButtonGroup has a nice function: clearSelection() to help with whatever(I could not understand the part: run the constructor part) you want.
Edit: As you wanted me to see an ItemListener implemented class, Yes i can see that But:
i can not see that you have actually registered an instance of that class(a1.addItemListener(handler);) to any component before performing any action on the component to which ButtonHandler is registered to: checkMe, refresh
In addition to that, in this action performed function, you are checking with
action command, which you haven't even set with JButton.setActionCommand(String) function. You should not assign a (Item)listener depending on event-occurrence of another (Action)listener.
Tutorial:
How to Write an ItemListener
How to Write an ActionListener
How to Use the ButtonGroup Component

Related

Trying to create a really simple button for my Panel, but even though i implement the action listener in the class, it isn't working [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 months ago.
Improve this question
I am trying just to get the button to display some text in the console, but whatever i do it isn't working here is the code for the Button class:
public class Button extends JButton implements ActionListener {
JButton button;
Button (){
button = new JButton();
this.setText("Click NOW");
button.addActionListener(this);
this.setForeground(Color.white);
button.setBounds(300, 100, 100, 50);
this.setBackground(Color.red);
this.setBorder(null);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource()== button) {
System.out.println("Display if you work");
}
}
}
There are no errors displayed and the code compiles correctly, it just isn't displaying the text in the terminal.
This code creates two JButtons, one the button field inside of the class, that you add the action listener to:
public class Button extends JButton implements ActionListener {
JButton button; // here!
Button (){
button = new JButton(); // here!
this.setText("Click NOW");
button.addActionListener(this); // and add the listener here
and the other which is the instance of this class that extends JButton:
// here !!!
public class Button extends JButton implements ActionListener {
// ....
and which is likely the one that is displayed as elsewhere you likely have this code:
Button button = new Button();
and then add this button to the GUI. Again, this "button" is from your Button class which extends JButton but doesn't have the action listener added to it.
You can solve this in one of two ways:
Don't create the new JButton button field inside of your new class and instead add the ActionListener to the this JButton, the instance of this class,
for example:
public class Button1 extends JButton implements ActionListener {
// JButton button;
Button1() {
// button = new JButton();
this.setText("Click NOW");
// button.addActionListener(this);
this.addActionListener(this);
this.setForeground(Color.white);
// button.setBounds(300, 100, 100, 50); // You really don't want to do
// this
this.setBackground(Color.red);
this.setBorder(null);
}
#Override
public void actionPerformed(ActionEvent e) {
// no need for the if block
// if (e.getSource() == button) {
System.out.println("Display if you work");
// }
}
}
Don't create a class that extends JButton but instead create code that creates a single JButton (not two) and add the ActionListener to the same object that is added to the GUI.
I'd go with number 2 myself and make it a method that returns a button with my properties of interest:
private JButton createMyButton(String text) {
JButton button = new JButton(text);
button.setForeground(Color.WHITE);
button.setBackground(Color.RED);
button.setBorder(null);
button.addActionListener(e -> {
System.out.println("Display if you work");
});
return button;
}
Side notes:
Avoid giving your class names that clash with core Java classes, such as class Button which clashes with the java.awt.Button class.
Avoid use of null layouts and setBounds. While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
For that reason you're far better off learning about and using the layout managers. You can find the layout manager tutorial here: Layout Manager Tutorial, and you can find links to the Swing tutorials and to other Swing resources here: Swing Info.
In your actionPerformed method, use equals in the if statement, like this:
if (e.getSource().equals(button)) {
System.out.println("Display if you work");
}
It should work. == doesn't work in this case.

ActionListener interface

public class myWindow extends JFrame implements ActionListener{
if i have this code my class will be a JFrame where where I can add component and add actionlistener to them in my constructor as followed
public MyWindow()
{
JButton b = new Jbutton("button");
b.addActionListener(this);
}
this keyword will work as an anonymous actionlistener object(which is my class) right ?
later on i will override the actionPerformed method with the heading:-
public void ActionPerformed(ActionEvent ae)
{ :
:
}
I really have a big confusion here .. my book says "the listener object invokes an event handler method with the event as an argument "
listener object : this
event handler method :ActionPerformed(ActionEvent ae)
argument: my event is the JButton b .. how come when it's not of EventAction type ? And if so why we are using :
ae.getActionCommand();
I thought it's a method to tell which component fired the event,why we need it when the component is passed as an argument then?
this keyword will work as an anonymous actionlistener object(which is my class) right ?
No this will be an Object of class which is implementing the actionsListener. In your case it is "MyWindow".
my event is the JButton b .. how come when it's not of EventAction type ? And if so why we are using :
JButton b is a component not an event. Events describes the changed in state of the source. When users interact with GUI, events are generated like clicking of button, moving the mouse.
Reference from Click here
Event Handling is a mechanism that controls the event and decides what should happen if an event occurs.
Steps involved in event handling:-
The User clicks the button and the event is generated.
Now the object of concerned event class is created automatically and information about the source and the event get populated with in same object.
Event object is forwarded to the method of registered listener class.
the method is now get executed and returns.
I thought it's a method to tell which component fired the event,why we need it when the component is passed as an argument then?
Now you would have understood that there could be many buttons registered to the same ActionsListerner. Now to perform different actions for different events,
e.getActionCommand() comes handy, it will tell you which button is the source of firing the event.
Hope this helps.
I have tried to give you can example of a simple JButton program.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ButtonSwing {
private int numClicks = 0;
public Component createComponents() {
//Method for creating the GUI componenets
final JLabel label = new JLabel("Clicks: " + "0"); //final so that i can access inside inner class
JButton button = new JButton("Simple Button");
button.addActionListener(
//inner class for ActionListener. This is how generally it is done.
new ActionListener() {
public void actionPerformed(ActionEvent e) {
numClicks++;
label.setText("Clicks: " + numClicks);
System.out.println(e.getActionCommand());
System.out.println(e.getModifiers());
System.out.println(e.paramString());
}
}
);
JPanel pane = new JPanel(); //using JPanel as conatiner first.
pane.setLayout(new FlowLayout());
pane.add(button); // adding button to the JPanel.
pane.add(label); // adding label to the JPanel.
return pane;
}
public static void main(String[] args) {
JFrame frame = new JFrame("SwingApplication");
ButtonSwing obj = new ButtonSwing();
Component contents = obj.createComponents();
frame.getContentPane().add(contents);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.pack(); //It will cause the window to be sized to fit the preferred size
//and layouts of its subcomponents.
frame.setVisible(true);
}
}
Your JButton is a component not an event. Events are generated by some action on components in this case When you click your button, an ActionEvent will be fired and it will be passed to all the listeners who subscribed to that event in this case it is your MyWindow object which is serving as an ActionListener

Trouble with Java GUI design

I am having trouble designing GUI's in an object oriented manner. The following code will help me express my question more clearly:
import javax.swing;
import java.awt.*;
import java.awt.event.*;
public class QuoteOptionsPanel extends JPanel
{
private JLabel quote;
private JRadioButton comedy, philosophy, carpentry;
private String comedyQuote, philosophyQuote, carpentryQuote;
//-----------------------------------------------------------------
// Sets up a panel with a label and a set of radio buttons
// that control its text.
//-----------------------------------------------------------------
public QuoteOptionsPanel()
{
comedyQuote = "Take my wife, please.";
philosophyQuote = "I think, therefore I am.";
carpentryQuote = "Measure twice. Cut once.";
quote = new JLabel (comedyQuote);
quote.setFont (new Font ("Helvetica", Font.BOLD, 24));
comedy = new JRadioButton ("Comedy", true);
comedy.setBackground (Color.green);
philosophy = new JRadioButton ("Philosophy");
philosophy.setBackground (Color.green);
carpentry = new JRadioButton ("Carpentry");
carpentry.setBackground (Color.green);
ButtonGroup group = new ButtonGroup();
group.add (comedy);
group.add (philosophy);
group.add (carpentry);
QuoteListener listener = new QuoteListener();
comedy.addActionListener (listener);
philosophy.addActionListener (listener);
carpentry.addActionListener (listener);
add (quote);
add (comedy);
add (philosophy);
add (carpentry);
setBackground (Color.green);
setPreferredSize (new Dimension(300, 100));
}
//*****************************************************************
// Represents the listener for all radio buttons.
//*****************************************************************
private class QuoteListener implements ActionListener
{
//--------------------------------------------------------------
// Sets the text of the label depending on which radio
// button was pressed.
//--------------------------------------------------------------
public void actionPerformed (ActionEvent event)
{
Object source = event.getSource();
if (source == comedy)
quote.setText (comedyQuote);
else
if (source == philosophy)
quote.setText (philosophyQuote);
else
quote.setText (carpentryQuote);
}
}
}
The above code simply creates a panel with three radio buttons, each corresponding to a quote. It also creates a label which displays a quote. Whenever a button is selected, the text in the label is set to the corresponding quote. I understand this code just fine. I run into trouble trying to modify it. Let's say I want to create the same program, but with the radio buttons stacked vertically on top of one another. Let's also say that I decide to go about this by adding the radio buttons to a panel with a BoxLayout, which I define in its own BoxPanel class. (I would then add the BoxPanel to my QuoteOptionsPanel, which would still contain my quote JLabel.)
So my BoxPanel code might look something like this:
import java.awt.*;
import javax.swing.*;
public class BoxPanel extends JPanel
{
private JRadioButton comedy, philosophy, carpentry;
public BoxPanel()
{
setLayout (new BoxLayout (this, BoxLayout.Y_AXIS));
setBackground (Color.green);
comedy = new JRadioButton ("Comedy", true);
comedy.setBackground (Color.green);
philosophy = new JRadioButton ("Philosophy");
philosophy.setBackground (Color.green);
carpentry = new JRadioButton ("Carpentry");
carpentry.setBackground (Color.green);
ButtonGroup group = new ButtonGroup();
group.add (comedy);
group.add (philosophy);
group.add (carpentry);
QuoteListener listener = new QuoteListener();
comedy.addActionListener (listener);
philosophy.addActionListener (listener);
carpentry.addActionListener (listener);
}
//*****************************************************************
// Represents the listener for all radio buttons.
//*****************************************************************
private class QuoteListener implements ActionListener
{
//--------------------------------------------------------------
// Sets the text of the label depending on which radio
// button was pressed.
//--------------------------------------------------------------
public void actionPerformed (ActionEvent event)
{
Object source = event.getSource();
I do not know what to do here.
}
}
}
So as you can see, I did not know how to define my QuoteListener class. I want it to perform the same function as in the original program I posted, but am unsure of how to make it do so. The label which displays the quote is located in QuoteOptionsPanel, so I do not have access to it. In essence I am asking for the optimal way to change a label on one panel with an event listener belonging to a component on a different panel. I would be immensely grateful for any help you may be able to provide. Please let me know if I have not expressed my question clearly enough.
There are several ways to solve this, but for most all the key is to get and use references. Say the class that holds the JLabel as a private field has a public method,
public void setQuoteLabelText(String text) {
quoteLabel.setText(text);
}
Then you have to pass the reference to the visualized object of this class to your BoxPanel class, either through a constructor parameter or a setXXX(...) setter method. Then your ActionListener can call methods on the object of this class.
1. You can create an instance of the class whose private instance variable you need to
access.
2. Follow the one of the many use of Encapsulation, that is to have private Instance variable
and public getter-setter for that instance variable.
3. Now you can access the private member, by calling the public method on the instance of
the class.
4. One more thing, try using the Group Layout created by NetBeans team in 2005. Use the Window Builder Pro, now free from google.

Can two JButton have the same mouse clicked event function?

I am developing a calculator in Java language. The problem is that, i put ten buttons for digits(0,1,2..9) and i want that when i clicked one of them, all perform the same mouse clicked function. Is it possible? In netbeans, it does not let me do that, or i couldnt achieve. Thank you for helping.
Yes. Add the same listener to both buttons you are using.
For example, suppose you are using actionListener then:
public class ListenerClass implements Action{
#override
public void actionPerformed(ActionEvent e) {
//here retrieve information on which button has generated the event
}
}
ListenerClass listener = new ListenerClass();
JButton first = new JButton();
JButton second = new JButton();
first.addActionListener(listener);
second.addActionListener(listener);

How to propogate Swing events from a inner component to a container?

I created a component based on a JPanel that contains a textfield and a checkbox. Since I use it as component and put it around in other panels I'd like to be able to set a KeyPressed event for the panel. Obiouvsly this doesn't work as the keyPressed events fire for the inner textfield. Is it there a way to propagate them to the JPanel as it was receiving them instead of the textfield? I tried with handleEvent but it doesn't even compile.
Let's clarify the question. I created this big element containing a textfield. Now a want to use this element in another and I want to set the OTHER ONE as the listener. So there is the JPanel between. That's the problem.
You can use javax.swing.event.EventListenerList in the JPanel containing the JTextField, and create a addKeyListener public method.
import javax.swing.event.EventListenerList;
public static class TestPanel extends JPanel implements KeyListener{
private JTextField text;
private EventListenerList listenerList = new EventListenerList();
TestPanel(){
text = new JTextField();
text.addKeyListener(this);
}
public void keyPressed(KeyEvent e){
//doesn't create a new array, used for performance reasons
Object[] listeners = listenerList.getListenerList();
//Array of pairs listeners[i] is Class, listeners[i + 1] is EventListener
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == KeyListener.class) {
((KeyListener)listeners[i+1]).keyPressed(e);
}
}
}
public void addKeyListener(KeyListener l) {
listenerList.add(KeyListener.class, l);
}
public void keyReleased(KeyEvent e){
//idem as for keyPressed
}
public void keyTyped(KeyEvent e){
//idem as for keyPressed
}
}
Try adding an ActionListener to the JPanel. The actionPerformed() method in the ActionListener will get called when the user presses key in the JTextfield. You can call getSource() on the event object to determine if the event was fired due to action in JTextField and act accordingly.
you could add the JPanel derivative to the JTextField as an event listener.
You will need to do some plumbing to get this to work, for example making your JPanel derivative implement KeyListener and implementing the required methods.

Categories

Resources