I have a instance of a custom JLabel and i want to changes its text in all frames, but the text is changing only on the last opened frame. There's a way i can achieve this?
Here's what happens:
And my code:
App.java
package test;
import javax.swing.JFrame;
public class App extends JFrame {
protected static App app;
private String loggedUser;
private MyCustomLabel myCustomLabel;
public App() {
loggedUser = "User One";
myCustomLabel = new MyCustomLabel(loggedUser);
}
public static App getApp() {
return app;
}
public MyCustomLabel getMyCustomLabel() {
return myCustomLabel;
}
public String getLoggedUser() {
return loggedUser;
}
public void setLoggedUser(String loggedUser) {
this.loggedUser = loggedUser;
}
}
FrmApp.java
package test;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
/**
*
* #author Marco
*/
public class FrmApp extends App {
public FrmApp() {
app = new App();
initComponents();
}
private void initComponents() {
setLayout(new FlowLayout());
setSize(300, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
btnFrmOne = new JButton("Open frmOne");
btnFrmOne.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
FrmOne frmOne = new FrmOne();
frmOne.setVisible(true);
}
});
add(btnFrmOne);
btnFrmTwo = new JButton("Open frmTwo");
btnFrmTwo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
FrmTwo frmTwo = new FrmTwo();
frmTwo.setVisible(true);
}
});
add(btnFrmTwo);
btnChangeUser = new JButton("Change user");
btnChangeUser.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (App.getApp().getLoggedUser().equals("User One")) {
App.getApp().setLoggedUser("User Two");
} else {
App.getApp().setLoggedUser("User One");
}
App.getApp().getMyCustomLabel().refresh();
}
});
add(btnChangeUser);
}
private JButton btnFrmOne;
private JButton btnFrmTwo;
private JButton btnChangeUser;
public static void main(String args[]) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
Logger.getLogger(FrmApp.class.getName()).log(Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
Logger.getLogger(FrmApp.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(FrmApp.class.getName()).log(Level.SEVERE, null, ex);
} catch (UnsupportedLookAndFeelException ex) {
Logger.getLogger(FrmApp.class.getName()).log(Level.SEVERE, null, ex);
}
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new FrmApp().setVisible(true);
}
});
}
}
FrmOne.java
package test;
import java.awt.FlowLayout;
import javax.swing.JFrame;
public class FrmOne extends JFrame {
public FrmOne() {
initComponents();
}
private void initComponents() {
setLayout(new FlowLayout());
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setSize(150, 100);
add(App.getApp().getMyCustomLabel());
}
}
FrmTwo.java
package test;
import java.awt.FlowLayout;
import javax.swing.JFrame;
public class FrmTwo extends JFrame {
public FrmTwo() {
initComponents();
}
private void initComponents() {
setLayout(new FlowLayout());
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setSize(150, 100);
add(App.getApp().getMyCustomLabel());
}
}
MyCustomLabel.java
package test;
import javax.swing.JLabel;
public class MyCustomLabel extends JLabel {
public MyCustomLabel(String loggedUser) {
initComponents(loggedUser);
}
private void initComponents(String loggedUser) {
setText(loggedUser);
}
public void refresh() {
setText(App.getApp().getLoggedUser());
}
}
Update
This is what im doing now to do what i wanted.
App.java
public class App extends JFrame {
public App() {
User user = new User(1, "User One");
LoggedUser.getInstance().setUser(user);
initComponents();
}
public static void main(String[] args) {
new App().setVisible(true);
}
private void initComponents() {
setSize(200, 200);
setLocation(400, 200);
setLayout(new FlowLayout());
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JButton btn1 = new JButton("dlgOne");
btn1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
DlgOne dlgOne = new DlgOne(App.this, false);
dlgOne.setVisible(true);
}
});
JButton btn2 = new JButton("dlgTwo");
btn2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
DlgTwo dlgTwo = new DlgTwo(App.this, false);
dlgTwo.setVisible(true);
}
});
JButton btn3 = new JButton("change user");
btn3.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (LoggedUser.getInstance().getUser().getId() == 1) {
User user = new User(2, "User Two");
LoggedUser.getInstance().setUser(user);
} else {
User user = new User(1, "User One");
LoggedUser.getInstance().setUser(user);
}
}
});
add(btn1);
add(btn2);
add(btn3);
}
}
MyCustomPanel.java
public class MyCustomPanel extends JPanel implements Observer {
private JLabel label;
public MyCustomPanel() {
initComponents();
}
#Override
public void update(Observable o, Object arg) {
//LoggedUser u = (LoggedUser) o;
//System.out.println(u.getUser().getId());
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
label.setText(LoggedUser.getInstance().getUser().getName());
}
});
}
private void initComponents() {
LoggedUser.getInstance().addObserver(this);
label = new JLabel(LoggedUser.getInstance().getUser().getName());
add(label);
}
}
User.java
public class User {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
DlgOne.java
public class DlgOne extends JDialog {
public DlgOne(Frame owner, boolean modal) {
super(owner, modal);
initComponents();
}
private void initComponents() {
setTitle("dlgOne");
setSize(200, 200);
setLocation(600, 200);
setLayout(new FlowLayout());
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
add(new MyCustomPanel());
}
}
DlgTwo.java
public class DlgTwo extends JDialog {
public DlgTwo(Frame owner, boolean modal) {
super(owner, modal);
initComponents();
}
private void initComponents() {
setTitle("dlgTwo");
setSize(200, 200);
setLocation(800, 200);
setLayout(new FlowLayout());
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
add(new MyCustomPanel());
}
}
LoggedUser.java
public class LoggedUser extends Observable {
private static LoggedUser instance;
public static LoggedUser getInstance() {
if (instance == null) {
instance = new LoggedUser();
}
return instance;
}
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
setChanged();
notifyObservers();
}
}
I have a instance of a custom JLabel and i want to changes its text in all frames,
A Swing component can only have a single parent. So you actually have two instances of your custom label. So updating the text in one label does not affect the other.
What you can do is create a PlainDocument to contain the text to be shared by multiple JTextFields. Then when the text is the Document is changed all the text fields will be updated.
So in the App class you would have:
private PlainDocument sharedDocument = new PlainDocument();
and you would create a method to access the Document. Maybe something like getSharedDocument().
Then in the form classes you would do something like:
//add(App.getApp().getMyCustomLabel());
JTextField textField = new JTextField( App.getApp().getSharedDocument() );
// customize text field to look like a label
textField.setBorder( null );
textField.setEditable( false );
add( textField );
Related
I am new to java swing. I am creating application for patient registration using Swing. There is a button called Clear, that button should clear the input data from the text fields.When button is InputPanel.clear() set the values correctly.But it is not updating.
My classes are below.
MainWindow class create and show the GUI.
public class MainWindow extends JFrame implements ActionListener {
private static final long serialVersionUID = 1905122041950251207L;
transient TableRowSorter<PatientTableModel> sorter;
private PatientListView patientListViewPanel = new PatientListView();
private InputPanel inputPanel = new InputPanel();
private SearchCriteriaPanel searhCriteriaPanel = new SearchCriteriaPanel(this);
public void createAndShowGUI() {
ButtonPanel btnPanel = new ButtonPanel(new MainWindow());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(600, 600);
sorter = new TableRowSorter<>(patientListViewPanel.getTableModel());
GridBagLayout gbl = new GridBagLayout();
this.setLayout(gbl);
GridBagConstraints gcon = new GridBagConstraints();
gcon.weightx = 1;
gcon.weighty = 5;
gcon.fill = GridBagConstraints.BOTH;
gcon.gridx = 0;
gcon.gridy = 0;
gcon.gridwidth = 11;
gcon.gridheight = 10;
gbl.setConstraints(inputPanel, gcon);
this.add(inputPanel);
gcon.gridx = 4;
gcon.gridy = 10;
gcon.gridwidth = 11;
gcon.gridheight = 5;
gbl.setConstraints(btnPanel, gcon);
this.add(btnPanel);
gcon.gridx = 0;
gcon.gridy = 22;
gcon.gridwidth = 11;
gcon.gridheight = 10;
gbl.setConstraints(searhCriteriaPanel, gcon);
this.add(searhCriteriaPanel);
gcon.gridx = 0;
gcon.gridy = 33;
gcon.gridwidth = 11;
gcon.gridheight = 10;
gbl.setConstraints(patientListViewPanel, gcon);
this.add(patientListViewPanel);
this.setVisible(true);
inputPanel.getNameText().addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
super.keyReleased(e);
if (inputPanel.getNameText().getText().length() > 0)
btnPanel.getSaveBtn().setEnabled(true);
}
});
patientListViewPanel.getTable().addMouseListener(new java.awt.event.MouseAdapter() {
#Override
public void mouseClicked(java.awt.event.MouseEvent evt) {
getSelectedData();
}
});
}
public MainWindow() {
super("Patient Registration");
}
#Override
public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();
switch (button.getText()) {
case "Save":
patientListViewPanel.getTableModel()
.addData(inputPanel.getData(patientListViewPanel.getTable().getRowCount()));
button.setEnabled(false);
break;
case "Clear":
inputPanel.clear();
break;
case "Search":
SearchCriteria s = new SearchCriteria(searhCriteriaPanel.getSearchNameText().getText(),
searhCriteriaPanel.getBirthYearText().getText(), searhCriteriaPanel.getMaleChkBx().isSelected(),
searhCriteriaPanel.getFemaleChkBx().isSelected());
patientListViewPanel.filter(s);
break;
default:
}
}
}
InputPanel is handle the fields and methods related to input data
public class InputPanel extends JPanel implements PropertyChangeListener {
/**
* clear fields in input panel
*/
public void clear() {
nameText.setText(" ");
phnText.setText("0");
datePickerObj.jDatePicker.getJFormattedTextField().setText("");
maleBtn.setSelected(true);
femaleBtn.setSelected(false);
adrsTxt.setText("");
statusList.setSelectedIndex(4);
}
public InputPanel() {
// fiels will be set to panel
addDataChangedListner();
isDataValid(phnText);
}
public void addDataChangedListner() {
PatientData model = new PatientData();
model.addPropertyChangeListener(this);
nameText.getDocument().addDocumentListener(new DataChangedListener(model, "name"));
phnText.getDocument().addDocumentListener(new DataChangedListener(model, "phnNumber"));
adrsTxt.getDocument().addDocumentListener(new DataChangedListener(model, "address"));
}
#Override
public void propertyChange(PropertyChangeEvent evt) {
String property = evt.getPropertyName();
String newValue = (String) evt.getNewValue();
switch (property) {
case "name":
updatedName = newValue;
break;
case "phnNumber":
updatedPhoneNumber = newValue;
break;
case "address":
updatedAddress = newValue;
break;
default:
}
}
}
Can someone help me to resolve this?
The basic functionality that you are having difficulty with is demonstrated in the following mre: (1)
import java.awt.BorderLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class MainWindow extends JFrame{
private InputPanel inputPanel;
private JButton saveBtn;
public void createAndShowGUI() {
inputPanel = new InputPanel();
saveBtn = new JButton("Save");
saveBtn.setEnabled(false);
add(saveBtn, BorderLayout.SOUTH);
JButton clearButton = new JButton("Clear");
clearButton.addActionListener(e->clearInput());
add(clearButton, BorderLayout.CENTER);
add(inputPanel, BorderLayout.NORTH);
inputPanel.getNameText().addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
super.keyReleased(e);
if (inputPanel.getNameText().getText().length() > 0) {
saveBtn.setEnabled(true);
}
}
});
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setVisible(true);
}
private void clearInput(){
inputPanel.clear();
saveBtn.setEnabled(false);
}
public MainWindow() {
createAndShowGUI();
}
public static void main(String[] args) {
new MainWindow();
}
}
class InputPanel extends JPanel {
JTextField nameText;
/**
* clear fields in input panel
*/
public void clear() {
nameText.setText(""); //use "" and not " " so text length = 0
}
public InputPanel() {
nameText = new JTextField(5);
add(nameText);
}
public JTextField getNameText() {
return nameText;
}
}
However, a better approach is to use the model to implement the change of data :
public class MainWindow extends JFrame implements PropertyChangeListener{
private InputPanel inputPanel;
private JButton saveBtn;
private final PatientData model;
public void createAndShowGUI() {
inputPanel = new InputPanel(model);
saveBtn = new JButton("Save");
saveBtn.setEnabled(false);
add(saveBtn, BorderLayout.SOUTH);
JButton clearButton = new JButton("Clear");
clearButton.addActionListener(e->clearInput());
add(clearButton, BorderLayout.CENTER);
add(inputPanel, BorderLayout.NORTH);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setVisible(true);
}
private void clearInput(){
inputPanel.clear();
}
public MainWindow() {
model = new PatientData();
model.setPropertyChangeListener(this);
createAndShowGUI();
}
#Override
public void propertyChange(PropertyChangeEvent evt) {
updateGui();
}
private void updateGui() {
if(model.getName().trim().isEmpty()){
saveBtn.setEnabled(false);
}else{
saveBtn.setEnabled(true);
}
}
public static void main(String[] args) {
new MainWindow();
}
}
class InputPanel extends JPanel implements DocumentListener{
private final JTextField nameText;
private final PatientData model;
/**
* clear fields in input panel
*/
public void clear() {
nameText.setText(""); //use "" and not " " so text length = 0
updateModel();
}
public InputPanel(PatientData model) {
this.model = model;
nameText = new JTextField("",5);
nameText.getDocument().addDocumentListener(this);
add(nameText);
}
#Override
public void changedUpdate(DocumentEvent e) {
updateModel();
}
#Override
public void removeUpdate(DocumentEvent e) {
updateModel();
}
#Override
public void insertUpdate(DocumentEvent e) {
updateModel();
}
private void updateModel() {
model.setName(nameText.getText());
}
}
class PatientData{
private String name ="";
private PropertyChangeListener listener;
public String getName() {
return name;
}
public void setPropertyChangeListener(PropertyChangeListener listener) {
this.listener = listener;
}
public void setName(String name) {
String oldName = this.name;
this.name = name;
if(listener != null) {
listener.propertyChange(new PropertyChangeEvent(this,"name", oldName, name));
}
}
}
(Test is online here)
(1) Always consider an mre when posting a question or answer.
i'm making a program, and I have 1 JFrame with JDesktopPane in this frame i open two JInternalFrame and I want to pass data between this two JInternalFrame but with JTextField.
I'm just made to pass the data but it doesn't update the JInternalFrame that i want to show. But if i choose to open again it show me the data.
Please Help me!
THANKS
In this JInternalFrame 2 i sent the data to another JInternalFrame 1
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String word = jTxtIDACA.getText();
DatosPersonales frame = new DatosPersonales();
frame.getData(word);
frame.setVisible(true);
this.getDesktopPane().add(frame);
this.dispose();
}
this is JInternalFrame 1 and i have
public void getData(String word){
initComponents();
this.word = word;
jTxtIDACA.setText(word);
}
The basic idea is you want some kind of model, which holds the data and use Observer Pattern to provide notification to interested parties when the model changes in some way.
The two JInternalFrames would then be able to share that model, one could update it and the other could monitor for changes to it (strictly speaking the relationship can work both ways, but we'll leave that alone for the moment)...
Now, because I never know what or how people might like to use the model, I always start with an interface and the provide an abstract implementation and some kind of default implementation if I feel it's required....
public interface FruitBowl {
public void addFruit(String fruit);
public void removeFruit(String fruit);
public List<String> getFruit();
public void addFruitBowlListener(FruitBowlListener listener);
public void removeFruitBowlListener(FruitBowlListener listener);
}
public abstract class AbstractFruitBowl implements FruitBowl {
private EventListenerList listenerList;
public AbstractFruitBowl() {
}
protected EventListenerList getEventListenerList() {
if (listenerList == null) {
listenerList = new EventListenerList();
}
return listenerList;
}
#Override
public void addFruitBowlListener(FruitBowlListener listener) {
getEventListenerList().add(FruitBowlListener.class, listener);
}
#Override
public void removeFruitBowlListener(FruitBowlListener listener) {
getEventListenerList().remove(FruitBowlListener.class, listener);
}
protected void fireFruitAdded(String fruit) {
FruitBowlListener[] listeners = getEventListenerList().getListeners(FruitBowlListener.class);
if (listeners.length > 0) {
FruitBowlEvent evt = new FruitBowlEvent(this, fruit);
for (FruitBowlListener listener : listeners) {
listener.fruitAdded(evt);
}
}
}
protected void fireFruitRemoved(String fruit) {
FruitBowlListener[] listeners = getEventListenerList().getListeners(FruitBowlListener.class);
if (listeners.length > 0) {
FruitBowlEvent evt = new FruitBowlEvent(this, fruit);
for (FruitBowlListener listener : listeners) {
listener.fruitRemoved(evt);
}
}
}
}
public class DefaultFruitBowl extends AbstractFruitBowl {
private List<String> fruits;
public DefaultFruitBowl() {
fruits = new ArrayList<>(25);
}
#Override
public void addFruit(String fruit) {
fruits.add(fruit);
fireFruitAdded(fruit);
}
#Override
public void removeFruit(String fruit) {
fruits.remove(fruit);
fireFruitRemoved(fruit);
}
#Override
public List<String> getFruit() {
return Collections.unmodifiableList(fruits);
}
}
Next we need to define the observer pattern contract through the use of listeners...
public class FruitBowlEvent extends EventObject {
private String fruit;
public FruitBowlEvent(FruitBowl fruitBowl, String fruit) {
super(fruitBowl);
this.fruit = fruit;
}
public FruitBowl getFruitBowl() {
return (FruitBowl)getSource();
}
public String getFruit() {
return fruit;
}
}
public interface FruitBowlListener extends EventListener {
public void fruitAdded(FruitBowlEvent evt);
public void fruitRemoved(FruitBowlEvent evt);
}
Next, we define the UI...
public class TestModel {
public static void main(String[] args) {
new TestModel();
}
public TestModel() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
FruitBowl fb = new DefaultFruitBowl();
JDesktopPane dp = new JDesktopPane() {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 200);
}
};
JInternalFrame manager = new JInternalFrame("Fruit Bowl Manager", true, true, true, true);
manager.add(new FruitBowelManagerPane(fb));
manager.setVisible(true);
manager.setBounds(0, 0, 200, 200);
JInternalFrame monitor = new JInternalFrame("Fruit Bowl Monitor", true, true, true, true);
monitor.add(new FruitBowelMonitorPane(fb));
monitor.setVisible(true);
monitor.setBounds(200, 0, 200, 200);
dp.add(manager);
dp.add(monitor);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(dp);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public abstract class AbstractFruitPane extends JPanel {
private FruitBowl fruitBowl;
public AbstractFruitPane(FruitBowl fruitBowl) {
this.fruitBowl = fruitBowl;
}
public FruitBowl getFruitBowl() {
return fruitBowl;
}
}
public class FruitBowelManagerPane extends AbstractFruitPane {
private String[] fruits = {"Banana", "Strewberry", "Pear", "Peach", "Orange"};
private JButton giver;
private JButton taker;
public FruitBowelManagerPane(FruitBowl fruitBowl) {
super(fruitBowl);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = 1;
giver = new JButton("Add fruit");
taker = new JButton("Remove fruit");
taker.setEnabled(false);
giver.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String fruit = fruits[(int)(fruits.length * Math.random())];
getFruitBowl().addFruit(fruit);
taker.setEnabled(true);
}
});
taker.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
List<String> fruits = getFruitBowl().getFruit();
String eat = fruits.get((int)(fruits.size() * Math.random()));
getFruitBowl().removeFruit(eat);
if (getFruitBowl().getFruit().isEmpty()) {
taker.setEnabled(false);
}
}
});
add(giver, gbc);
add(taker, gbc);
}
}
public class FruitBowelMonitorPane extends AbstractFruitPane {
private JLabel label;
public FruitBowelMonitorPane(FruitBowl fruitBowl) {
super(fruitBowl);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
label = new JLabel("I'm watching you...");
add(label);
fruitBowl.addFruitBowlListener(new FruitBowlListener() {
#Override
public void fruitAdded(FruitBowlEvent evt) {
label.setText("You added " + evt.getFruit());
}
#Override
public void fruitRemoved(FruitBowlEvent evt) {
if (getFruitBowl().getFruit().isEmpty()) {
label.setText("You ate all the fruit!");
} else {
label.setText("You ate my " + evt.getFruit());
}
}
});
}
}
}
Updated with combined example
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EventListener;
import java.util.EventObject;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.EventListenerList;
public class TestModel {
public static void main(String[] args) {
new TestModel();
}
public TestModel() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
FruitBowl fb = new DefaultFruitBowl();
JDesktopPane dp = new JDesktopPane() {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 200);
}
};
JInternalFrame manager = new JInternalFrame("Fruit Bowl Manager", true, true, true, true);
manager.add(new FruitBowelManagerPane(fb));
manager.setVisible(true);
manager.setBounds(0, 0, 200, 200);
JInternalFrame monitor = new JInternalFrame("Fruit Bowl Monitor", true, true, true, true);
monitor.add(new FruitBowelMonitorPane(fb));
monitor.setVisible(true);
monitor.setBounds(200, 0, 200, 200);
dp.add(manager);
dp.add(monitor);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(dp);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public abstract class AbstractFruitPane extends JPanel {
private FruitBowl fruitBowl;
public AbstractFruitPane(FruitBowl fruitBowl) {
this.fruitBowl = fruitBowl;
}
public FruitBowl getFruitBowl() {
return fruitBowl;
}
}
public class FruitBowelManagerPane extends AbstractFruitPane {
private String[] fruits = {"Banana", "Strewberry", "Pear", "Peach", "Orange"};
private JButton giver;
private JButton taker;
public FruitBowelManagerPane(FruitBowl fruitBowl) {
super(fruitBowl);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = 1;
giver = new JButton("Add fruit");
taker = new JButton("Remove fruit");
taker.setEnabled(false);
giver.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String fruit = fruits[(int) (fruits.length * Math.random())];
getFruitBowl().addFruit(fruit);
taker.setEnabled(true);
}
});
taker.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
List<String> fruits = getFruitBowl().getFruit();
String eat = fruits.get((int) (fruits.size() * Math.random()));
getFruitBowl().removeFruit(eat);
if (getFruitBowl().getFruit().isEmpty()) {
taker.setEnabled(false);
}
}
});
add(giver, gbc);
add(taker, gbc);
}
}
public class FruitBowelMonitorPane extends AbstractFruitPane {
private JLabel label;
public FruitBowelMonitorPane(FruitBowl fruitBowl) {
super(fruitBowl);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
label = new JLabel("I'm watching you...");
add(label);
fruitBowl.addFruitBowlListener(new FruitBowlListener() {
#Override
public void fruitAdded(FruitBowlEvent evt) {
label.setText("You added " + evt.getFruit());
}
#Override
public void fruitRemoved(FruitBowlEvent evt) {
if (getFruitBowl().getFruit().isEmpty()) {
label.setText("You ate all the fruit!");
} else {
label.setText("You ate my " + evt.getFruit());
}
}
});
}
}
public class FruitBowlEvent extends EventObject {
private String fruit;
public FruitBowlEvent(FruitBowl fruitBowl, String fruit) {
super(fruitBowl);
this.fruit = fruit;
}
public FruitBowl getFruitBowl() {
return (FruitBowl) getSource();
}
public String getFruit() {
return fruit;
}
}
public interface FruitBowlListener extends EventListener {
public void fruitAdded(FruitBowlEvent evt);
public void fruitRemoved(FruitBowlEvent evt);
}
public interface FruitBowl {
public void addFruit(String fruit);
public void removeFruit(String fruit);
public List<String> getFruit();
public void addFruitBowlListener(FruitBowlListener listener);
public void removeFruitBowlListener(FruitBowlListener listener);
}
public abstract class AbstractFruitBowl implements FruitBowl {
private EventListenerList listenerList;
public AbstractFruitBowl() {
}
protected EventListenerList getEventListenerList() {
if (listenerList == null) {
listenerList = new EventListenerList();
}
return listenerList;
}
#Override
public void addFruitBowlListener(FruitBowlListener listener) {
getEventListenerList().add(FruitBowlListener.class, listener);
}
#Override
public void removeFruitBowlListener(FruitBowlListener listener) {
getEventListenerList().remove(FruitBowlListener.class, listener);
}
protected void fireFruitAdded(String fruit) {
FruitBowlListener[] listeners = getEventListenerList().getListeners(FruitBowlListener.class);
if (listeners.length > 0) {
FruitBowlEvent evt = new FruitBowlEvent(this, fruit);
for (FruitBowlListener listener : listeners) {
listener.fruitAdded(evt);
}
}
}
protected void fireFruitRemoved(String fruit) {
FruitBowlListener[] listeners = getEventListenerList().getListeners(FruitBowlListener.class);
if (listeners.length > 0) {
FruitBowlEvent evt = new FruitBowlEvent(this, fruit);
for (FruitBowlListener listener : listeners) {
listener.fruitRemoved(evt);
}
}
}
}
public class DefaultFruitBowl extends AbstractFruitBowl {
private List<String> fruits;
public DefaultFruitBowl() {
fruits = new ArrayList<>(25);
}
#Override
public void addFruit(String fruit) {
fruits.add(fruit);
fireFruitAdded(fruit);
}
#Override
public void removeFruit(String fruit) {
fruits.remove(fruit);
fireFruitRemoved(fruit);
}
#Override
public List<String> getFruit() {
return Collections.unmodifiableList(fruits);
}
}
}
i got stuck at adding a button to a JComboBox editor, I succeeded to add a button but I got some issues like when I first enter to the editor an action perform event gets fired which is unacceptable and the other is I can't get the text typed.
Result:
Problems:
#Override
public Component getEditorComponent() {
return panel;
}
This is the problem, if I return panel.jtexfield I only get a text field without a button, so what's the trick here?
Here is my code
import Store.util.DatabaseHelper;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.plaf.basic.BasicComboBoxEditor;
import org.hibernate.HibernateException;
import org.netbeans.lib.awtextra.AbsoluteLayout;
public class NewComboTest extends JFrame {
private ArrayList<Object> shopCart = new ArrayList<Object>();
private JComboBox cb;
private static final Object[] comboContents = {
"First", "Second", "Third", "Fourth", "Fifth"
};
public NewComboTest() {
super("New Combo Test");
setLayout(null);
cb = new JComboBox();
cb.setRenderer(new NewComboRenderer());
cb.setEditor(new NewComboEditor());
cb.setEditable(true);
cb.setSize(new Dimension(350, 100));
for (int i = 0; i < comboContents.length; i++) {
cb.addItem(comboContents[ i]);
}
cb.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("_____________" + cb.getSelectedItem());
shopCart.add(cb.getSelectedItem());
System.out.println("items added" + shopCart);
}
});
cb.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
System.out.println("KeyReleased" + cb.getEditor().getItem().toString());
populateModel(cb.getEditor().getItem().toString());
}
});
getContentPane().add(cb, new org.netbeans.lib.awtextra.AbsoluteConstraints(320, 200, 480, 50));
setSize(1200, 450);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] arg) {
new NewComboTest();
}
private class NewComboEditor extends JPanel implements ComboBoxEditor {
JTextField tf;
JButton eraseButton;
textPanel panel = new textPanel();
public NewComboEditor() {
}
#Override
public void addActionListener(ActionListener l) {
tf.addActionListener(l);
}
#Override
public Component getEditorComponent() {
return panel;
}
public Component getEditorComponent2() {
return panel;
}
#Override
public Object getItem() {
return tf.getText();
}
#Override
public void removeActionListener(ActionListener l) {
tf.removeActionListener(l);
}
#Override
public void selectAll() {
tf.selectAll();
}
#Override
public void setItem(Object o) {
if (o != null) {
tf.setText(tf.getText());
} else {
tf.setText("");
}
}
private class textPanel extends JPanel {
JTextField jTextField1 = new JTextField();
JButton jButton1 = new JButton();
public textPanel() {
setLayout(new BorderLayout());
jButton1.setBackground(new java.awt.Color(255, 255, 255));
jButton1.setForeground(new java.awt.Color(0, 51, 51));
jButton1.setText("X");
jButton1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
jTextField1.setText("");
}
});
add(jTextField1, BorderLayout.CENTER);
add(jButton1, BorderLayout.EAST);
}
public String getText(){
return jTextField1.getText();
}
}
}
private class NewComboRenderer extends JLabel implements ListCellRenderer {
public NewComboRenderer() {
setOpaque(true);
}
public Component getListCellRendererComponent(
JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
setText(value.toString());
setBackground(isSelected ? Color.BLUE : Color.white);
setForeground(isSelected ? Color.white : Color.red);
return this;
}
}
/* public void populateModel(String text) throws HibernateException {
java.util.List l = DatabaseHelper.GetProductsBy(text);
for (Object object : l) {
cb.addItem(object);
}
ignore this its unnecessary.
*/
}
}
I also wish to set the text font and size to the same as the set up at the combo box.
The first set of problems I can see is, you define a JTextField and JButton in the NewComboEditor, but also define a textPanel, which contains all these things any way. But instead of using the components on the textPane, you use the newly created components (in the NewComboEditor) instead...In fact, I'm not even sure how that could work, because you never initilise these components (in the NewComboEditor), so there should be a NullPointerException...
If that wasn't enough problems, the JTextField and JButton aren't added to anything anyway...
Instead...
NewComboEditor shouldn't need to extend from anything (or it could extend from textPane instead if you really wanted to).
All references to the field should be made to the text field in the textPane
As an example...
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionListener;
import javax.swing.ComboBoxEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class CustomComboBoxEditor {
public static void main(String[] args) {
new CustomComboBoxEditor();
}
public CustomComboBoxEditor() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JComboBox cb = new JComboBox();
cb.addItem("Apple");
cb.addItem("Banana");
cb.addItem("Orange");
cb.setEditable(true);
cb.setEditor(new MyComboBoxEditor());
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
frame.add(cb);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MyComboBoxEditor implements ComboBoxEditor {
private EditorPane editorPane;
public MyComboBoxEditor() {
editorPane = new EditorPane();
}
#Override
public Component getEditorComponent() {
return editorPane;
}
#Override
public void setItem(Object anObject) {
editorPane.setText(anObject == null ? null : anObject.toString());
}
#Override
public Object getItem() {
return editorPane.getText();
}
#Override
public void selectAll() {
editorPane.selectAll();
}
#Override
public void addActionListener(ActionListener l) {
editorPane.addActionListener(l);
}
#Override
public void removeActionListener(ActionListener l) {
editorPane.removeActionListener(l);
}
}
public class EditorPane extends JPanel {
private JTextField field;
private JButton button;
public EditorPane() {
field = new JTextField(10);
button = new JButton("X");
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx = 0;
add(field, gbc);
gbc.weightx = 0;
gbc.fill = GridBagConstraints.NONE;
gbc.gridx++;
add(button, gbc);
}
#Override
public void addNotify() {
super.addNotify();
field.requestFocusInWindow();
}
public void selectAll() {
field.selectAll();
}
public void setText(String text) {
field.setText(text);
}
public String getText() {
return field.getText();
}
public void addActionListener(ActionListener listener) {
field.addActionListener(listener);
}
public void removeActionListener(ActionListener listener) {
field.removeActionListener(listener);
}
}
}
Now, if you want to set the field's properties to be the same as the combo box, I would simply pass a reference of the combo box to the editor and allow it to extract the properties you need (i.e. font, color, etc.)
1) how can I set Cursor to 0 possition without using Caret or Focus wrapped into invokeLater() (confortly can be solved by using #camickr Formatted Text Field Tips), is there somebody who knows another way
2) How to reset Formatter sometimes (by raising Focus by TAB from keyboard), reset doesn't works and on focusLost (empty field) Formatter returns/reincarnated chars or String back (last know before setText("");),
Note: know code or following code is only this way, about how to reset Formatter from OTN, but their terrible search rulles ...., only code (question or answer by Jeanette???)
import java.awt.event.*;
import java.beans.*;
import java.text.ParseException;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.Document;
public class FormattedNull {
private JFormattedTextField field;
private JButton focusButton;
private JComponent createContent() {
JComponent content = new JPanel();
field = new JFormattedTextField(new Integer(55));
field.setColumns(20);
field.addPropertyChangeListener(getPropertyChangeListener());
field.getDocument().addDocumentListener(getDocumentListener());
content.add(field);
focusButton = new JButton("just something focusable");
focusButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
field.setValue(0);
field.requestFocusInWindow();
}
});
content.add(focusButton);
return content;
}
protected void maybeCommitEdit(Document document) {
try {
field.commitEdit();
} catch (ParseException e) {
// uncomment to map empty string to null
if (field.getText().length() == 0) {
field.setValue(null);
}
}
}
/*public void commitEdit() throws ParseException {
if(allowsNull() && isBlank()) {
setValue(null);
}
else {
super.commitEdit();
}
}*/
private PropertyChangeListener getPropertyChangeListener() {
PropertyChangeListener propertyChangeListener = new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if ("value".equals(evt.getPropertyName())) {
matchValueChanged(evt.getNewValue());
}
}
};
return propertyChangeListener;
}
protected void matchValueChanged(Object value) {
System.out.println("got new value: " + value);
}
private DocumentListener getDocumentListener() {
DocumentListener documentListener = new DocumentListener() {
#Override
public void removeUpdate(DocumentEvent e) {
maybeCommitEdit(e.getDocument());
}
#Override
public void insertUpdate(DocumentEvent e) {
maybeCommitEdit(e.getDocument());
}
#Override
public void changedUpdate(DocumentEvent e) {
}
};
return documentListener;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new FormattedNull().createContent());
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
});
}
}
attached images are based on my sscce
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.text.MaskFormatter;
public class TestTest {
private JFormattedTextField myFormattedField1 = new JFormattedTextField(createFormatter("AAAAAAAAAAAA"));
private JFormattedTextField myFormattedField2 = new JFormattedTextField(createFormatter("AAAAAAAAAAAA"));
private JFormattedTextField myFormattedField3 = new JFormattedTextField(createFormatter("AAAAAAAAAAAA"));
private JFormattedTextField myFormattedField4 = new JFormattedTextField(createFormatter("AAAAAAAAAAAA"));
private JButton jb = new JButton("Reset to Default");
private JFrame frame = new JFrame("Text Test");
public TestTest() {
myFormattedField1.setText("ABCDEFGHIJKL");
myFormattedField2.setText("ABCDEFGHIJKL");
myFormattedField3.setText("ABCDEFGHIJKL");
myFormattedField4.setText("ABCDEFGHIJKL");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(150, 150);
frame.setLayout(new GridLayout(5, 0));
frame.add(jb);
frame.add(myFormattedField1);
frame.add(myFormattedField2);
frame.add(myFormattedField3);
frame.add(myFormattedField4);
jb.addActionListener(new java.awt.event.ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
myFormattedField1.setText("");
myFormattedField2.setText("");
myFormattedField3.setText("");
myFormattedField4.setText("");
}
});
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
TestTest textTest = new TestTest();
}
protected MaskFormatter createFormatter(String s) {
MaskFormatter formatter = null;
try {
formatter = new MaskFormatter(s);
} catch (java.text.ParseException exc) {
System.err.println("formatter is bad: " + exc.getMessage());
}
return formatter;
}
}
On Mac OS, the default behavior of the UI delegate, com.apple.laf.AquaTextFieldF, is similar to CaretPositionListener:
Tab or Shift-Tab: place the caret at the beginning of the field.
Click: briefly place the caret at the beginning of the field and then move it to the click point.
IMO, the CaretPositionListener does the latter much more smoothly.
The default behavior of JFormattedTextField on focus lost is COMMIT_OR_REVERT. In the example below, Tab though the first, invalid field to see the effect. The formatter can neither commit nor revert to the invalid value, so it substitutes MASK.length() spaces. This value is valid, if a little obscure.
Addendum: I've updated the code below to allow changing the setFocusLostBehavior().
Code:
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.text.MaskFormatter;
/** #see http://stackoverflow.com/questions/7378821 */
public class TrashTest {
private static final String MASK = "########";
private static final String DEFAULT = "01234567";
private static final String BOGUS = "0123456";
private JFormattedTextField jtf1 = createField();
private JFormattedTextField jtf2 = createField();
private JFormattedTextField jtf3 = createField();
private JFormattedTextField jtf4 = createField();
private JButton reset = new JButton("Reset to Default");
private JComboBox combo = new JComboBox();
private JFrame frame = new JFrame("Text Test");
public TrashTest() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(150, 150);
frame.setLayout(new GridLayout(0, 1));
frame.add(reset);
frame.add(jtf1);
frame.add(jtf2);
frame.add(jtf3);
frame.add(jtf4);
frame.add(combo);
this.initFields();
reset.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
initFields();
}
});
for (Edit e : Edit.values()) {
combo.addItem(e);
}
combo.setSelectedIndex(jtf1.getFocusLostBehavior());
combo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Edit current = (Edit) combo.getSelectedItem();
jtf1.setFocusLostBehavior(current.value);
}
});
frame.pack();
frame.setVisible(true);
}
private void initFields() {
jtf1.setText(BOGUS);
jtf2.setText(DEFAULT);
jtf3.setText(DEFAULT);
jtf4.setText(DEFAULT);
}
protected JFormattedTextField createField() {
MaskFormatter formatter = null;
try {
formatter = new MaskFormatter(MASK);
} catch (java.text.ParseException e) {
e.printStackTrace(System.out);
}
JFormattedTextField jtf = new JFormattedTextField(formatter);
return jtf;
}
enum Edit {
COMMIT(JFormattedTextField.COMMIT),
COMMIT_OR_REVERT(JFormattedTextField.COMMIT_OR_REVERT),
REVERT(JFormattedTextField.REVERT),
PERSIST(JFormattedTextField.PERSIST);
private int value;
private Edit(int n) {
this.value = n;
}
public static Edit getEnum(int n) {
for (Edit e : Edit.values()) {
if (e.value == n) {
return e;
}
}
return Edit.COMMIT_OR_REVERT;
}
}
public static void main(String[] args) {
TrashTest textTest = new TrashTest();
}
}
Greetings,
I have been studying Obserser/Observable implementation to Model-View-Controller.
I may also misused the pattern but here's what I've done so far.
In my code. When Submit was press, it triggers the makeChange() of the Model.
But never triggers the update() of Testing.
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
public class Testing implements Observer {
public Testing() {
model.addObserver(this);
loadListener1();
}
private void loadListener1() {
view1.submitButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
model = new Model(view1.data1Field.getText(), view1.data2Field.getText());
model.makeChange();
model.notifyObservers();
}
});
}
public void update(Observable o, Object arg) { System.out.println("Notify - Observer"); }
public static void main(String[] a) { Testing testing = new Testing(); }
private View view1 = new View("1");
private Model model = new Model();
}
class View extends JFrame {
public View(String frame) {
super("Frame: " + frame);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300, 300);
setVisible(true);
setLayout(new GridLayout(3, 2));
add(data1Label); add(data1Field);
add(data2Label); add(data2Field);
add(submitButton); add(cancelButton);
}
private final JLabel data1Label = new JLabel("Data1");
private final JLabel data2Label = new JLabel("Data2");
public final JTextField data1Field = new JTextField();
public final JTextField data2Field = new JTextField();
public final JButton submitButton = new JButton("Submit");
public final JButton cancelButton = new JButton("Cancel");
}
class Model extends Observable {
public Model() { }
public Model(String data1, String data2) {
setData1(data1);
setData2(data2);
}
public String getData1() { return data1; }
public final void setData1(String data1) { this.data1 = data1; }
public String getData2() { return data2; }
public final void setData2(String data2) { this.data2 = data2; }
public void makeChange() {
setChanged();
notifyObservers();
System.out.println("Notify - Observable");
}
private String data1;
private String data2;
}
Can you guide me thru?
Your reply is highly appreciated.
Thanks,
Cyril H.
In constructor of clas Testing your register itself to instance of Model that is created during field initialisation.
In actionPerformed method of submit button you creatd a new instance of Model and later call on this new instance the method notifyObservers which has no registered observers!
Try this code:
private void loadListener1() {
view1.submitButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
model.setData1(view1.data1Field.getText()),
model.setData2(view1.data2Field.getText());
model.makeChange();
}
});
}