I have one Mediator.java which do all the functions. And there is RecordGenerationJPanel.java to save the information of a record.NewApplicationJPanel.java is main screen and when I click jbtnGenerate in it, it will show RecordGenerationJPanel and do the showGern method in Mediator class.
All the methods have done by another developer and I have asked to make a new class which will function like showGern method. New showGern class should do some combo box disabled and it also include new text field. But it will be invoked only a checkbox in main screen(NewApplicationJPanel) is checked. Otherwise, it will call the original showGern Method.
Do I need to create another RecordGenerationJPanel? Or, can I do it in same RecordGenerationJPanel? If it's same, how should I do to show different enabling or disabling and hiding some text field according to condition.
Usually, if RecordGenerationJPanel and the requested new class share some attributes and methods, those attributes and methods should be in one class and used by both. So if theres's a future change requirement of a bug fix that affects those common parts, you just have to do it once and both panels benefit from the single fix.
In your case, I'd really copy the existing RecordGenerationJPanel to a new class and modify it to meet you requirements.
If it works, you can start a refactoring and extract the common parts to a new class.
You can add new "checkbox" (as described in your question) to old JPanel. And show/Hide/enable/disable components based on state of checkbox. Also which method to call depends on state of this checkbox.
You can enable/disable components by implementing ActionListener and attaching it to Checkbox.
JCheckBox cb1 = new JCheckBox("Check Box 1")
cb1.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
//enable disable components if checkbox is selected
//enable disable components if checkbox is not selected
}
});
Hope this helps.
Related
It might be confusing for some to answer this but I will try to put my question in the best way. I am working with jdbc and gui. Basically I want to display (in buttons format) the particular data received from my sql database. I could get the data correctly and put it to my array of buttons as their names. In other words, I have an ArrayList of buttons with different names/texts received from my database. Thus i really need to make an arraylist of buttons since data are dynamically populated. My problem is, I am so confused of how am going to create an actionListener to each button. Everytime each button is clicked, it must show the values associated with its name. I don't know how am i supposed to pass at least the names of the buttons to my actionListener method (or action Event Handler). If you find it confusing, here is the code for my buttons.
todayTaskButton.add(new JButton(taskForToday.get(i)));
todayTaskButton.get(i).setPreferredSize(new Dimension(300,75));
todayTaskButton.get(i).setBackground(Color.GRAY);
todayTaskButton.get(i).setFont(new Font("Century Gothic",Font.PLAIN,30));
todayTaskButton.get(i).setForeground(Color.WHITE);
todayTaskButton.get(i).setFocusable(false);
Thank you so much
You don't need to pass the name of the button to the ActionListener. It is automatically detected. You just need to implement the method actionPerformed(ActionEvent) in you class.
Then add the listener to the button :
todayTaskButton.get(i).addActionListener(this);
In your actionPerformed method, you can do:
JButton b = (JButton) e.getSource();
String text = b.getText();
Honestly there are so many ways you might achieve this, the problem is picking the right one for you...
You could...
Create a anonymous class for each button, each time your create them
todayTaskButton.get(i).addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//...
}
});
While this can work, it can make the code really messy, you also still need a way to map the action back to the button in some way, which can be done using the actionCommand property or using the source property if you don't mind iterating through the list of available buttons
You could...
Create a purpose build class which implements ActionListener for each button, which possibly takes some kind of reference to the data
todayTaskButton.get(i).addActionListener(new TodayActionListener(taskForToday.get(i)));
This is a little more focused, as you don't really care about the button, as you have the "today" value for the listener, so all the normally repeated code could be isolated into a single class and you would simply pass in the "variable" element
You could...
Take full advantage of the Action API and make individual, self contained actions for each button...
public class TaskAction extends AbstractAction {
public TodayAction(String task) {
putValue(NAME, task);
}
#Override
public void actionPerformed(ActionEvent e) {
// Specific action for task
}
}
Then you could simply use
todayTaskButton.add(new JButton(new TaskAction(taskForToday.get(i))));
While this is similar to the previous option, the Action is a self contained unit of work and has a number of properties which the JButton can use to configure it self. The Action can also be re-used for JMenuItems and key bindings, making it incredibly flexible
Have a closer look at How to Use Actions for more details
I always use one ActionListenr for a button, but I find that one component can be assigned multiple action listeners. How we can do that and what is use of it
Thanks in advance
c.addActionListener(actionlistener1);
c.addActionListener(actionlistener2);
It is useful if you need to do several actions that are not necessarily correlated. For example, changing the background color of a button vs appending the action in a Logger vs informing the controller that the button have been pressed, etc...
This allows to be modular: each actionListener can handle a very specific task for a group of components. For example, you can write a default actionListener for all your buttons, and a specific one for a group of buttons that have the same behaviour.
Finally, some objects already have listeners when you instantiate them (JButton have a default FocusListener, JScrollPane a default MouseWheelListener, etc). This allow you to add other behaviours to your components, without overriding previous ones.
How we can do that
That's the easy part, create multiple instance of ActionListeners and use addActionListener. One would assume that they are all different...
and what is use of it
That's a harder question. One could assume that you would use multiple listeners when you want to apply newer logic to the process but not extend from the existing functionality...
Let's say you have a login form. You have a "Login" button. You write an ActionListener to gather the required details and validate them.
Later on, you decide that the button should be disabled during that process. Normally, you would add that functionality to the original code, but for what ever reason (it's not your code etc), you can't.
You could create another ActionListener whose sole purpose was to disable the button when it was pressed.
As an example...
I want to show one JLabel and one JComboBox when one particular RadioButton is selected in previous frame, otherwise it should be hidden. Even when I implement ComponentListener in that class his abstract methods(componentShown(), componentHidden()) are never called.
I think that your problem can be handled pretty easily, without even getting into these event handlers. Just pass a variable from your initial frame, when the RadioButton is selected, to the new frame (maybe a boolean variable with true value). Then, in your new fame, simply show the components, based on the value of that variable.
I hope you can handle the passing of variables, by handling the constructor parameters of your new frame.
Hope this helps ! Any clarifications required, please comment.
I am Swing novice. I made a small app using JTree, JCheckBox, JList and JButton. I am using the associated model classes to store the presentation state. Works fine, except for the JButton. I'd like to update the button's text according to a property of my model. Basically, it will change from log in/to log off whether the user is currently logged in. Unfortunatly, I can't find a setText method in the ButtonModel interface. Can anybody tell me how to do this ?
Thanks. PW.
For a JButton you can use an Action as your model. The Action interface defines keys which are used by the JButton to retrieve its state from the Action, including one for the text: Action.NAME
If you look at the source code, the constructor with the Action (or simply the setAction method) uses more information from the Action then what can be retrieved from a ButtonModel. Same for other constructors, e.g.
public JButton(String text, Icon icon) {
// Create the model
setModel(new DefaultButtonModel());
// initialize
init(text, icon);
}
So it seems that you are correct in your assessment that the ButtonModel does not contain all information used to visualize a typical JButton
OK, so if I add an ActionListener to a GUI element, and it's the only element I use that ActionListener with, does it matter which of the following lines (a,b) I use to get the checkbox selected state?
final JCheckBox checkbox = (JCheckBox)this.buildResult.get("cbDebugTick");
checkbox.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent event){
boolean bChecked =
// (a) checkbox.isSelected();
// (b) ((JCheckBox)event.getSource()).isSelected();
model.setPrintDebugOn(bChecked);
}
});
It makes sense to me that if I add the ActionListener object to multiple GUI elements, then I should use (b).
And in (b), is it OK to blindly cast event.getSource() to JCheckBox, since I'm the one who added the action listener, or should I program defensively and do an instanceof check?
note: this question is in the context of event listeners in general; kdgregory has some good points below specifically re: checkboxes which I had neglected to consider.
I'd do neither.
If clicking the checkbox is going to start some action, I'd attach an ItemListener, then just look at the selection state in the ItemEvent.
However, checkboxes don't normally invoke actions, they manage state. So a better approach is to examine all of your checkboxes in response to whatever does kick off the action.
Edit: some commentary about the larger issues that the OP raised.
First, it's important to realize that large parts of Swing represent implementation convenience rather than a coherent behavior model. JCheckBox and JButton have nothing in common other than the fact that clicking within their space is meaningful. However, they both inherit from AbstractButton, which provides implementation details such as the button's label. It also assumes that buttons are "pressed", and that pressing a button will initiate some meaningful behavior (the action). In the case of JCheckbox, however, the button press is not important, the change in state is. That state change is signaled to the ItemListener -- which is also defined on AbstractButton even though state changes are meaningless to other button types (the JavaDoc even says "checkbox").
One of the things that Swing did get right -- if hard to use -- is the idea of that an Action is separate from the control initiating that action. An Action object can be invoked from multiple controls: a menu item, a pushbutton on a dialog, a keystroke, whatever. More important from a design perspective is that it takes you away from the idea of a generic "listener" that tries to figure out what needs to happen. I've seen apps where a single listener receives input from the entire menu system, for example, and then runs through a big if/else chain to figure out which menu item was pressed. Using Actions means you have more classes, but in the long run gives you a more maintainable app.
Finally, from a usability perspective, there's a difference between controls that maintain state, such as JCheckbox and JTextArea, and those that initiate actions, such as JButton and JMenuItem. I have seen a (web) app where clicking on a radio button takes you to a different page. That's bad. Even if you're planning to use listeners internally, to update the state of some model, you should ask yourself why the collection of GUI elements do not in themselves provide you with a model.
For the case where the listener is exclusive (such as an anon listener), I use (a).
If the listener will be reused (eg, this is an instance of ActionListener) I'll write it as:
#Override
public void actionPerformed(ActionEvent event) {
Object src = event.getSource();
if (src == checkbox) {
boolean bChecked = checkbox.isSelected();
// ...
}
}
If you have several checkboxes and they are processed the same way, then instanceof makes sense.
in (b) to be rigourous, you should indeed do a instanceof check, but it's not that important. I would think both these lines are fine and acceptable, though (b) would be "better code"
Although, what is usually done in an action listener is simply call another method customized to your checkbox. So it would look like something like this:
#Override public void actionPerformed(ActionEvent event) {
//your treatment would be in this method, where it would be acceptable to use (a)
onCheckBoxActionPerformed(event)
}
I'd program with b defensively as it's the best-practice option. But if only you are ever going to use the code then there is no reason why you can't do a. However, imagine how happy you will be with yourself if you come back to it at some future point, change something and find you wrote good code which you can directly reuse...