I'm developing the MVC application and don't know how to pass values of textfields in View to Controller, when a user press the button. ActionListener of this button is placed in Controller:
private class NewTaskListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
/* here I need to get values of textfields in View
and pass them to AddNewTaskForUser
*/
model.AddNewTaskForUser(userName, newTask);
}
}
Listener is added to button in such way:
Controller:
this.view.AddNewTaskListanaer(new NewTaskListener());
View:
public void AddNewTaskListanaer(ActionListener actionListener)
{
btnSetupTask.addActionListener(actionListener);
}
Thanks!
Your view should have public methods:
public String getTaskName() {
return taskName.getText();
}
public String getDescription() {
return description.getText();
}
// And so on and so on...
Now in your controller you can get the desired text field data from the view. So now in your action listener you can do:
private class NewTaskListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
String userName = view.getUsername();
String newTask = view.getTaskName();
model.AddNewTaskForUser(userName, newTask);
}
}
This is assuming the action listener class is declared within the controller so it has access to the controllers properties.
Also, methods should not start with a capital letter. They should be in the format lowerCamelCase.
Example:
addActionListener and actionPerformed.
you need to pass the instances of your textfield to your listener.
private class NewTaskListener implements ActionListener {
private JTextField textField;
public NewTaskListener(JTextField textField) {
this.textField = textField;
}
#Override
public void actionPerformed(ActionEvent e) {
//.. do stuff
model.AddNewTaskForUser(userName, newTask);
}
}
and create it like this:
this.view.AddNewTaskListanaer(new NewTaskListener(textField));
Related
i have created 3 classes TourAgency class, addTourAgency Jdialog class and addGuide Jdialog class
TourAgency class
public class TourAgency
{
...
public TourAgency() {
this("Not set", "Not set");
}
public TourAgency(String inAgencyName, String inAgencyLocation)
{
setAgencyName(inAgencyName);
setAgencyLocation(inAgencyLocation);
}
addTourAgency class (the code where the agency is created)
public class addTAJD extends JDialog{
...
private TourAgency ta1;
okBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae)
{
String name = nameTF.getText().trim();
String location = locationTF.getText().trim();
ta1 = new TourAgency(name, location);
...
setVisible(false);
JOptionPane.showMessageDialog(null, ta1.getAgencyName() + " is created");
}
});
addGuide class (the part of the code to check whether the agency is missing or not)
public class AddNGuideJD extends JDialog{
private JLabel name, idNumber, salary, extra;
private JTextField nameTF, idNumberTF, salaryTF, extraTF;
private JButton okBtn, resetBtn, cancelBtn;
private Guide guide;
private TourAgency ta1;
okBtn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae)
{
if(ta1 != null)
{
...
}
else
{
JOptionPane.showMessageDialog(null, "Please add a Tour Agency to countinue");
}
}
});
so my questions is when i created a tour agency in the addTourAgency class and i click on the on button from the addGuide class, why does it always pop out the message saying an agency is not created?((JOptionPane.showMessageDialog(null, "Please add a Tour Agency to countinue");). Did i miss something? how can i used the object that i have already created?
Use getters and setters.
In the JDialog where you create AgencyTour create a getAgencyTour function and In the next JDialog create a setAgencyTour function to pass the result from the previous function.
Also you can pass the created AgencyTour from addTAJD as a parameter to the constructor of AddNGuideJD
i'm doing a class that does a sort of "file explorer",
in the constructor i create the frame ,panel ecc.. but than i want to say to the main program that calls this class that the user has finish the selection, i know i can call a static method that is in the main from this class,but i want to make a action listener because i want to use this class for different programs
For Example if FileEx is my class:
public class FileEx()
{
public FileEx()
{
//program that do something
if(done == true)
//here i want to call the action
}
public void addActionListener(ActionListener ac) //i don't know if it's correct
//but i want something like this
{
}
}
public static void main(String[] args)
{
FileEx fileex = new FileEx();
fileex.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e)
{
//when done is true i want this block of code to be called
}
});
}
ActionListeners will only work when added to components that allow them to be added and that notify listeners with them such as JButtons, JMenuItems, JComboBoxes and such. We have no idea what type of class FileEx is or why it should accept an ActionListener and a little more information would be qutie helpful. If you want to notify another object that an event occurs, such as that a calculation is done, use another type of listener such as a PropertyChangeListener. Alternatively you could do the processing in a modal JDialog window, which will notify the calling window that it is done performing its duties by returning code flow to the calling window.
For example, please look at my answers to similar questions:
Drawing with paintComponent after value of Jbutton changed in another class
JTextField data in different frames, with data stored in global variable?
Loop making program freeze
EDIT
For example, if you wanted your FileEx to allow other classes to listen for changes to a String called selection (the so-called "bound" property) you could create it to look something like:
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
public class TestFileEx {
public static void main(String[] args) {
final FileEx fileEx = new FileEx();
fileEx.addPropertyChangeListener(FileEx.SELECTION, new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
// TODO code to call when fileEx has changed selections
String fileExSelection = evt.getNewValue().toString();
// or
String fileExSelection2 = fileEx.getSelection();
}
});
}
}
and
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.event.SwingPropertyChangeSupport;
publicclass FileEx {
public static final String SELECTION = "selection";
private SwingPropertyChangeSupport propertyChangeSupport = new SwingPropertyChangeSupport(
this);
private String selection;
public void someMethodThatChangesSelection() {
}
public String getSelection() {
return selection;
}
public void setSelection(String selection) {
String oldValue = this.selection;
String newValue = selection;
this.selection = selection;
// notify the listeners of change
propertyChangeSupport.firePropertyChange(SELECTION, oldValue, newValue);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(listener);
}
public void rem(String propertyName, PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(propertyName, listener);
}
}
Here is the code based on your example which adds actionlisteners and calls them:
public class FileEx()
{
private final List<ActionListener> listeners = new ArrayList<>();
public FileEx()
{
//program that do something
if(done == true) {
notifyListeners();
}
}
public void addActionListener(ActionListener ac)
{
listeners.add(ac);
}
private void notifyListeners()
{
for (final ActionListener listener: listeners)
{
listener.actionPerformed(null);//You can create event if you want.
}
}
}
public static void main(String[] args)
{
FileEx fileex = new FileEx();
fileex.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e)
{
//when done is true i want this block of code to be called
}
});
}
I currently have a JTextField and inside that, I have default text.
The problem I currently have is getting that JTextField to have a working ActionListener. I have added an action listener to the component, but when I use FocusListener to check for focus, it will not give any output/reply.
Any help will be much appreciated. And please supply me with some example code of what I should change, thanks.
PS. I am using this class as a component from another class, so in another class I wrote:
window.add(smartTextField);
SmartText.java
package com.finn.multiweb;
import java.awt.Color;
import javax.swing.JTextField;
public class SmartText extends JTextField {
private static final long serialVersionUID = 1L;
JTextField textField = new JTextField();
String defaultText;
boolean hasDefaultText;
public SmartText() {
super();
hasDefaultText = false;
notFocused();
}
public SmartText(String defaultText) {
super(defaultText);
this.defaultText = defaultText;
hasDefaultText = true;
notFocused();
}
private void notFocused() {
super.setForeground(Color.GRAY);
if (hasDefaultText == true) {
super.setText(defaultText);
} else if (hasDefaultText == false) {
super.setText("");
}
}
private void isFocused() {
super.setForeground(Color.BLACK);
super.setText("");
}
private void focusGained(java.awt.event.FocusEvent evt) {
System.out.println("test");
}
}
You've not added a FocusListener to the field
// You need to implement the FocusListener interface
public class SmartText extends JTextField implements FocusListener {
private static final long serialVersionUID = 1L;
JTextField textField = new JTextField();
String defaultText;
boolean hasDefaultText;
public SmartText() {
super();
hasDefaultText = false;
notFocused();
// Then register yourself as interested in focus events
addFocusListener(this);
}
public SmartText(String defaultText) {
super(defaultText);
this.defaultText = defaultText;
hasDefaultText = true;
notFocused();
// Then register yourself as interested in focus events
addFocusListener(this);
}
// Then implement the contract of the FocusListener interface
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent e) {
}
Take a read through How to Write a Focus Listener for more details
From the looks of your code, you trying to add "prompt support" to the field, you may consider using the PromptSupport from the SwingLabs, SwingX libraries, for example
You can use the Text Prompt which is a single class.
To work with FocusListener Interface and in order to listen’s the keyboards gaining or losing focus, the listener object created from class is need to registered with a component using the component’s addFocusListener() method. The two important method focusGained(FocusEvent e) and void focusLost(FocusEvent e) which helps to find which component is focused.
Take a read through What is FocusListener Interface and How it Work and Validate Text Field Using FocusListener Interface in Java for more details with proper examples.
There's a text field and when lost focus it will validate the inputs, if not passed, print out the error message (to be simple here just has an empty check). And there's a button next to the text field, it will print out the text once click on it.
As I tried, when input some text and then click the button it will trigger both the focus lost event of text field and the event of button. In a other word, it will do the validation first and then print out the input text.
Here comes my question, what is the good approach to prevent printing out the text if the validation not passed? Or is there a way to "ignore" the click event on button if validation not passed?
I tried to use a boolean flag which indicate the validation result and check the flag when perform the action for button, but I do not think it is a good approach. As I know there's an event dispatcher thread in Swing which deal with the events, is it possible I can cancel the events from here?
Below is a piece of code which explain the question:
public class SimpleDemo
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel content = new JPanel(new FlowLayout());
frame.setContentPane(content);
final JTextField textField = new JTextField(10);
textField.addFocusListener(new FocusAdapter()
{
#Override
public void focusLost(FocusEvent e)
{
String text = textField.getText();
// do some validation here, if not validated
// do not trigger the event on button.
if ("".equals(text))
{
System.out.print("please input a text!");
}
}
});
content.add(textField);
JButton button = new JButton("Print Text");
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
// action performed for button
String text = textField.getText();
System.out.println(text);
}
});
content.add(button);
frame.setVisible(true);
frame.pack();
}
}
I faces similar issue while working on an application. I solved it like below
I created a abstract class ApplicationFrame which every frame in the application extends
public abstract class ApplicationFrame extends JFrame implements ActionListener {
#Override
final public void actionPerformed(ActionEvent event) {
if(validateInput()){
performAction(event);
}
}
/*
* Sub class should override this method to receive any action
*/
protected void performAction(ActionEvent event) {};
/*
* Sub class should override this method to perform validation
*/
abstract protected boolean validateInput();
}
All Frames will now extend this base frame, as below:
public class Frame1 extends ApplicationFrame{
#Override
protected void performAction(ActionEvent event) {
// perform action
}
#Override
protected boolean validateInput() {
// return true or false depending upon the validation results
}
// if you want to add Action Listener, you need to add like this:
btnSomeButton.addActionListener(this);
}
If you need to handle Focus events, you can make ApplicationFrame or the base frame implement FocusListener.
This is my custom implementation to solve the problem, hope this helps.
Make the button disabled on start-up
Upon lost focus, validate the text & enable button only when the input passes validation.
Upon start of text change, disable the button
It's always makes sense to make ui to communicate with user. So you can show "please input a text" as the default text of the textField when nothing is entered by user.
Here is the code for such custom textField:
public class TextFieldWithDefaultText extends JTextField implements FocusListener{
private final String hint;
public TextFieldWithDefaultText (String $text)
{
super($text);
this.hint = $text;
addFocusListener(this);
}
#Override
public void focusGained (FocusEvent $e)
{
if (this.getText().isEmpty())
{
super.setText("");
}
}
#Override
public void focusLost (FocusEvent $e)
{
if (this.getText().isEmpty())
{
super.setText(hint);
}
}
#Override
public String getText ()
{
String typed = super.getText();
return typed.equals(hint) ? "" : typed;
}
}
Write the acttionListerner for your button like this:
JButton button = new JButton("Print Text");
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
if(!textField.getText().isEmpty())
System.out.println(textField.getText());
}
});
And ur textField implementation should be :
final TextFieldWithDefaultText textField = new TextFieldWithDefaultText ("please input a text");
Hope this helps :)
Here is a class View of the MVC paradigm, the class consist of 2 JDialogs, to be opened on click of JMenuItem - addEvent and editEvent.
public class EventView extends javax.swing.JFrame {
private javax.swing.JDialog addDialog;
private javax.swing.JDialog editDialog;
private EventModel model;
/** Constructor */
public EventView(EventModel model) {
initComponents();
this.model = model;
updateEventTable();
}
public void addEventListener(ActionListener al) {
addEventButton.addActionListener(al);
}
/* public void clearListener(ActionListener cl) {
clearEventButton.addActionListener(cl);
}*/
public void addDialog(ActionListener ae) {
addEvent.addActionListener(ae);
}
public void editDialog(ActionListener ee) {
editEvent.addActionListener(ee);
}
}
The controller class handles the user interaction with listeners.
public class EventController implements ActionListener {
//... The Controller needs to interact with both the Model and View.
private EventModel model;
private EventView view;
/** Constructor */
public EventController(EventModel model, EventView v){
model = new EventModel();
view = v;
//... Add listeners to the view.
view.addEventListener(new addEventListener());
//view.clearListener(new clearEventListener());
view.addDialog(new addDialogListener());
view.editDialog(new editDialogListener());
}
class addEventListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String name = "";
String date;
String start="";
String end="";
String venue="";
String details="";
String opportunities="";
String moreOppor="";
try {
name = view.getEventName();
date = view.eventDate().toString();
start = view.startTime();
end = view.endTime();
venue = view.locationWhere();
details = view.getDetails();
opportunities = view.getOpportunities();
moreOppor = view.getMore();
model.addEvent(name,date,start,venue,details,opportunities,moreOppor,end);
view.showSuccess("Event Added!");
} catch (Exception ex) {
view.showError(ex);
}
}
}
class addDialogListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("");
}
}
class editDialogListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("");
}
}
I have two question in relation to this module:
EventController is showing an error that it is not abstract and does not override abstract method actionPerformed when I believe I did. Correct me if im wrong. I do have an additional JMenuItem called deleteEvent but I havent touched that yet. Working on NetbeansIDE F.Y.I
I would like to replace the lines System.out.println(""); with something that will allow me to display the dialog addDialog of the view class but I cannot access the component. how to do this? I've tried view. but it doesnt show up allow for setVisible(true) .
Your compiler is quite right: EventController does not declare a public void actionPerformed(ActionEvent e) method. It does have two inner classes that have the method, though, but that doesn't count.
The way you have named your class, addEventListener, suggests that you really meant to call the method addEventListener instead of declare a class, but no definite suggestion can be given based on your code.
1) You forgot to implement the actionPerformed() method in the EventController Class.
2) You should set the view as an argument of addDialogListener and editDialogListener.
Something like :
public class addDialogListener implements ActionListener {
private EventView view;
public addDialogListener(EventView view){
this.view = view;
}
#Override
public void actionPerformed(ActionEvent e) {
view.doWhatever();
}
}
And then :
view.addDialog(new addDialogListener(view));
public class EventController {
}
instead of
public class EventController implements ActionListener {
}