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.
Related
In this program I'm trying to input a functionality to start game, where if I click start game (MainMenu) a new jpanel opens up (MainGame), creating another jpanel that creates jbuttons in a grid. If i go back, and click start game again, a new grid should generate instead of the previous one, effectively starting a "new game". the problem is that if i go back and click on new game again, the program creates 2 grids.
I've tried removing the instance of the grid panel with = null but it doesn't work
Main function:
import javax.swing.*;
import java.awt.*;
import java.awt.CardLayout;
public class Game extends JFrame {
MainMenu mainMenu;
Settings settings;
MainGame mainGame;
CardLayout cl;
JPanel container;
public Game(){
setSize(900,900); //have all as seperate classes
setDefaultCloseOperation(3); //cl call container
container = new JPanel(); //container call menu1 and menu2
cl = new CardLayout();
mainMenu = new MainMenu();
settings = new Settings();
mainGame = new MainGame();
mainMenu.setSettings(settings);
settings.setMainMenu(mainMenu);
settings.setMainGame(mainGame);
mainMenu.setMainGame(mainGame);
mainGame.setMainMenu(mainMenu);
mainGame.setSettings(settings);
container.setLayout(cl); //this stays here i think
//add setter for main game here
container.add(mainMenu,"1");
container.add(settings,"2");
container.add(mainGame,"3");
mainMenu.setContainer(container);
mainMenu.setCl(cl);
settings.setContainer(container);
settings.setCl(cl);
mainGame.setContainer(container);
mainGame.setCl(cl);
cl.show(container, "1");
add(container,BorderLayout.CENTER);
}
public static void main(String[] args) {
Game game = new Game();
game.setVisible(true);
}
}
main game class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class MainGame extends JPanel {
MainMenu mainMenu;
Settings settings;
CardLayout cl;
JPanel container;
String rows;
String columns;
public void setMainMenu(MainMenu mainMenu) {
this.mainMenu = mainMenu;
}
public void setSettings(Settings settings) {
this.settings = settings;
}
public void setCl(CardLayout cl) {
this.cl = cl;
}
public void setContainer(JPanel container) {
this.container = container;
}
public void setRows(String rows) {
this.rows = rows;
}
public void setColumns(String columns) {
this.columns = columns;
}
public MainGame(){
JPanel north = new JPanel();
north.setLayout(new FlowLayout());
ReturnAction returnAl = new ReturnAction();
JButton Return2 = new JButton("Return");
Return2.addActionListener(returnAl);
north.add(Return2);
add(north);
}
class ReturnAction implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
cl.show(container,"1");
}
}
}
Main menu class (this one contains the game generation part):
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
public class MainMenu extends JPanel {
JPanel grid = new JPanel();
MainGame mainGame;
Settings settings;
CardLayout cl;
JPanel container;
String rows;
String columns;
boolean checkexists = false;
int rownumber;
int columnnumber;
public void setMainGame(MainGame mainGame) {
this.mainGame = mainGame;
}
public void setCl(CardLayout cl) {
this.cl = cl;
}
public void setContainer(JPanel container) {
this.container = container;
}
public void setSettings(Settings settings) {
this.settings = settings;
}
public void setRows(String rows) {
this.rows = rows;
}
public void setColumns(String columns) {
this.columns = columns;
}
public MainMenu() {
setLayout(new GridLayout(3, 1));
JButton Newgame = new JButton("New Game");
JButton Cont = new JButton("Continue");
JButton Sett = new JButton("Settings");
add(Newgame);
add(Cont);
SwitchMenu1 switchMenu1 = new SwitchMenu1();
SwitchMenu2 switchMenu2 = new SwitchMenu2();
GenerateGame generateGame = new GenerateGame();
Newgame.addActionListener(switchMenu2);
Newgame.addActionListener(generateGame);
Sett.addActionListener(switchMenu1);
add(Sett);
}
class SwitchMenu1 implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
cl.show(container, "2");
}
}
class SwitchMenu2 implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
cl.show(container, "3");
}
}
class GenerateGame implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (checkexists == true){
grid = null;
grid = new JPanel();
}
try {
rownumber = Integer.parseInt(rows);
} catch (NumberFormatException be) {
rownumber = 10;
}
try {
columnnumber = Integer.parseInt(columns);
} catch (NumberFormatException be) {
columnnumber = 10;
}
Random rand = new Random();
int randomnumber;
String Letters = "AAIIOOUUEEABCDEFGHIJKLMNOPQRSTUVWXYZ";
grid.setLayout(new GridLayout(rownumber, columnnumber));
JButton[][] gridbutton = new JButton[rownumber][columnnumber];
MainbuttonAL mainbuttonAL = new MainbuttonAL();
for (int i = 0; i < rownumber; i++) {
for (int j = 0; j < columnnumber; j++) {
if (checkexists == true){
gridbutton[i][j] = null;
}
randomnumber = rand.nextInt(Letters.length());
gridbutton[i][j] = new JButton("" + Letters.charAt(randomnumber));
gridbutton[i][j].addActionListener(mainbuttonAL);
grid.add(gridbutton[i][j]);
}
}
mainGame.add(grid);
checkexists = true;
}
}
class MainbuttonAL implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
}
}
}
settings class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
public class MainMenu extends JPanel {
JPanel grid = new JPanel();
MainGame mainGame;
Settings settings;
CardLayout cl;
JPanel container;
String rows;
String columns;
boolean checkexists = false;
int rownumber;
int columnnumber;
public void setMainGame(MainGame mainGame) {
this.mainGame = mainGame;
}
public void setCl(CardLayout cl) {
this.cl = cl;
}
public void setContainer(JPanel container) {
this.container = container;
}
public void setSettings(Settings settings) {
this.settings = settings;
}
public void setRows(String rows) {
this.rows = rows;
}
public void setColumns(String columns) {
this.columns = columns;
}
public MainMenu() {
setLayout(new GridLayout(3, 1));
JButton Newgame = new JButton("New Game");
JButton Cont = new JButton("Continue");
JButton Sett = new JButton("Settings");
add(Newgame);
add(Cont);
SwitchMenu1 switchMenu1 = new SwitchMenu1();
SwitchMenu2 switchMenu2 = new SwitchMenu2();
GenerateGame generateGame = new GenerateGame();
Newgame.addActionListener(switchMenu2);
Newgame.addActionListener(generateGame);
Sett.addActionListener(switchMenu1);
add(Sett);
}
class SwitchMenu1 implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
cl.show(container, "2");
}
}
class SwitchMenu2 implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
cl.show(container, "3");
}
}
class GenerateGame implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (checkexists == true){
grid = null;
grid = new JPanel();
}
try {
rownumber = Integer.parseInt(rows);
} catch (NumberFormatException be) {
rownumber = 10;
}
try {
columnnumber = Integer.parseInt(columns);
} catch (NumberFormatException be) {
columnnumber = 10;
}
Random rand = new Random();
int randomnumber;
String Letters = "AAIIOOUUEEABCDEFGHIJKLMNOPQRSTUVWXYZ";
grid.setLayout(new GridLayout(rownumber, columnnumber));
JButton[][] gridbutton = new JButton[rownumber][columnnumber];
MainbuttonAL mainbuttonAL = new MainbuttonAL();
for (int i = 0; i < rownumber; i++) {
for (int j = 0; j < columnnumber; j++) {
if (checkexists == true){
gridbutton[i][j] = null;
}
randomnumber = rand.nextInt(Letters.length());
gridbutton[i][j] = new JButton("" + Letters.charAt(randomnumber));
gridbutton[i][j].addActionListener(mainbuttonAL);
grid.add(gridbutton[i][j]);
}
}
mainGame.add(grid);
checkexists = true;
}
}
class MainbuttonAL implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
}
}
}
what method can i employ to regenerate a grid?
In general, you should be working on the concept of decoupling your views and your data, this means that you could have a "game model" which could be applied to a view and the view would then modify itself based on model properties, this is commonly known as "model - view - controller".
The problem is, however, you never remove grid from it's parent container when you create a new game
if (checkexists == true){
grid = null;
grid = new JPanel();
}
Instead, before you re-intialise the grid, you should remove from it's parent container
if (grid != null) {
mainGame.remove(grid);
grid = null;
grid = new JPanel();
}
or you could just remove the components from the grid panel itself
grid.removeAll();
A different approach...
At all stages you should be trying to decouple you objects and workflows from each other, so that it's easier to change any one part without having adverse effects on the other parts of the system or workflow.
Looking at you code, for example, the navigation decisions are tightly coupled to each panel/view, but in reality, they shouldn't know or care about how the navigation works (or the fact that there are other views), they should just do there job.
You can decouple this workflow through the use of delegation (backed by an observer). This basically means that the individual view doesn't care "how" the navigation works, only that when it makes a request for some action to be taken, it happens.
You should take the time to read through...
Model-View-Controller
Observer Pattern
Dependency Injection in Java
But how does this help you? Well, it will help you all the time!
Lets start with the "game" itself. The first thing we need is some kind of container to hold the data base logic for the game, so based on your current code, it might look something like...
public interface GameModel {
public int getRows();
public int getColumns();
}
I know, amazing isn't it, but this interface would grow to hold the logic required to run your game.
Now, we can apply this to the GamePanel
public class GamePane extends JPanel {
public interface Obsever {
public void back(GamePane source);
}
private GameModel model;
private Obsever obsever;
private JPanel contentPane;
private ActionListener buttonActionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
didTap(e.getActionCommand());
}
};
public GamePane(Obsever obsever) {
this.obsever = obsever;
setLayout(new BorderLayout());
contentPane = new JPanel();
add(new JScrollPane(contentPane));
JButton backButton = new JButton("<< Back");
backButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
obsever.back(GamePane.this);
}
});
JPanel bannerPane = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.anchor = GridBagConstraints.LINE_END;
bannerPane.add(backButton, gbc);
add(bannerPane, BorderLayout.NORTH);
}
#Override
public Dimension getPreferredSize() {
// Bunch of things we could do here, but this basically
// acts as a stand in for CardLayout, otherwise the primary
// view will be to small
return new Dimension(800, 800);
}
public void setModel(GameModel model) {
if (this.model == model) {
// Do nothing, nothings changed
return;
}
this.model = model;
buildUI();
}
protected void buildUI() {
contentPane.removeAll();
if (model == null) {
return;
}
String Letters = "AAIIOOUUEEABCDEFGHIJKLMNOPQRSTUVWXYZ";
Random rnd = new Random();
JButton[][] gridbutton = new JButton[model.getRows()][model.getColumns()];
contentPane.setLayout(new GridLayout(model.getRows(), model.getColumns()));
//Game.MainMenu.MainbuttonAL mainbuttonAL = new Game.MainMenu.MainbuttonAL();
for (int i = 0; i < model.getRows(); i++) {
for (int j = 0; j < model.getColumns(); j++) {
int randomnumber = rnd.nextInt(Letters.length());
gridbutton[i][j] = new JButton("" + Letters.charAt(randomnumber));
//gridbutton[i][j].addActionListener(mainbuttonAL);
contentPane.add(gridbutton[i][j]);
}
}
}
protected void didTap(String action) {
}
}
Now, the nice "juicy" part is in the buildUI which is called by setModel when the model changes. This just re-builds the UI based on the GameModel properties.
As for the navigation concept, you can see part of it in the GamePane via its Observer interface. I started by creating a seperate class to handle the navigation workflows.
This means that the "how" or "implementation detail" is decoupled or hidden from the other parts of the system. Instead, it makes use of simple observer/delegation workflow.
Each view provides an Observer (for the what of a better name) which describes the navigation actions it needs performed. For example, both the SettingsPane and GamePane simply have back. They don't care what came before them, that's up to the navigation controller to decide.
public class NavigationPane extends JPanel {
enum View {
MAIN_MENU, GAME, SETTINGS
}
private CardLayout cardLayout;
private GameModel model;
private GamePane gamePane;
// Just for testing...
private Random rnd = new Random();
public NavigationPane() {
cardLayout = new CardLayout();
setLayout(cardLayout);
add(new MainMenu(new MainMenu.Observer() {
#Override
public void newGame(MainMenu source) {
gamePane.setModel(createModel());
navigateTo(View.GAME);
}
#Override
public void continueGame(MainMenu source) {
// Because it's possible to push continue
// without starting a game
// It might be possible have a "menu" model
// which can be used to change the enabled state of
// the continue button based on the state of the
// game
gamePane.setModel(getOrCreateGameModel());
navigateTo(View.GAME);
}
#Override
public void settingsGame(MainMenu source) {
navigateTo(View.SETTINGS);
}
}), View.MAIN_MENU);
gamePane = new GamePane(new GamePane.Obsever() {
#Override
public void back(GamePane source) {
navigateTo(View.MAIN_MENU);
}
});
add(gamePane, View.GAME);
add(new SettingsPane(new SettingsPane.Obsever() {
#Override
public void back(SettingsPane source) {
navigateTo(View.MAIN_MENU);
}
}), View.SETTINGS);
navigateTo(View.MAIN_MENU);
}
protected GameModel createModel() {
model = new DefaultGameModel(rnd.nextInt(9) + 2, rnd.nextInt(9) + 2);
return model;
}
protected GameModel getOrCreateGameModel() {
if (model == null) {
model = createModel();
}
return model;
}
protected void add(Component component, View view) {
add(component, view.name());
}
protected void navigateTo(View view) {
cardLayout.show(this, view.name());
}
}
Runnable example...
So, that's a lot of out-of-context code. The below is basically an example of one possible approach you could take to further reduce some of the clutter and coupling which is growing in your code base at this time.
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new NavigationPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class NavigationPane extends JPanel {
enum View {
MAIN_MENU, GAME, SETTINGS
}
private CardLayout cardLayout;
private GameModel model;
private GamePane gamePane;
// Just for testing...
private Random rnd = new Random();
public NavigationPane() {
cardLayout = new CardLayout();
setLayout(cardLayout);
add(new MainMenu(new MainMenu.Observer() {
#Override
public void newGame(MainMenu source) {
gamePane.setModel(createModel());
navigateTo(View.GAME);
}
#Override
public void continueGame(MainMenu source) {
// Because it's possible to push continue
// without starting a game
// It might be possible have a "menu" model
// which can be used to change the enabled state of
// the continue button based on the state of the
// game
gamePane.setModel(getOrCreateGameModel());
navigateTo(View.GAME);
}
#Override
public void settingsGame(MainMenu source) {
navigateTo(View.SETTINGS);
}
}), View.MAIN_MENU);
gamePane = new GamePane(new GamePane.Obsever() {
#Override
public void back(GamePane source) {
navigateTo(View.MAIN_MENU);
}
});
add(gamePane, View.GAME);
add(new SettingsPane(new SettingsPane.Obsever() {
#Override
public void back(SettingsPane source) {
navigateTo(View.MAIN_MENU);
}
}), View.SETTINGS);
navigateTo(View.MAIN_MENU);
}
protected GameModel createModel() {
model = new DefaultGameModel(rnd.nextInt(9) + 2, rnd.nextInt(9) + 2);
return model;
}
protected GameModel getOrCreateGameModel() {
if (model == null) {
model = createModel();
}
return model;
}
protected void add(Component component, View view) {
add(component, view.name());
}
protected void navigateTo(View view) {
cardLayout.show(this, view.name());
}
}
public class MainMenu extends JPanel {
public interface Observer {
public void newGame(MainMenu source);
public void continueGame(MainMenu source);
public void settingsGame(MainMenu source);
}
private Observer observer;
public MainMenu(Observer observer) {
this.observer = observer;
setLayout(new GridBagLayout());
JButton newGameButton = new JButton("New Game");
JButton continueButton = new JButton("Continue");
JButton settingsButton = new JButton("Settings");
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(newGameButton, gbc);
add(continueButton, gbc);
add(settingsButton, gbc);
newGameButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
observer.newGame(MainMenu.this);
}
});
continueButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
observer.continueGame(MainMenu.this);
}
});
settingsButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
observer.settingsGame(MainMenu.this);
}
});
}
}
public class SettingsPane extends JPanel {
public interface Obsever {
public void back(SettingsPane source);
}
public SettingsPane(Obsever obsever) {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(new JLabel("All your setting belong to us"), gbc);
JButton backButton = new JButton("<< Back");
backButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
obsever.back(SettingsPane.this);
}
});
add(backButton, gbc);
}
}
public interface GameModel {
public int getRows();
public int getColumns();
}
public class DefaultGameModel implements GameModel {
private int rows;
private int columns;
public DefaultGameModel(int rows, int columns) {
this.rows = rows;
this.columns = columns;
}
#Override
public int getRows() {
return rows;
}
#Override
public int getColumns() {
return columns;
}
}
public class GamePane extends JPanel {
public interface Obsever {
public void back(GamePane source);
}
private GameModel model;
private Obsever obsever;
private JPanel contentPane;
private ActionListener buttonActionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
didTap(e.getActionCommand());
}
};
public GamePane(Obsever obsever) {
this.obsever = obsever;
setLayout(new BorderLayout());
contentPane = new JPanel();
add(new JScrollPane(contentPane));
JButton backButton = new JButton("<< Back");
backButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
obsever.back(GamePane.this);
}
});
JPanel bannerPane = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.anchor = GridBagConstraints.LINE_END;
bannerPane.add(backButton, gbc);
add(bannerPane, BorderLayout.NORTH);
}
#Override
public Dimension getPreferredSize() {
// Bunch of things we could do here, but this basically
// acts as a stand in for CardLayout, otherwise the primary
// view will be to small
return new Dimension(800, 800);
}
public void setModel(GameModel model) {
if (this.model == model) {
// Do nothing, nothings changed
return;
}
this.model = model;
buildUI();
}
protected void buildUI() {
contentPane.removeAll();
if (model == null) {
return;
}
String Letters = "AAIIOOUUEEABCDEFGHIJKLMNOPQRSTUVWXYZ";
Random rnd = new Random();
JButton[][] gridbutton = new JButton[model.getRows()][model.getColumns()];
contentPane.setLayout(new GridLayout(model.getRows(), model.getColumns()));
//Game.MainMenu.MainbuttonAL mainbuttonAL = new Game.MainMenu.MainbuttonAL();
for (int i = 0; i < model.getRows(); i++) {
for (int j = 0; j < model.getColumns(); j++) {
int randomnumber = rnd.nextInt(Letters.length());
gridbutton[i][j] = new JButton("" + Letters.charAt(randomnumber));
//gridbutton[i][j].addActionListener(mainbuttonAL);
contentPane.add(gridbutton[i][j]);
}
}
}
protected void didTap(String action) {
}
}
}
I am working on a school project using BlueJay and I have created two classes in package Logic which are the Game class, and the VectorGames class.
In my package GUI, I created a class called AddGame and ViewGame class.
The issue that I have encountered is that, when I click the Save Button on Addgame, it saves the file only once. When I try to save it doesn't do or say anything it just stays there returning nothing. Another issue encountered is that on ViewGame, the gameType column is remaining empty ( this is from combo type box )
AddGame code :
package GUI;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import Logic.*;
public class AddGame extends JFrame implements ActionListener{
private JPanel north, south, east, west, center;
private JLabel titleLabel, westLabel, eastLabel;
private JTextField gameNameFld, gameKeyFld;
private JComboBox gameTypeCombo;
private JButton saveButton, clearButton;
private VectorGames vg;
public AddGame(){
super("Adding a Game");
this.setLayout(new BorderLayout());
vg = new VectorGames();
vg.readFromFile();
//north panel
north = new JPanel();
this.add(north,BorderLayout.NORTH);
titleLabel = new JLabel("Add a game below");
titleLabel.setFont(new Font("Verdana",Font.BOLD,20));
titleLabel.setForeground(Color.black);
north.add(titleLabel);
//west and east panels
west = new JPanel();
east = new JPanel();
this.add(west, BorderLayout.WEST);
this.add(east, BorderLayout.EAST);
westLabel = new JLabel(" ");
eastLabel = new JLabel(" ");
west.add(westLabel);
east.add(eastLabel);
//center panel
center = new JPanel();
this.add(center, BorderLayout.CENTER);
center.setLayout(new GridLayout(4,2,0,20));
gameNameFld = new JTextField();
gameKeyFld = new JTextField();
gameTypeCombo = new JComboBox();
gameTypeCombo.setModel(new DefaultComboBoxModel(new String[]
{"<--Select-->", "Arcade", "Puzzle", "Adventure", "Shooter", "Roleplay"}));
center.add(createLabel("Game Name"));
center.add(gameNameFld);
center.add(createLabel("Game Key"));
center.add(gameKeyFld);
center.add(createLabel("Game Type"));
center.add(gameTypeCombo);
//south panel
south = new JPanel();
south.setLayout(new FlowLayout());
this.add(south, BorderLayout.SOUTH);
clearButton = new JButton("Clear");
south.add(clearButton);
clearButton.addActionListener(this);
saveButton = new JButton("Save");
south.add(saveButton);
saveButton.addActionListener(this);
this.setSize(300,400);
this.setLocation(50,50);
this.setVisible(true);
}
private JLabel createLabel(String title){
return new JLabel(title);
}
private void clearFields(){
gameNameFld.setText("");
gameKeyFld.setText("");
gameTypeCombo.setSelectedIndex(0);
}
private boolean validateForm(){
boolean flag = false;
if(gameNameFld.getText().equals("")||gameKeyFld.getText().equals("")||
gameTypeCombo.getSelectedIndex()==0){
flag = true;
}
return flag;
}
public void actionPerformed(ActionEvent event){
if (event.getSource() == clearButton){
clearFields();
}
if(event.getSource() == saveButton){
if(validateForm() == true){
JOptionPane.showMessageDialog(null,"You have empty fields",
"Empty Fields", JOptionPane.ERROR_MESSAGE);
} else if(vg.checkGamebyGameKey(gameKeyFld.getText()) == true){
JOptionPane.showMessageDialog(null,"Game Key already exists!",
"Game Key Check", JOptionPane.ERROR_MESSAGE);
} else {
Game tempGame = new Game(gameNameFld.getText(),gameKeyFld.getText(),
(String)gameTypeCombo.getSelectedItem());
vg.addGame(tempGame);
vg.saveToFile();
JOptionPane.showMessageDialog(null, "Game added successfully!", "Adding a Game",
JOptionPane.INFORMATION_MESSAGE);
clearFields();
}
}
}
}
ViewGame code:
package GUI;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import Logic.*;
public class ViewGame extends JFrame {
private JTable table;
private VectorGames vg;
public ViewGame(){
super("Viewing Games by Name");
this.setLayout(new BorderLayout());
vg = new VectorGames();
vg.readFromFile();
vg.sortGamesByName();
int numOfGames = vg.getVectorSize();
int count = 0;
Game tempGame = new Game();
String[] tableHeader = {"Game Name", "Game Type", "Game Key"};
Object [][] tableContent = new Object[numOfGames][3];
for(int i = 0; i < numOfGames; i++){
tempGame = vg.getGamesByIndex(count);
tableContent[i][0] = tempGame.getGameName();
tableContent[i][2] = tempGame.getGameType();
tableContent[i][1] = tempGame.getGameKey();
}
table = new JTable (tableContent, tableHeader);
JScrollPane scrollPane = new JScrollPane(table);
table.setPreferredScrollableViewportSize(new Dimension(500, 400));
this.add(table.getTableHeader(), BorderLayout.NORTH);
this.add(table, BorderLayout.CENTER);
this.setSize(500,600);
this.setLocation(100,50);
this.setVisible(true);
}
}
Game code:
package Logic;
import java.io.*;
public class Game implements Serializable{ // Using serializable to allow easy save and read access
//Initializing variables related to Game
private String gameName, gameKey, gameType;
//Creating a constructor with the parameters for class Games
public Game(String gameName, String gamekey, String gameType){
setGameName(gameName);
setGameKey(gameKey);
setGameType(gameType);
}
//Setting up a parameterless constructor for class Games
public Game(){
}
public String getGameName(){//Get Method for gameName
return gameName;
}
public String getGameKey(){//Get Method for gameKey
return gameKey;
}
public String getGameType(){//Get Method for gameType
return gameType;
}
public void setGameName(String gameName){//Set Method for gameName
this.gameName = gameName;
}
public void setGameKey(String gameKey){//Set Method for gameKey
this.gameKey = gameKey;
}
public void setGameType(String gameType){//Set Method for gameType
this.gameType = gameType;
}
public String toString(){
return "Game Name : " + gameName + "\nGame Key : "
+ gameKey + "\nGame Type ; " + gameType;
}
}
VectorGames code:
package Logic;
import java.util.*;
import java.io.*;
import java.lang.*;
public class VectorGames extends IOException{
/* Add a Game, Remove a Game, getVectorGame Size, print allGamesAvailable,
* saveToFile , searchGame and return boolean literal, searchGame and return
* client object, sort games, readFromFile.
*
*/
private Vector<Game> games;
public VectorGames(){
games = new Vector<Game>();
}
//Adding a Game
public void addGame(Game game){
games.add(game);
}
public void deleteGame(Game game){
games.remove(game);
}
public int getVectorSize(){
return games.size();
}
public void clearVector(){
games.clear();
}
public void printGames(){
for(Game tempGame : games){
System.out.println(tempGame.toString());
System.out.println("");
}
}
public Game getGamesByIndex(int i){
Game tempGame = new Game();
if (i < getVectorSize()){
tempGame = games.get(i);
}
return tempGame;
}
public void sortGamesByName(){
Game currentGame = new Game();
Game nextGame = new Game();
Game tempGame = new Game();
for(int i = 0; i < getVectorSize(); i++){
for(int j = 0; j < getVectorSize()-i-1; j++){
currentGame = games.elementAt(j);
nextGame = games.elementAt(j+1);
if(currentGame.getGameName().compareTo(nextGame.getGameName())>0){
tempGame = currentGame;
games.setElementAt(nextGame, j);
games.setElementAt(tempGame, j+1);
}
}
}
}
public boolean checkGamebyGameKey(String gameKey){
boolean flag = false;
for(Game tempGames : games){
if(tempGames .getGameKey().equals(gameKey)){
flag = true;
}
}
return flag;
}
public Game accessGameByGameName(String gameName){
Game foundGameName = new Game();
for(Game tempGames: games){
if(tempGames.getGameName().equals(gameName)){
foundGameName = tempGames;
}
}
return foundGameName;
}
public void saveToFile(){
try{
File f = new File("C:/Users/Denis/Desktop/GameStore/Databases","gameList.obj");
FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(games);
oos.flush();
oos.close();
}catch (IOException ioe){
System.err.println("Cannot write to file!");
}
}
public void readFromFile(){
try{
File f = new File("C:/Users/Denis/Desktop/GameStore/Databases","gameList.obj");
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);
games = (Vector<Game>) ois.readObject();
ois.close();
} catch (FileNotFoundException fnfe){
System.err.println("Cannot find file!");
}catch (IOException ioe){
System.err.println("Cannot read from file!");
}catch(ClassNotFoundException cnfe){
System.err.println("Client class cannot be found!");
}
}
}
Main class: GameCenter
public class GameCenter extends JFrame {
public static void main(String... args) {
SwingUtilities.invokeLater(() -> new GameCenter().setVisible(true));
}
public GameCenter() {
super("Game Center");
init();
}
private void init() {
setLayout(new BorderLayout(5, 5));
Model model = new Model();
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.add("Add", new AddTabPanel(model));
tabbedPane.add("View", new ViewTabPanel(model));
add(tabbedPane, BorderLayout.CENTER);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(400, 500);
setMinimumSize(new Dimension(400, 500));
setResizable(false);
}
}
Game entity:
final class Game {
private static final Pattern RECORD = Pattern.compile("(?<key>.+)\\|(?<name>.+)\\|(?<type>.+)");
private final String name;
private final String key;
private final String type;
public static Game createFromRecord(String str) {
Matcher matcher = RECORD.matcher(str);
return matcher.matches() ? new Game(matcher.group("name"), matcher.group("key"), matcher.group("type")) : null;
}
public Game(String name, String key, String type) {
this.name = name;
this.key = key;
this.type = type;
}
public String getName() {
return name;
}
public String getKey() {
return key;
}
public String getType() {
return type;
}
public String serialize() {
return String.format("%s|%s|%s", key, name, type);
}
}
Table model:
final class Model extends AbstractTableModel {
private static final long serialVersionUID = 1858846855164475327L;
private final Map<String, Game> keyGame = new TreeMap<>();
private final List<Game> data = new ArrayList<>();
private File file;
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
public void add(String name, String key, String type) {
keyGame.put(key, new Game(name, key, type));
fireTableDataChanged();
}
public void remove(int rowIndex) {
keyGame.remove(data.get(rowIndex).getKey());
fireTableDataChanged();
}
public void save() throws IOException {
if (file == null)
return;
try (FileWriter out = new FileWriter(file, false)) {
for (Game game : keyGame.values())
out.write(game.serialize() + '\n');
}
}
public void read() throws IOException {
if (file == null)
return;
keyGame.clear();
for (String record : Files.readAllLines(file.toPath())) {
Game game = Game.createFromRecord(record);
if (game != null)
keyGame.put(game.getKey(), game);
}
fireTableDataChanged();
}
private enum Column {
NAME("Game Name", Game::getName),
KEY("Game Key", Game::getKey),
TYPE("Game Type", Game::getType);
private final String title;
private final Function<Game, Object> get;
Column(String title, Function<Game, Object> get) {
this.title = title;
this.get = get;
}
public Object getValue(Game game) {
return get.apply(game);
}
}
// ========== AbstractTableModel ==========
#Override
public void fireTableDataChanged() {
data.clear();
data.addAll(keyGame.values());
super.fireTableDataChanged();
}
// ========== TableModel ==========
#Override
public int getRowCount() {
return data.size();
}
#Override
public int getColumnCount() {
return Column.values().length;
}
#Override
public String getColumnName(int columnIndex) {
return Column.values()[columnIndex].title;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return Column.values()[columnIndex].getValue(data.get(rowIndex));
}
}
AddGame tab panel:
final class AddTabPanel extends JPanel implements ActionListener, DocumentListener {
private final Model model;
private final JTextField nameField = new JTextField();
private final JTextField keyField = new JTextField();
private final JLabel nameLabel = new JLabel("Game Name");
private final JLabel keyLabel = new JLabel("Game Key");
private final JLabel typeLabel = new JLabel("Game Type");
private final JComboBox<String> typeCombo = createGameTypeCombo();
private final JButton openButton = new JButton("Open");
private final JButton saveButton = new JButton("Save");
private final JButton clearButton = new JButton("Clear");
public AddTabPanel(Model model) {
this.model = model;
init();
addListeners();
}
private void init() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = createConstraints();
add(createTitlePanel(), gbc);
add(createMainPanel(), gbc);
add(createButtonPanel(), gbc);
gbc.weighty = 1;
add(Box.createVerticalGlue(), gbc);
onNameFieldChanged();
onKeyFieldChanged();
onTypeComboChanged();
}
private static JPanel createTitlePanel() {
JLabel label = new JLabel("Add a game below");
label.setFont(new Font("Verdana", Font.BOLD, 20));
JPanel panel = new JPanel();
panel.add(label);
return panel;
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new GridLayout(3, 2, 5, 5));
panel.add(nameLabel);
panel.add(nameField);
panel.add(keyLabel);
panel.add(keyField);
panel.add(typeLabel);
panel.add(typeCombo);
return panel;
}
private static GridBagConstraints createConstraints() {
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
return gbc;
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel();
panel.add(clearButton);
panel.add(saveButton);
panel.add(openButton);
return panel;
}
private static JComboBox<String> createGameTypeCombo() {
JComboBox<String> combo = new JComboBox<>();
combo.setModel(new DefaultComboBoxModel<>(new String[] { "<--Select-->", "Arcade", "Puzzle", "Adventure", "Shooter", "Roleplay" }));
return combo;
}
private void addListeners() {
clearButton.addActionListener(this);
saveButton.addActionListener(this);
openButton.addActionListener(this);
nameField.getDocument().addDocumentListener(this);
keyField.getDocument().addDocumentListener(this);
typeCombo.addActionListener(this);
}
private void validateFields() {
String name = nameField.getText().trim();
String key = keyField.getText().trim();
int type = typeCombo.getSelectedIndex();
saveButton.setEnabled(!name.isEmpty() && !key.isEmpty() && type != 0);
}
private void onNameFieldChanged() {
nameLabel.setForeground(nameField.getText().trim().isEmpty() ? Color.RED : Color.BLACK);
validateFields();
}
private void onKeyFieldChanged() {
keyLabel.setForeground(keyField.getText().trim().isEmpty() ? Color.RED : Color.BLACK);
validateFields();
}
private void onTypeComboChanged() {
typeLabel.setForeground(typeCombo.getSelectedIndex() == 0 ? Color.RED : Color.BLACK);
validateFields();
}
private void onCleanButton() {
nameField.setText(null);
keyField.setText(null);
typeCombo.setSelectedIndex(0);
validateFields();
}
private void onSaveButton() {
String name = nameField.getText().trim();
String key = keyField.getText().trim();
String type = (String)typeCombo.getSelectedItem();
model.add(name, key, type);
if (model.getFile() == null) {
JFileChooser fileChooser = new JFileChooser();
int res = fileChooser.showSaveDialog(this);
model.setFile(res == JFileChooser.APPROVE_OPTION ? fileChooser.getSelectedFile() : null);
}
try {
model.save();
} catch(Exception e) {
JOptionPane.showMessageDialog(this, "Cannot save file", e.getMessage(), JOptionPane.ERROR_MESSAGE);
}
}
private void onOpenButton() {
JFileChooser fileChooser = new JFileChooser();
int res = fileChooser.showOpenDialog(null);
model.setFile(res == JFileChooser.APPROVE_OPTION ? fileChooser.getSelectedFile() : null);
try {
model.read();
} catch(Exception e) {
JOptionPane.showMessageDialog(this, "Cannot read file", e.getMessage(), JOptionPane.ERROR_MESSAGE);
}
}
// ========== ActionListener ==========
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == typeCombo)
onTypeComboChanged();
else if (e.getSource() == clearButton)
onCleanButton();
else if (e.getSource() == saveButton)
onSaveButton();
else if (e.getSource() == openButton)
onOpenButton();
}
// ========== DocumentListener ==========
#Override
public void insertUpdate(DocumentEvent e) {
if (e.getDocument() == nameField.getDocument())
onNameFieldChanged();
else if (e.getDocument() == keyField.getDocument())
onKeyFieldChanged();
}
#Override
public void removeUpdate(DocumentEvent e) {
if (e.getDocument() == nameField.getDocument())
onNameFieldChanged();
else if (e.getDocument() == keyField.getDocument())
onKeyFieldChanged();
}
#Override
public void changedUpdate(DocumentEvent e) {
}
}
ViewGame tab panel:
final class ViewTabPanel extends JPanel implements ActionListener, PopupMenuListener {
private final Model model;
private final JTable table = new JTable();
private final JPopupMenu popupMenu = new JPopupMenu();
private final JMenuItem deleteItem = new JMenuItem("Delete");
public ViewTabPanel(Model model) {
this.model = model;
init();
addListeners();
}
private void init() {
setLayout(new GridLayout(1, 1));
add(new JScrollPane(table));
popupMenu.add(deleteItem);
table.setComponentPopupMenu(popupMenu);
table.setAutoCreateRowSorter(true);
table.setModel(model);
table.updateUI();
}
private void addListeners() {
popupMenu.addPopupMenuListener(this);
deleteItem.addActionListener(this);
}
// ========== ActionListener ==========
#Override
public void actionPerformed(ActionEvent event) {
if (event.getSource() == deleteItem) {
model.remove(table.getSelectedRow());
try {
model.save();
} catch(Exception e) {
JOptionPane.showMessageDialog(this, "Cannot save file", e.getMessage(), JOptionPane.ERROR_MESSAGE);
}
}
}
// ========== PopupMenuListener ==========
#Override
public void popupMenuWillBecomeVisible(PopupMenuEvent event) {
if (event.getSource() == popupMenu) {
SwingUtilities.invokeLater(() -> {
int rowAtPoint = table.rowAtPoint(SwingUtilities.convertPoint(popupMenu, new Point(0, 0), table));
if (rowAtPoint > -1)
table.setRowSelectionInterval(rowAtPoint, rowAtPoint);
});
}
}
#Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent event) {
}
#Override
public void popupMenuCanceled(PopupMenuEvent event) {
}
}
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 );
I am performing actions for 2 combo boxes which involves in changing the background color of JLabel. Here is my code,
public class JavaApplication8 {
private JFrame mainFrame;
private JLabel signal1;
private JLabel signal2;
private JPanel s1Panel;
private JPanel s2Panel;
public JavaApplication8()
{
try {
prepareGUI();
} catch (ClassNotFoundException ex) {
Logger.getLogger(JavaApplication8.class.getName())
.log(Level.SEVERE, null, ex);
}
}
public static void main(String[] args) throws
ClassNotFoundException
{
JavaApplication8 swingControl = new JavaApplication8();
swingControl.showCombobox1();
}
public void prepareGUI() throws ClassNotFoundException
{
mainFrame = new JFrame("Signal");
mainFrame.setSize(300,200);
mainFrame.setLayout(new GridLayout(3, 0));
mainFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowEvent){
System.exit(0);
}
});
signal1 = new JLabel("Signal 1",JLabel.LEFT);
signal1.setSize(100,100);
signal1.setOpaque(true);
signal2 = new JLabel("Signal 2",JLabel.LEFT);
signal2.setSize(100,100);
signal2.setOpaque(true);
final DefaultComboBoxModel light = new DefaultComboBoxModel();
light.addElement("Red");
light.addElement("Green");
final JComboBox s1Combo = new JComboBox(light);
s1Combo.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae)
{
if(s1Combo.getSelectedIndex() == 0)
{
signal1.setBackground(Color.RED);
}
else
{
signal1.setBackground(Color.GREEN);
}
}
});
final JComboBox s2Combo1 = new JComboBox(light);
s2Combo1.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae)
{
if(s2Combo1.getSelectedIndex() == 0)
{
signal2.setBackground(Color.RED);
}
else
{
signal2.setBackground(Color.GREEN);
}
}
});
s1Panel = new JPanel();
s1Panel.setLayout(new FlowLayout());
JScrollPane ListScrollPane = new JScrollPane(s1Combo);
s1Panel.add(signal1);
s1Panel.add(ListScrollPane);
s2Panel = new JPanel();
s2Panel.setLayout(new FlowLayout());
JScrollPane List1ScrollPane = new JScrollPane(s2Combo1);
s2Panel.add(signal2);
s2Panel.add(List1ScrollPane);
mainFrame.add(s1Panel);
mainFrame.add(s2Panel);
String[] columnNames = {"Signal 1","Signal 2"};
Object[][] data = {{"1","1"}};
final JTable table = new JTable(data,columnNames);
JScrollPane tablepane = new JScrollPane(table);
table.setFillsViewportHeight(true);
mainFrame.add(tablepane);
mainFrame.setVisible(true);
}
}
When Executed, If I change the item from combo box 1, the 2nd combo box also performs the change. Where did I go wrong?
Yours is a simple solution: don't have the JComboBoxes share the same model. If they share the same model, then changes to the selected item of one JComboBox causes a change in the shared model which changes the view of both JComboBoxes.
I wold use a method to create your combo-jlabel duo so as not to duplicate code. For instance:
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class App8 extends JPanel {
private static final int COMBO_COUNT = 2;
private static final String SIGNAL = "Signal";
private List<JComboBox<ComboColor>> comboList = new ArrayList<>();
public App8() {
setLayout(new GridLayout(0, 1));
for (int i = 0; i < COMBO_COUNT; i++) {
DefaultComboBoxModel<ComboColor> cModel = new DefaultComboBoxModel<>(ComboColor.values());
JComboBox<ComboColor> combo = new JComboBox<>(cModel);
add(createComboLabelPanel((i + 1), combo));
comboList.add(combo);
}
}
private JPanel createComboLabelPanel(int index, final JComboBox<ComboColor> combo) {
JPanel panel = new JPanel();
final JLabel label = new JLabel(SIGNAL + " " + index);
label.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
label.setOpaque(true);
combo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
ComboColor cColor = (ComboColor) combo.getSelectedItem();
label.setBackground(cColor.getColor());
}
});
panel.add(label);
panel.add(combo);
return panel;
}
private static void createAndShowGui() {
App8 mainPanel = new App8();
JFrame frame = new JFrame("App8");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
enum ComboColor {
RED("Red", Color.RED),
GREEN("Green", Color.GREEN);
private String text;
private Color color;
public String getText() {
return text;
}
public Color getColor() {
return color;
}
private ComboColor(String text, Color color) {
this.text = text;
this.color = color;
}
#Override
public String toString() {
return text;
}
}
I just wanted to double check my implementation for using a SwingWorker thread is done the correct and clean way. Also, just need verification my implementation of the model-view-controller pattern is correct and clean as well. Everything seems to be working as it should and it seems a nice simple implementation to me.
The Model class.
package Model;
public class Model
{
private int counter;
private boolean go = true;
public Void go()
{
counter = 0;
while(go)
{
counter++;
System.out.println(counter);
}
return null;
}
public int getCounter()
{
return counter;
}
public String getCounterToString()
{
return Integer.toString(counter);
}
public void setGo(boolean value)
{
this.go = value;
}
}
The View class.
package View;
import java.awt.*;
import javax.swing.*;
public class View extends JFrame
{
private JPanel topPanel, bottomPanel;
private JTextArea messageArea;
private JButton startButton, cancelButton;
private JLabel messageLabel;
private JScrollPane scrollPane;
public View()
{
setSize(250, 220);
setTitle("View");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
topPanel = new JPanel();
bottomPanel = new JPanel();
messageArea = new JTextArea(8, 20);
messageArea.setEditable(true);
scrollPane = new JScrollPane(messageArea);
messageLabel = new JLabel("Message Area");
topPanel.setLayout(new BorderLayout());
topPanel.add(messageLabel, "North");
topPanel.add(scrollPane, "South");
startButton = new JButton("START");
cancelButton = new JButton("CANCEL");
bottomPanel.setLayout(new GridLayout(1, 2));
bottomPanel.add(startButton);
bottomPanel.add(cancelButton);
Container cp = getContentPane();
cp.add(topPanel, BorderLayout.NORTH);
cp.add(bottomPanel, BorderLayout.SOUTH);
}
public JButton getStartButton()
{
return startButton;
}
public JButton getCancelButton()
{
return cancelButton;
}
public void setMessageArea(String message)
{
messageArea.append(message + "\n");
}
}
The Controller class.
package Controller;
import java.awt.event.*;
import javax.swing.SwingWorker;
import Model.*;
import View.*;
public class Controller implements ActionListener
{
private Model theModel;
private View theView;
private SwingWorker<Void, Void> worker;
public Controller(Model model, View view)
{
this.theModel = model;
this.theView = view;
view.getStartButton().addActionListener(this);
view.getCancelButton().addActionListener(this);
}
public void actionPerformed(ActionEvent ae)
{
Object buttonClicked = ae.getSource();
if(buttonClicked.equals(theView.getStartButton()))
{
theModel.setGo(true);
worker = new SwingWorker<Void, Void>()
{
#Override
protected Void doInBackground()
{
//theView.setMessageArea(theModel.getCounterToString());
return theModel.go();
}
#Override
protected void done()
{
//theView.setMessageArea(theModel.getCounterToString());
}
};
worker.execute();
}
else if(buttonClicked.equals(theView.getCancelButton()))
{
theModel.setGo(false);
}
}
}
The Main class.
package swinginfiniteloop;
import Model.*;
import View.*;
import Controller.*;
public class Main
{
public static void main(String[] args)
{
Model model = new Model();
View view = new View();
Controller controller = new Controller(model, view);
view.setVisible(true);
}
}