MVC pattern with child windows - java

In Java I have a simple window with a button. When I press the button I call the constructor of another class which opens a new window with a button again.
1) is correct to call a method of the View class from the Model class with the Observer Observable pattern?
2) is correct to delegate the call of the new window to the View class? or I have to do it in the Model class?
3) how can I set a listener for the new button in the Controller class? at the moment I call the constructor of the Controller class, I have an instance of the View (with the first button) but I still not have an instance of the sub-window class (and so the second button).
View:
import java.awt.*;
import java.util.Observable;
import java.util.Observer;
import javax.swing.*;
public class View implements Observer
{
JFrame frame;
JPanel panel;
JButton button;
Model model;
public View(Model model)
{
frame = new JFrame();
panel = new JPanel();
button = new JButton("Press");
this.model = model;
panel.add(button);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,500);
frame.add(panel);
frame.setVisible(true);
}
public void update(Observable ob, Object extra_arg)
{
switch(model.method_var)
{
case 0:
NewWindow newwindow = new NewWindow();
}
}
}
Model:
import java.util.Observable;
public class Model extends Observable
{
int method_var;
public void newwindow()
{
method_var = 0;
setChanged();
notifyObservers();
}
}
Controller:
import java.awt.event.ActionEvent;
public class Controller
{
Model model;
View view;
public Controller(Model model, View view)
{
this.model = model;
this.view = view;
view.button.addActionListener(new Action());
model.addObserver(view);
}
class Action implements java.awt.event.ActionListener
{
public void actionPerformed(ActionEvent e)
{
model.newwindow();
}
}
}
New-Window:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class NewWindow
{
JFrame frame;
JPanel panel;
JButton button;
Model model;
public NewWindow()
{
frame = new JFrame();
panel = new JPanel();
button = new JButton("Press again");
this.model = model;
panel.add(button);
frame.setSize(100,100);
frame.add(panel);
frame.setVisible(true);
}
}
Main:
public class Main
{
public static void main(String[] args)
{
Model model = new Model();
View view = new View(model);
Controller controller = new Controller(model, view);
}
}

IMHO, all the logic should be in the controllers of the components. That's their purpose. Doing so requires more effort, but it also avoids confusion as your design grows.

Related

How to have one JPanel show up and the second one disappear on button click?

So I have 3 separate classes, the settings button on the mainmenu class should switch to main menu, but it simply hides the first panel, same thing when i click return on the other menu, i would like to find a simple soluton without using a layout manager because i don't know how to have card layout communicate to the 2 classes, but thats the solution, it'd be nice if someone could give me some pointers on how to implement that:
public class Game extends JFrame {
MainMenu mainMenu;
Settings settings;
public Game(){
setSize(900,900);
setDefaultCloseOperation(3);
mainMenu = new MainMenu();
settings = new Settings();
mainMenu.setSettings(settings);
settings.setMainMenu(mainMenu);
add(settings,BorderLayout.CENTER);
add(mainMenu, BorderLayout.CENTER);
}
public static void main(String[] args) {
Game game = new Game();
game.setVisible(true);
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class MainMenu extends JPanel {
Settings settings;
public void setSettings(Settings settings) {
this.settings = settings;
}
public MainMenu() {
setLayout(new GridLayout(1,3));
JButton Newgame = new JButton("New Game");
JButton Cont = new JButton("Continue");
JButton Sett = new JButton("Settings");
add(Newgame);
add(Cont);
SwitchMenu1 switchMenu1 = new SwitchMenu1();
Sett.addActionListener(switchMenu1);
add(Sett);
}
class SwitchMenu1 implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
if(isVisible()){
settings.setVisible(true);
setVisible(false);
}
}
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Settings extends JPanel {
MainMenu mainMenu;
public void setMainMenu(MainMenu mainMenu) {
this.mainMenu = mainMenu;
}
public Settings(){
JButton Return = new JButton("Return");
SwitchMenu2 switchMenu2 = new SwitchMenu2();
Return.addActionListener(switchMenu2);
add(Return, BorderLayout.SOUTH);
}
class SwitchMenu2 implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
if(isVisible()){
mainMenu.setVisible(true);
setVisible(false);
}
}
}
}
I want to have the other JPanel show up on button click, but it doesn't work, the first one simply disappears. How can i fix this?
Thanks a lot!
This sounds a use case for CardLayout. You have a JPanel, named for example cards, which uses a CardLayout manager. You add all your panels (cards) to that panel, giving them unique names (e.g., "MAIN_MENU", "SETTINGS", etc.). Then, instead of passing every other panel in each of your panels, you only pass the cards panel, which can be used to show the card you wish, e.g., cl.show(cards, "SETTINGS"); on clicking a button, for instance.
Update
As per #c0der's suggestion (see comments section below), the code structure has been updated.
Game.java
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Game extends JFrame {
JPanel cards;
CardLayout cardLayout;
public Game(){
MainMenu mainMenu = new MainMenu();
Settings settings = new Settings();
cardLayout = new CardLayout();
cards = new JPanel(cardLayout);
cards.add(mainMenu, "MAIN_MENU");
cards.add(settings, "SETTINGS");
mainMenu.setSetBtnActionListener(new BtnController("SETTINGS"));
settings.setReturnBtnActionListener(new BtnController("MAIN_MENU"));
add(cards);
setSize(640,480);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
class BtnController implements ActionListener {
String cardName;
public BtnController(String cardName) {
this.cardName = cardName;
}
#Override
public void actionPerformed(ActionEvent e) {
cardLayout.show(cards, cardName);
}
}
public static void main(String[] args) {
new Game();
}
}
MainMenu.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
public class MainMenu extends JPanel {
JButton setBtn;
public MainMenu() {
setLayout(new GridLayout(1, 3));
JButton newGameBtn = new JButton("New Game");
JButton contBtn = new JButton("Continue");
setBtn = new JButton("Settings");
add(newGameBtn);
add(contBtn);
add(setBtn);
}
public void setSetBtnActionListener(ActionListener al) {
setBtn.addActionListener(al);
}
}
Settings.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
public class Settings extends JPanel {
JButton returnBtn;
public Settings() {
returnBtn = new JButton("Return");
setLayout(new BorderLayout());
add(returnBtn, BorderLayout.SOUTH);
}
public void setReturnBtnActionListener(ActionListener al) {
returnBtn.addActionListener(al);
}
}

How to get/set JRadionButtonMenuItem dynamically?

This example has Radio Buttons located on a Sub Menu as seen here.
What I would like to do is anytime the "Change Radio Button" button is pressed, it will change which button is selected on the menu. This means it has to first retrieve which is currently set then select the other.
Granted for this simple sample the Radio Buttons could be made instance variables to make things easy but image the JMenu and associated sub-menus and radio buttons are generated is some class further down in the bowels of the program. Direct access is not that direct.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
public class RadioButtonsOnMenu
{
public static void main(final String args[])
{
JFrame frame = new JFrame("MenuSample Example");
JButton jButton = new JButton("Change Radio Button");
jButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
System.out.println("Changing Radion Button");
//How to change the JButton on the menu?
//frame.getMenuBar().......
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel jPanel = new JPanel();
jPanel.add(jButton);
frame.add(jPanel);
frame.setJMenuBar(buildMenu());
frame.setSize(350, 250);
frame.setVisible(true);
}
public static JMenuBar buildMenu()
{
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
fileMenu.setMnemonic(KeyEvent.VK_F);
menuBar.add(fileMenu);
JMenuItem newMenuItem = new JMenuItem("New", KeyEvent.VK_N);
fileMenu.add(newMenuItem);
JMenu findOptionsMenu = new JMenu("Options");
findOptionsMenu.setMnemonic(KeyEvent.VK_O);
fileMenu.add(findOptionsMenu);
ButtonGroup directionGroup = new ButtonGroup();
JRadioButtonMenuItem forwardMenuItem = new JRadioButtonMenuItem("Forward", true);
forwardMenuItem.setMnemonic(KeyEvent.VK_F);
findOptionsMenu.add(forwardMenuItem);
directionGroup.add(forwardMenuItem);
JRadioButtonMenuItem backwardMenuItem = new JRadioButtonMenuItem("Backward");
backwardMenuItem.setMnemonic(KeyEvent.VK_B);
findOptionsMenu.add(backwardMenuItem);
directionGroup.add(backwardMenuItem);
return menuBar;
}
}
It is not clear how best to access the sub-menu and associated radio button settings within the JButton action.
jButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
System.out.println("Changing Radion Button");
//How to change the JButton on the menu?
//frame.getMenuBar().......
}
});
I could probably get the Menu Bar from the Frame and drill down figure the code can get messy if there Menu Bar has numerous items, sub items and even multiple radio button groups.
Is there a more direct way to find out which Radio Buttons on the menu are selected as well as a more direct way to change their value?
The "trick" is to create an application model to hold the value of the menu radio buttons.
Here's the GUI I created.
I started the Swing application with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.
I created a JFrame and a JButton JPanel. I separated the creation of the JFrame and JPanel.
I created an application model class to hold a boolean which determines whether forward or backward is selected. The JButton ActionListener switches the state of the boolean. The updateRadioButtonMenu method updates the selected state of the radio button menu items.
Here's the complete runnable code.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.SwingUtilities;
public class RadioButtonsOnMenu implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new RadioButtonsOnMenu());
}
private ApplicationModel model;
private JRadioButtonMenuItem backwardMenuItem;
private JRadioButtonMenuItem forwardMenuItem;
public RadioButtonsOnMenu() {
this.model = new ApplicationModel();
}
#Override
public void run() {
JFrame frame = new JFrame("MenuSample Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setJMenuBar(createMenuBar());
frame.add(createButtonPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JMenuBar createMenuBar() {
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
fileMenu.setMnemonic(KeyEvent.VK_F);
menuBar.add(fileMenu);
JMenuItem newMenuItem = new JMenuItem("New", KeyEvent.VK_N);
fileMenu.add(newMenuItem);
JMenu findOptionsMenu = new JMenu("Options");
findOptionsMenu.setMnemonic(KeyEvent.VK_O);
fileMenu.add(findOptionsMenu);
ButtonGroup directionGroup = new ButtonGroup();
forwardMenuItem = new JRadioButtonMenuItem("Forward", model.isForward());
forwardMenuItem.setMnemonic(KeyEvent.VK_F);
findOptionsMenu.add(forwardMenuItem);
directionGroup.add(forwardMenuItem);
backwardMenuItem = new JRadioButtonMenuItem("Backward", !model.isForward());
backwardMenuItem.setMnemonic(KeyEvent.VK_B);
findOptionsMenu.add(backwardMenuItem);
directionGroup.add(backwardMenuItem);
return menuBar;
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(100, 100, 100, 100));
JButton button = new JButton("Change Radio Button");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
model.setForward(!model.isForward());
updateRadioButtonMenu();
}
});
panel.add(button);
return panel;
}
public void updateRadioButtonMenu() {
forwardMenuItem.setSelected(model.isForward());
backwardMenuItem.setSelected(!model.isForward());
}
public class ApplicationModel {
private boolean isForward;
public ApplicationModel() {
this.isForward = true;
}
public boolean isForward() {
return isForward;
}
public void setForward(boolean isForward) {
this.isForward = isForward;
}
}
}
What you could do is to save the state in a boolean. You could add listener to the radio buttons and change the boolean everytime one of them is selected
boolean isForward = true;
so when changed to backward you set the value to false. This way you don't need to get The state of the radiobuttons everytime.
In your button actionlistener you could then do:
jButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
System.out.println("Changing Radion Button");
forwardRadioButton.setState(!isForward);
backwardRadioButton.setState(isForward);
iSForward = !isForward;
}
});
I would say you need to do these two things:
Since you seem to have a lot of items it is best to store them somewhere else
1 Create a class to store all the items and then just pass the class
public class myItemHolder{
//declare all the items here instead of at the main
JButton jButton = new JButton("Change Radio Button");
ButtonGroup directionGroup = new ButtonGroup();
JRadioButtonMenuItem forwardMenuItem = new JRadioButtonMenuItem("Forward", true);
JRadioButtonMenuItem backwardMenuItem = new JRadioButtonMenuItem("Backward");
myListener(myItemHolder items){
directionGroup.add(forwardMenuItem);
}
public ButtonGroup getButtons() {
return directionGroup;
}
public JButton getClick() {
return jButton;
}
}
2 Create your own action listener class like so
public class myListener implements ActionListener{
myItemHolders items;
myListener(myItemHolder items){
this.items=items;
}
#Override
public void actionPerformed(ActionEvent e) {
//get the radiobutton like so and do what you want with it
items.getButtons()
}
}
Now you just need to do this in the main:
public class RadioButtonsOnMenu
{
public static void main(final String args[])
{
myItemHolder items = new myItemHolder();
items.getClick.addActionListener(new myListener(items));
}
}
And there you can access everything easily :)
It is all a matter of where you declare your stuff.
Or if you only want to send the ButtonGroup you can just do so by changing the structure a little so the actionlistener only requests the ButtonGroup and give it items.getButtons() instead of items.
Here's another possible way to go about it using Enum state tracking. I make use of a Enum and a Map to track the Radio Button that should be activated. This lets it scale as large as you want for associated Radio Button items within the same JMenu.
RadioMenu
package tools;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import javax.swing.JMenu;
import javax.swing.JRadioButtonMenuItem;
public class RadioMenu<E extends Enum<E>> extends JMenu {
private static final long serialVersionUID = 1L;
private E currentState;
private JRadioButtonMenuItem selectedRadioButton;
private HashMap<E, JRadioButtonMenuItem> stateMap;
public RadioMenu() {
stateMap = new HashMap<E, JRadioButtonMenuItem>();
}
public RadioMenu(String name) {
super(name);
stateMap = new HashMap<E, JRadioButtonMenuItem>();
}
public void addRadioButton(E associatedState, JRadioButtonMenuItem radioButton) {
//Set default to first added button
if(stateMap.isEmpty()) {
currentState = associatedState;
radioButton.setSelected(true);
selectedRadioButton = radioButton;
}
add(radioButton);
stateMap.put(associatedState, radioButton);
radioButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setState(associatedState);
}
});
}
public void generateButtonsFromEnum(Class<E> enumType) {
for(E enumValue : enumType.getEnumConstants()) {
addRadioButton(enumValue, new JRadioButtonMenuItem(enumValue.toString()));
}
}
public E getState() {
return currentState;
}
public void setState(E newState) {
currentState = newState;
selectedRadioButton.setSelected(false);
selectedRadioButton = stateMap.get(newState);
selectedRadioButton.setSelected(true);
}
}
RadioMenuTest
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import tools.RadioMenu;
public class RadioMenuTest implements Runnable {
public enum RadioOptions {
Forward, Backward, Left, Right
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new RadioMenuTest());
}
private RadioMenu<RadioOptions> optionsMenu;
#Override
public void run() {
JFrame frame = new JFrame("RadioMenu Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setJMenuBar(createMenuBar());
frame.getContentPane().add(createButtonPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JMenuBar createMenuBar() {
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
menuBar.add(fileMenu);
optionsMenu = new RadioMenu<RadioOptions>("Options");
optionsMenu.generateButtonsFromEnum(RadioOptions.class);
fileMenu.add(optionsMenu);
return menuBar;
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel(new FlowLayout());
JButton setBackwardButton = new JButton("Set To Backward");
setBackwardButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
optionsMenu.setState(RadioOptions.Backward);
}
});
panel.add(setBackwardButton);
JButton setRightButton = new JButton("Set To Right");
setRightButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
optionsMenu.setState(RadioOptions.Right);
}
});
panel.add(setRightButton);
return panel;
}
}

How to turn a regular class into MVC?

I am working on a MVC based off of the code that I will be providing. I am having issues because I am fairly new to the subject. I am able to make the view, but when it comes to making the model it is a little more complicated for me. I need some guidance on how to turn the following code into a MVC so I can practice and learn. I been at this for several hours and I decided to come here for help.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
class SayHi extends JFrame implements MouseListener{
// components
protected JLabel helloLabel = new JLabel("Hello");
protected JTextField userInputTextField = new JTextField(20);
private JButton sayHiBtn = new JButton("Say Hi");
/** Constructor */
SayHi() {
//... Layout the components.
JPanel content = new JPanel();
content.setLayout(new FlowLayout());
content.add(new JLabel("Enter your name"));
content.add(userInputTextField);
content.add(sayHiBtn);
content.add(helloLabel);
// Add a mouse listener to the button
sayHiBtn.addMouseListener(this);
//... finalize layout
this.setContentPane(content);
this.pack();
this.setTitle("Simple App - Not MVC");
// The window closing event should probably be passed to the
// Controller in a real program, but this is a short example.
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
// Methods I am forced to implement because of the MouseListener
public void mouseClicked(MouseEvent e) {
helloLabel.setText("Hello " + userInputTextField.getText());
}
public void mouseEntered(MouseEvent e){
}
public void mouseExited(MouseEvent e){
}
public void mousePressed(MouseEvent e){
}
public void mouseReleased(MouseEvent e){
}
public static void main(String[] args){
SayHi s = new SayHi();
s.setVisible(true);
}
}
The View only controls the visuals, The Model only controls the data access and the Controller is in charge of the logic that glues the two.
You could split that class into 3 classes in order to make it a MVC.
All the Jpanel would be located in a View, in the Model you would have all your values, like setting a string to hello and such, while the controller needs to interact with both the Model and View.
private SayHiModel model;
private SayHiView view;
SayHiController(SayHiModel model, SayHiView view) {
this.model = model;
this.view = view;
this.model.setValue(model.INITIAL_VALUE);
view.totalTextField.setText(model.getValue());
//... Add listeners to the view.
view.addMultiplyListener(new MultiplyListener());
view.addClearListener(new ClearListener());
}
Just a little hint to get you going.
There isn't much of a model to work with.
Here's your example code, with one view class, one model class, and one controller class. The SayHi class is the view class. The SayHiModel class is the model class. The SayHiListener class is the controller class.
package com.ggl.testing;
import java.awt.FlowLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class SayHi implements Runnable {
private JFrame frame;
private JLabel helloLabel;
private JTextField userInputTextField;
private SayHiModel model;
public static void main(String[] args) {
SwingUtilities.invokeLater(new SayHi());
}
public SayHi() {
this.model = new SayHiModel();
}
#Override
public void run() {
// ... Layout the components.
JPanel content = new JPanel();
content.setLayout(new FlowLayout());
content.add(new JLabel("Enter your name: "));
userInputTextField = new JTextField(20);
content.add(userInputTextField);
JButton sayHiBtn = new JButton("Say Hi");
// Add a mouse listener to the button
sayHiBtn.addMouseListener(new SayHiListener(this, model));
content.add(sayHiBtn);
helloLabel = new JLabel("Hello");
content.add(helloLabel);
// ... finalize layout
frame = new JFrame("MVC App");
// The window closing event should probably be passed to the
// Controller in a real program, but this is a short example.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(content);
frame.pack();
frame.setVisible(true);
}
public JFrame getFrame() {
return frame;
}
public void setHelloLabel(String name) {
helloLabel.setText("Hello " + name);
}
public String getName() {
return userInputTextField.getText().trim();
}
public class SayHiModel {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class SayHiListener extends MouseAdapter {
private SayHi sayHi;
private SayHiModel sayHiModel;
public SayHiListener(SayHi sayHi, SayHiModel sayHiModel) {
this.sayHi = sayHi;
this.sayHiModel = sayHiModel;
}
#Override
public void mouseClicked(MouseEvent e) {
sayHiModel.setName(sayHi.getName());
sayHi.setHelloLabel(sayHiModel.getName());
JFrame frame = sayHi.getFrame();
frame.setVisible(false);
frame.pack();
frame.setVisible(true);
}
}
}

Adding values to Jtable when button is clicked in java [duplicate]

In my application everything is distributed.
On a action, application retrieves data from DB and saves in ArrayList<T>.
I create an object of RelativeTableModel where I pass the ArrayList<T>.
public void RelationsClicked() {
ArrayList<Relation> data = myParent.dbOperation.getRelations();
RelativeTableModel tModel = new RelativeTableModel(data); // subclass of AbstractTableModel
myParent.SetBrowsePanelData(tModel);
myParent.SetMainPanel(CashAccountingView.BROWSEPANEL);
}
I have a BrowseListPanel class that has a JTable in JScrollPane. Its instance is already created in the main application.
I pass the model to BrowseListPanel and finally show the panel.
Code:
public void SetBrowsePanelData(AbstractTableModel tModel) {
browsePanel.setTModel(tModel);
}
// BrowseListPanel's Code
public void setTModel(AbstractTableModel tModel) {
this.tModel = tModel; // tModel = AbstractTableModel
}
// Show the Panel
public void SetMainPanel(String panel) {
activePanel = panel;
SetFontSize();
cards.show(mainPanel, panel);
mainPanel.revalidate();
mainPanel.repaint();
}
But I don't see the Table. I believe as the object of BrowseListPanel (containing the JTable) is already created & later the TableModel is added. So some sort of event should be fired in setTModel().
Am I right? If so, what event should be thrown and what should be its implementation.
Invoking setModel() on the table should be sufficient, but you might call fireTableStructureChanged() on the model explicitly as a way to help sort things out.
Also, verify that you are working on the event dispatch thread.
Addendum: Here's an sscce that shows the basic approach.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
/** #see http://stackoverflow.com/questions/8257148 */
public class SwapTableModel extends JPanel {
public SwapTableModel() {
final JTable table = new JTable(Model.Alpha.model);
table.setPreferredScrollableViewportSize(new Dimension(128, 32));
this.add(new JScrollPane(table));
final JComboBox combo = new JComboBox();
for (Model model : Model.values()) {
combo.addItem(model);
}
this.add(combo);
combo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Model model = (Model) combo.getSelectedItem();
table.setModel(model.model);
}
});
}
private enum Model {
Alpha(), Beta();
private DefaultTableModel model;
private Model() {
Object[] data = {this.toString()};
this.model = new DefaultTableModel(data, 1);
model.addRow(data);
}
}
private void display() {
JFrame f = new JFrame("SwapTableModel");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new SwapTableModel().display();
}
});
}
}

handling events in java swing

How can I assign two buttons to share the same class for handling events in Java/swing?
For example, I have this:
private class BtnEvtHandler implements ActionListener {
private int counter=10;
public void actionPerformed(ActionEvent e) {
gs.setX(counter);
gs.repaint();
counter=counter+10;
}
public void actionPerformed(ActionEvent e) {
//action for move button
}
}
JButton jumpBtn= new JButton("JUMP");
BtnEvtHandler okButtonHandler= new BtnEvtHandler();
(jumpBtn).addActionListener(okButtonHandler);
menuPanel.add(jumpBtn);
Now I want to add another button as below which can have the same class as event handler but dispatches to different actionPerformed as mentioned in above code.
JButton moveBtn= new JButton("MOVE");
menuPanel.add(moveBtn);
(moveBtn).addActionListener(okButtonHandler);
You can't reuse one ActionListener and expect it to call a different method depending on the button you attach it to. The contract of ActionListener has one method that gets called. But you can check the source of the event and have flow control based on that. Here's an example:
package com.sandbox;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
public class SwingSandbox {
public static void main(String[] args) throws IOException {
JFrame frame = buildFrame();
JPanel pane = new JPanel();
MyActionListener myActionListener = new MyActionListener();
JButton button1 = new JButton("Button1");
button1.addActionListener(myActionListener);
pane.add(button1);
JButton button2 = new JButton("Button2");
button2.addActionListener(myActionListener);
pane.add(button2);
frame.add(pane);
}
private static JFrame buildFrame() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
return frame;
}
private static class MyActionListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
JButton source = (JButton) e.getSource();
if ("Button1".equals(source.getText())) {
System.out.println("You clicked button 1");
} else {
System.out.println("You clicked button 2");
}
}
}
}

Categories

Resources