How to add parameter in mouselistener - java

I want to make the JLabel answer print out the answer when users press the label. But I found line 104 does not use the "input" from HanoisFrames. It keeps using 0 as "input" and prints out "0". I tried to write line 96 as
"private class MouseHandler extends HanoisFrames implements MouseListener, MouseMotionListener" and I used "super (int)" but it does not work. What should I do?
package Hanois;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Hanoi {
private JFrame frame;
JButton[][] buttons= new JButton[3][3];
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Hanoi window = new Hanoi();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Hanoi() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 901, 696);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenuBar menubar=new JMenuBar();//Menu
frame.setJMenuBar(menubar);
JMenu file= new JMenu("File");
file.setFont(new Font("Segoe UI", Font.PLAIN, 21));
menubar.add(file);
JMenuItem exit= new JMenuItem("Exit");//provide users a way to exit
exit.setFont(new Font("Segoe UI", Font.PLAIN, 21));
file.add(exit);
class exitaction implements ActionListener{
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
exit.addActionListener(new exitaction());
JPanel panelone = new JPanel();
frame.getContentPane().add(panelone, BorderLayout.CENTER);
panelone.setBackground(Color.WHITE);
panelone.setLayout(new GridLayout(3,4,3,3));
JPanel paneltwo = new JPanel();
frame.getContentPane().add(paneltwo, BorderLayout.NORTH);
paneltwo.setBackground(Color.WHITE);
JLabel lblFunHanoiTower = new JLabel("Fun Hanoi Tower");
frame.getContentPane().add(paneltwo, BorderLayout.NORTH);
lblFunHanoiTower.setForeground(Color.BLACK);
lblFunHanoiTower.setBackground(SystemColor.activeCaption);
lblFunHanoiTower.setFont(new Font("Viner Hand ITC", Font.PLAIN, 36));
paneltwo.add(lblFunHanoiTower);
ActionListener listener =new ActionListener() {
public void actionPerformed(ActionEvent e) {
for(int row = 0; row < buttons.length ; row++) {
for(int col= 0; col < buttons[0].length ;col++) {
if(e.getSource()==buttons[row][col]){
buttons[row][col].setBackground(Color.lightGray);
HanoisFrames f= new HanoisFrames(((row*3)+(col+3)));
f.setVisible(true);//
}
}
}
}
};
for(int row = 0; row < buttons.length ; row++) {
for(int col= 0; col < buttons[0].length ;col++) {
buttons[row][col] = new JButton("level "+String.valueOf((row*3)+(col+3)-2));
buttons[row][col].setFont(new Font("Tempus Sans ITC", Font.BOLD, 32));
buttons[row][col].setBackground(SystemColor.controlHighlight);
buttons[row][col].setSize(6, 6);
buttons[row][col].addActionListener(listener);
panelone.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
panelone.add(buttons[row][col]);
}
}
}
}
package Hanois;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class HanoisFrames extends JFrame {
private JPanel contentPane;
private JButton ret ;
private JButton next;
private JButton last;
private JLabel answer;
private JMenu menu;
private JButton reset;
private JLabel move;
private JPanel panel;
static int input;
private JLabel lblLevel;
boolean showAnswer=false;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
HanoisFrames frame = new HanoisFrames(input);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public HanoisFrames(int input) {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 901, 696);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
MouseHandler handler=new MouseHandler();
panel = new JPanel();
contentPane.add(panel, BorderLayout.SOUTH);
panel.setLayout(new GridLayout(2,3));
move = new JLabel(" Move");
panel.add(move);
reset = new JButton("Reset");
panel.add(reset);
answer = new JLabel();
answer.setHorizontalAlignment(SwingConstants.CENTER);
panel.add(answer);
answer.setText("Answer");
answer.addMouseListener(handler);
answer.addMouseMotionListener(handler);
last = new JButton("Last");
panel.add(last);
ret = new JButton("Return");
panel.add(ret);
next = new JButton("Next");
panel.add(next);
lblLevel = new JLabel("LEVEL "+ String.valueOf(input-2));
lblLevel.setHorizontalAlignment(SwingConstants.CENTER);
lblLevel.setFont(new Font("Viner Hand ITC", Font.PLAIN, 36));
contentPane.add(lblLevel, BorderLayout.NORTH);
}
public int hanoiCalculator(int input) {
if (input==0){
return 0;
}else if (input==1){
return 1;
}else{
return 2*(hanoiCalculator(input-1)+1)-1;
}
}
private class MouseHandler implements MouseListener,MouseMotionListener {
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mousePressed(MouseEvent e) {
answer.setText("Answer: "+String.valueOf(hanoiCalculator(input)).toString());
}
#Override
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseReleased(MouseEvent e) {
answer.setText("Answer: ");
}
}
}

Here:
public class HanoisFrames extends JFrame {
private JPanel contentPane;
// ...
private JPanel panel;
static int input;
You never set your input value in your HanoiFrames constructor, and so it remains the default value for an int field, 0. But even if you did set the field because it's a static field, any changes made to it in any HanoiFrames class will change the value in all HanoiFrames classes, and so it cannot be a static field.
So, change input declaration to non-static:
public class HanoisFrames extends JFrame {
private JPanel contentPane;
private JButton ret;
//.....
private JPanel panel;
private int input; // private non-static field now
and set it in the constructor:
public HanoisFrames(int input) {
this.input = input;
This way each HanoisFrames will have a unique and durable input value
Side Recommendation:
I would advise against creating and then swapping a bunch of JFrames. Instead gear your code towards creating JPanels, and then swap them when needed, using a CardLayout.

Related

Java - Problem during the creation of a stock JPanel

I am attempting to create a JPanel that houses in a GridLayout a number of JLabels to the left JTextFields on the right. Unfortunately, nothing is shown even if the Components are reported as correctly added. Where is the problem?
public class AlternateGL_JPanel extends JPanel {
protected JPanel layoutPanel;
protected int rows, columns;
public AlternateGL_JPanel(int rows, int columns) {
this.rows = rows;
this.columns = columns;
// ===== MAIN FRAME DEFINITION =====
setBorder(new EmptyBorder(0, 0, 0, 0));
setLayout(new GridLayout(this.rows, this.columns));
// setBounds(10, 10, 500, 500);
// ===== INNER PANEL =====
this.layoutPanel = new JPanel(); //This is the nested panel
layoutPanel.setLayout(new GridLayout(this.rows, this.columns));
super.add(layoutPanel, BorderLayout.PAGE_START);
}
// =========================================================
// TODO | Superclass: JPanel
public void add(JComponent component) {
layoutPanel.add(component);
}
}
/** A <b>ManyTextAndInsertText</b> is a {#link JPanel} that houses a number of {#link JLabel}s to the left
* and {#link JTextField}s on the right.
*
*/
public class ManyTextAndInsertText extends AlternateGL_JPanel {
private JLabel[] texts;
private JTextField[] insertTexts;
public ManyTextAndInsertText(String[] descriptions) {
super(descriptions.length, 2);
this.texts = new JLabel[descriptions.length];
this.insertTexts = new JTextField[descriptions.length];
for(int i=0 ; i<descriptions.length ; i++)
{
texts[i] = new JLabel(descriptions[i]);
insertTexts[i] = new JTextField();
for(int j=0 ; j<this.getComponentCount() ; j++)
System.out.println("\t" + this.getComponent(j).toString());
this.add(texts[i]);
for(int j=0 ; j<this.getComponentCount() ; j++)
System.out.println("\t" + this.getComponent(j).toString());
this.add(insertTexts[i]);
}
}
public class TestManyTextes extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
TestManyTextes frame = new TestManyTextes();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public TestManyTextes() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new ManyTextAndInsertText(new String[] { "First text: " , "Second text: "});
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
}
I greatly simplified your code and created this GUI.
Instead of extending Swing components, I used Swing components.
You would get a nicer looking form using a GridBagLayout, rather than a GridLayout.
Here's the runnable example.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
public class TestManyTexts {
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
new TestManyTexts();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public TestManyTexts() {
JFrame frame = new JFrame("Test Many Texts");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ManyTexts panel = new ManyTexts(new String[] { "First text: ",
"Second text: ", "Third Text:", "Forth Text" });
frame.add(panel.getPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public class ManyTexts {
private JPanel panel;
private JTextField[] fields;
public ManyTexts(String[] labels) {
createPanel(labels);
}
private void createPanel(String[] labels) {
panel = new JPanel(new GridLayout(0, 2));
panel.setBorder(new EmptyBorder(5, 5, 5, 5));
fields = new JTextField[labels.length];
for (int i = 0; i < labels.length; i++) {
JLabel label = new JLabel(labels[i]);
panel.add(label);
fields[i] = new JTextField(15);
panel.add(fields[i]);
}
}
public JPanel getPanel() {
return panel;
}
public JTextField[] getFields() {
return fields;
}
}
}

Card Layout - Get Input from previous Card

I need a running order of pages 1-5 pages. I am using the card layout to navigate between each page after entering data on each page. The navigation to the next page works via an Action Listener on each text field.
My question is how do I pass the input from each card/page to the next? I can System.out.println each TextFeilds data. But I can't grab this information in the next card/action listener. The reason I need this to happen is I'd like to compare the strings of each page and also display a label of page 1's input on page/card2.
I apologize in advance for the massive block of code... Most of you will recognise most of this code anyway as it's copied from the CardLayout sample java code. I have just added two cards just now until I get the basics of passing variables back and fourth.
All help is appreciated even a small push the the right direction.
import java.awt.*;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.event.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Scanner;
import javax.swing.*;
public class CardLayoutDemo implements ItemListener {
JPanel cards; //a panel that uses CardLayout
final static String TEXTPANEL = "Card1 with text";
final static String TEXTPANEL2 = "Card with JTextField";
public void addComponentToPane(Container pane) {
//Put the JComboBox in a JPanel to get a nicer look.
JPanel comboBoxPane = new JPanel(); //use FlowLayout
String comboBoxItems[] = { TEXTPANEL, TEXTPANEL2};
JComboBox cb = new JComboBox(comboBoxItems);
cb.setEditable(false);
cb.addItemListener(this);
comboBoxPane.add(cb);
//Create the "cards".
JPanel card1 = new JPanel();
JTextField jtf=new JTextField("", 40);
jtf.setSize(40, 10);
card1.add(jtf);
JLabel lab1 = new JLabel("Page1 Text", JLabel.LEFT);
card1.add(lab1 = new JLabel("Page1"));
JPanel card2 = new JPanel();
JTextField jtf2=new JTextField("", 40);
jtf2.setSize(40, 10);
card2.add(jtf2);
JLabel lab2 = new JLabel("Page2 Text", JLabel.LEFT);
card2.add(lab2 = new JLabel("Page2 "));
//Create the panel that contains the "cards".
cards = new JPanel(new CardLayout());
cards.add(card1, TEXTPANEL);
cards.add(card2, TEXTPANEL2);
pane.add(cards, BorderLayout.CENTER);
jtf.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
String getText1 = jtf.getText();
System.out.println("PAGE1 ");
System.out.println(getText1);
CardLayout cl = (CardLayout)(cards.getLayout());
cl.show(cards, TEXTPANEL2);
jtf2.requestFocus();
jtf2.requestFocusInWindow();
}
//JOptionPane.showMessageDialog(null,"Action Listener is working");
});
//PAGE2
jtf2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
String getText2 = jtf2.getText();
System.out.println("PAGE2 ");
System.out.println(getText2);
CardLayout cl = (CardLayout)(cards.getLayout());
cl.show(cards, TEXTPANEL);
jtf.requestFocus();
jtf.requestFocusInWindow();
jtf.setText("");
}
});
}//ADD COMPONENT TO PANE
public void itemStateChanged(ItemEvent evt) {
CardLayout cl = (CardLayout)(cards.getLayout());
cl.show(cards, (String)evt.getItem());
// String getLoginUser1 = jtf.getText();
//System.out.println(getLoginUser1);
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event dispatch thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("CardLayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(600, 300));
JFrame.setDefaultLookAndFeelDecorated(true);
//Create and set up the content pane.
CardLayoutDemo demo = new CardLayoutDemo();
demo.addComponentToPane(frame.getContentPane());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
/* Use an appropriate Look and Feel */
try {
//UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
} catch (InstantiationException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
/* Turn off metal's use of bold fonts */
UIManager.put("swing.boldMetal", Boolean.FALSE);
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Here is another view on the problem. You could create some kind of cards manager and hold all required info inside of it. Here is an example:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
public class CardLayoutDemo implements ItemListener {
private static class QuizManager {
final java.util.List<String> quizData = new ArrayList<>();
final java.util.List<JPanel> cards = new ArrayList<>();
final JPanel rootView;
public QuizManager(JPanel root){
rootView = root;
}
private JPanel createQuizPanel(String pageText, final int index) {
JPanel card = new JPanel();
JTextField jtf=new JTextField("", 40);
jtf.setSize(40, 10);
JLabel prev = new JLabel("", JLabel.LEFT);
card.add(prev);
card.add(jtf);
card.add(new JLabel(pageText, JLabel.LEFT));
jtf.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
QuizManager.this.onCardSubmited(card, index, jtf.getText());
}
});
card.addComponentListener(new ComponentAdapter() {
#Override
public void componentShown(ComponentEvent e) {
super.componentShown(e);
jtf.requestFocus();
jtf.requestFocusInWindow();
String text = QuizManager.this.getPrevStringFor(index);
if (text != null) {
prev.setText(text);
}
}
});
return card;
}
private String getPrevStringFor(int index) {
if (index == 0) return null;
return quizData.get(index-1);
}
private String buildPanelName(int index) {
return String.format("card-%d", index);
}
public QuizManager addCard(String title) {
int index = cards.size();
quizData.add(null);//not set yet, just allocating
JPanel card = createQuizPanel(title, index);
cards.add(card);//this array looks like redundant
rootView.add(card, buildPanelName(index));
return this;
}
private void showCard(int index) {
CardLayout cl = (CardLayout) (rootView.getLayout());
cl.show(rootView, buildPanelName(index));
}
public void show() {
showCard(0);
}
public void onCardSubmited(JPanel card, int cardIndex, String text) {
System.out.println("page " + cardIndex);
System.out.println("text : " + text);
quizData.set(cardIndex, text);
if (cardIndex < cards.size() - 1) {
showCard(cardIndex + 1);
} else {
System.out.println("WE FINISHED");
//add finalazing code here
}
}
}
JPanel cardsRoot;
public void addComponentToPane(Container pane) {
cardsRoot = new JPanel(new CardLayout());
QuizManager manager = new QuizManager(cardsRoot)
.addCard("First page")
.addCard("Second page")
.addCard("Third card")
.addCard("Forth card");
pane.add(cardsRoot, BorderLayout.CENTER);
manager.show();
}
public void itemStateChanged(ItemEvent evt) {
CardLayout cl = (CardLayout)(cardsRoot.getLayout());
cl.show(cardsRoot, (String)evt.getItem());
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event dispatch thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("CardLayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(600, 300));
JFrame.setDefaultLookAndFeelDecorated(true);
//Create and set up the content pane.
CardLayoutDemo demo = new CardLayoutDemo();
demo.addComponentToPane(frame.getContentPane());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
/* Use an appropriate Look and Feel */
try {
//UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
} catch (InstantiationException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
/* Turn off metal's use of bold fonts */
UIManager.put("swing.boldMetal", Boolean.FALSE);
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Take a look how easy would be to create many of cards.
You've got the variable declaration of key components buried within the addComponentToPane(...) method, limiting their scope to this method only, preventing you from getting the information you need. While the canonical solution for this sort of problem is to use an model-view-controller or MVC type pattern so that the model (the underlying program logic and data) is extracted out of the view (the GUI), you can do a quick and dirty solution just by giving your variables private class scope.
For instance, if the JTextField was called textField and was held in a JPanel that acts as a "card", say called cardPanel, you could create a class that looked something like so:
public class CardPanel extends JPanel {
// constants to give the GUI a bigger size
private static final int PREF_W = 300;
private static final int PREF_H = 100;
// our key JTextField declared at class level
private JTextField textField = new JTextField(20);
// a JLabel to display the previous cardpanel's text
private JLabel label = new JLabel(" ");
// create the JPanel
public CardPanel(String name) {
setName(name);
setBorder(BorderFactory.createTitledBorder("Panel " + name));
JPanel labelPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
labelPanel.add(new JLabel("Prior Card's Word: "));
labelPanel.add(label);
setLayout(new BorderLayout());
add(textField, BorderLayout.PAGE_START);
add(labelPanel, BorderLayout.CENTER);
}
// have to jump through this hoop if we want to JTextField to
// have focus when a card is swapped
public void setFocusOnTextField() {
textField.requestFocusInWindow();
textField.selectAll();
}
// to make our GUI larger
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
// allow outside classes to add a listener to the JTextField
public void addActionListener(ActionListener listener) {
textField.addActionListener(listener);
}
// allow outside classes to get text from the text field
public String getTextFieldText() {
return textField.getText();
}
// allow outside classes to put text into the JLabel
public void setLabelText(String text) {
label.setText(text);
}
}
And then we could use it like so:
public class MyCardLayoutDemo extends JPanel {
private static final String[] NAMES = {"One", "Two", "Three", "Four"};
private Map<String, CardPanel> namePanelMap = new HashMap<>();
private CardLayout cardLayout = new CardLayout();
private int nameIndex = 0;
public MyCardLayoutDemo() {
setLayout(cardLayout);
MyListener listener = new MyListener();
for (String name : NAMES) {
CardPanel cardPanel = new CardPanel(name);
cardPanel.addActionListener(listener);
add(cardPanel, name);
namePanelMap.put(name, cardPanel);
}
}
private class MyListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// get the current CardPanel
String name = NAMES[nameIndex];
CardPanel currentCard = namePanelMap.get(name);
// advance the name index to get the next CardPanel
nameIndex++;
nameIndex %= NAMES.length;
name = NAMES[nameIndex];
CardPanel nextCard = namePanelMap.get(name);
// get text from current CardPanel
String text = currentCard.getTextFieldText();
nextCard.setLabelText(text); // and put it into next one
// swap cards
cardLayout.show(MyCardLayoutDemo.this, name);
nextCard.setFocusOnTextField();
}
}
private static void createAndShowGui() {
MyCardLayoutDemo mainPanel = new MyCardLayoutDemo();
JFrame frame = new JFrame("My CardLayout Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}

Appear automatically JTextField

Please, how can I appear automatically some JTextField from what user choose in JComboBox ?
My example is simple. I have a JComboBox in my box with some operation. And depending on what the user choose from this JComboBox, I appear one or more JTextField.
I have this code:
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
CalculatriceFenetre fenetre = new CalculatriceFenetre();
fenetre.setVisible(true);
}
});
}
.
public class CalculatriceFenetre extends JFrame {
private JTextField field1, field2;
private JComboBox liste;
public CalculatriceFenetre() {
super();
build();
}
private void build() {
setTitle("Calculatrice");
setSize(400, 200);
setLocationRelativeTo(null);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setContentPane(buildContentPane());
}
private JPanel buildContentPane() {
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
panel.setBackground(Color.white);
field1 = new JTextField();
field1.setColumns(10);
field2 = new JTextField();
field2.setColumns(10);
field2.setVisible(false);
panel.add(field1);
panel.add(field2);
liste = new JComboBox(new OperateursModel());
liste.addActionListener(new CustomActionListener());
panel.add(liste);
return panel;
}
class CustomActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (liste.getSelectedItem().equals("op1")) {
field2.setVisible(true);
}
}
}
.
public class OperateursModel extends DefaultComboBoxModel {
private ArrayList<String> operateurs;
public OperateursModel(){
super();
operateurs = new ArrayList<String>();
operateurs.add("op1");
}
public String getSelectedOperateur(){
return (String)getSelectedItem();
}
#Override
public Object getElementAt(int index) {
return operateurs.get(index);
}
#Override
public int getSize() {
return operateurs.size();
}
#Override
public int getIndexOf(Object element) {
return operateurs.indexOf(element);
}
}
And depending on what the user choose from this JComboBox, I appear one or more JTextField.
Then you can write an ActionListener to handle the selection of an item from the combo box.
You can start by reading the section from the Swing tutorial on How to Use a Combo Box for a working example that uses an ActionListener.
In your case you want to add a text field to the frame so the code would be something like:
JTextField textField = new JTextField(10);
frame.add( textField );
frame.revalidate();
frame.repaint();
Also, there is no need for you to create a custom ComboBoxModel. You can just add items to the default model. Again, the tutorial will show you how to do this.
Like I mentioned, this is an easy approach for your question. Create all the JTextFields you need first and toggle its visibility instead of removing and adding it on run time.
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class DynamicTextFieldsApp
{
public static void main(String[] args){
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame("JTextField Toggler");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
f.add(new DisplayPanel());
f.pack();
f.setLocationRelativeTo(null);
}});
}
}
A simple JPanel with comboBox and several JTextFields.
class DisplayPanel extends JPanel
{
public static final int PLAYERS = 5;
private JComboBox cmbPlayerNumber;
private JTextField[] txtPlayerName;
private JLabel lblPlayerNumber;
public DisplayPanel(){
setPreferredSize(new Dimension(170, 240));
createComponents();
initComponents();
loadComponents();
setBoundsForComponents();
}
private void createComponents(){
cmbPlayerNumber = new JComboBox(new String[]{"1", "2", "3", "4", "5"});
txtPlayerName = new JTextField[PLAYERS];
lblPlayerNumber = new JLabel("Num of Players");
}
private void initComponents(){
for(int x=0; x<PLAYERS; x++){
txtPlayerName[x] = new JTextField("No Name " + (x+1));
txtPlayerName[x].setVisible(false);
}
cmbPlayerNumber.setSelectedIndex(-1);
cmbPlayerNumber.addActionListener(new CmbListener());
}
private void loadComponents(){
add(cmbPlayerNumber);
add(lblPlayerNumber);
for(int x=0; x<PLAYERS; x++)
add(txtPlayerName[x]);
}
private void setBoundsForComponents(){
setLayout(null);
lblPlayerNumber.setBounds(10, 0, 150, 30);
cmbPlayerNumber.setBounds(10, 30, 150, 30);
for(int x=0; x<PLAYERS; x++)
txtPlayerName[x].setBounds(10, (30*x)+70, 150, 30);
}
private class CmbListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
int numOfPlayers = cmbPlayerNumber.getSelectedIndex() + 1;
for(int x=0; x<numOfPlayers; x++)
txtPlayerName[x].setVisible(true);
for(int x=numOfPlayers; x<PLAYERS; x++){
txtPlayerName[x].setVisible(false);
txtPlayerName[x].setText("No name " + (x+1));
}
}
}
}
And of course, you can work with some layout manager instead of null layout.

update components based on which tab its called from

Hello Guru's I am a beginner Java swing developer and am trying to build a simple app... here is a simplified version.
Setup: 1 JFrame, 2 BorderLayout based tabbed panels (A and B) each has 1 textfiled, shared JPanel class with combo box and ItemListener initialized in each tab's (North)
Issue: How to control updates to textfield's text based on which panel it came from eg. if I select Apples in TabA, the Item Listener updates the TextField on TabB as well. What I would like to accomplish is determine where the call came from TabA or TabB and only update the textfield associated with that tab.
Hope this makes some sense
public class Main extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel contentPane;
public JTextField tfPanelA;
public JTextField tfPanelB;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Main frame = new Main();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Main() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
contentPane.add(tabbedPane, BorderLayout.CENTER);
JPanel panelA = new JPanel();
tabbedPane.addTab("Tab A", null, panelA, null);
panelA.setLayout(new BorderLayout(0, 0));
sharedPanel s1 = new sharedPanel(this);
panelA.add(s1, BorderLayout.NORTH);
tfPanelA = new JTextField();
panelA.add(tfPanelA);
tfPanelA.setColumns(10);
JPanel panelB = new JPanel();
tabbedPane.addTab("Tab B", null, panelB, null);
panelB.setLayout(new BorderLayout(0, 0));
sharedPanel s2 = new sharedPanel(this);
panelB.add(s2, BorderLayout.NORTH);
tfPanelB = new JTextField();
panelB.add(tfPanelB);
tfPanelB.setColumns(10);
}
}
// Shared Class...
public class sharedPanel extends JPanel {
private Main app;
private String[] clist = {"Apples","Oranges","Bananas"};
/**
* Create the panel.
*/
public sharedPanel(final Main app) {
this.app=app;
setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
JComboBox<String> comboBox = new JComboBox<String>();
comboBox.setModel(new DefaultComboBoxModel<String>(clist));
comboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
//update PanelA's textfield ONLY if called from PanelA
// do this if called from PanelA
app.tfPanelA.setText(e.getItem().toString());
// do this if called from PanelB
app.tfPanelB.setText(e.getItem().toString());
}
});
add(comboBox);
}
}
Since you have create a new instance of sharedPanel for each tab, simply provide a reference to the text field you want to be updated to it...
Which you end up with something more like...
public class sharedPanel extends JPanel {
private JTextField field;
private String[] clist = {"Apples","Oranges","Bananas"};
public sharedPanel(final JTextField field) {
this.field=field;
setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
JComboBox<String> comboBox = new JComboBox<String>();
comboBox.setModel(new DefaultComboBoxModel<String>(clist));
comboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
sharedPanel.this.field.setText(e.getItem().toString());
}
});
add(comboBox);
}
}
Updated with a "model" example
This is very basic example of just one possible use of a model to bridge the changes between the common panel and other panels. This means that the common panel doesn't care about anything else and updates the supplied model, which fires events to interested parties who can take appropriate action as required.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class TabbedModel {
protected static final String[] MAIN_LIST = {"Apples","Oranges","Bananas"};
public static void main(String[] args) {
new TabbedModel();
}
public TabbedModel() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JTabbedPane tabPane = new JTabbedPane();
tabPane.addTab("A", new ATab());
tabPane.addTab("B", new ATab());
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(tabPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DefaultCommonModel implements CommonModel {
private List<ChangeListener> listeners;
private String value;
public DefaultCommonModel() {
listeners = new ArrayList<>(25);
}
#Override
public void addChangeListener(ChangeListener listener) {
listeners.add(listener);
}
#Override
public void removeChangeListener(ChangeListener listener) {
listeners.remove(listener);
}
#Override
public void setValue(String aValue) {
if (aValue == null ? value != null : !aValue.equals(value)) {
value = aValue;
fireStateChanged();
}
}
#Override
public String getValue() {
return value;
}
protected void fireStateChanged() {
if (!listeners.isEmpty()) {
ChangeEvent evt = new ChangeEvent(this);
for (ChangeListener listener : listeners) {
listener.stateChanged(evt);
}
}
}
}
public interface CommonModel {
public void addChangeListener(ChangeListener listener);
public void removeChangeListener(ChangeListener listener);
public void setValue(String value);
public String getValue();
}
public class CommonPanel extends JPanel {
private CommonModel model;
private JComboBox comboBox;
public CommonPanel(CommonModel model) {
this.model = model;
setLayout(new GridBagLayout());
comboBox = new JComboBox(new DefaultComboBoxModel<>(MAIN_LIST));
comboBox.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
String value = (String) e.getItem();
CommonPanel.this.model.setValue(value);
}
});
add(comboBox);
}
}
public class ATab extends JPanel {
private List<JTextField> fields;
public ATab() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
DefaultCommonModel model = new DefaultCommonModel();
model.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
CommonModel model = (CommonModel) e.getSource();
for (JTextField field : fields) {
field.setText(model.getValue());
}
}
});
CommonPanel commonPanel = new CommonPanel(model);
add(commonPanel, gbc);
fields = new ArrayList<>(25);
for (int index = 0; index < random(); index++) {
JTextField field = new JTextField(10);
add(field, gbc);
fields.add(field);
}
}
protected int random() {
return (int)Math.round(Math.random() * 9) + 1;
}
}
}
Since you have two instances of your SharedPanel you can add the textfield to be updated as a reference to the constructor:
SharedPanel s1 = new SharedPanel(this, tfPanelA);
and
public SharedPanel(final Main app, final JTextField tf) {
...
comboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
tf.setText(e.getItem().toString());
}
});
...
}

Substitute the currently displayed JPanel with another JPanel within a JFrame

I have three Java classes:
a JFrame: HomeView,
a JPanel: TopicListView,
another JPanel: ReplyListView.
In HomeView, I have a menu item that I can click to display TopicListView. In TopicListView, I want to have a button that I can click to display ReplyListView. When the button is clicked, it will invoke the openReplyListView() method. The method will create a new JPanel and replace the current JPanel with it. However, the code in openReplyListView() do not work.
Note: I am not using CardLayout.
Any help would be appreciated on how to get this working.
Thanks in advance.
HomeView class:
public class HomeView extends JFrame {
private JPanel contentPane;
private JMenuBar menuBar;
private JMenu mnForum;
private JMenuItem mntmReply;
private JMenuItem mntmTopic;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
HomeView frame = new HomeView();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public HomeView() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 1280, 720);
setJMenuBar(getMenuBar_1());
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
}
private JMenuBar getMenuBar_1() {
if (menuBar == null) {
menuBar = new JMenuBar();
menuBar.add(getMnForum());
}
return menuBar;
}
private JMenu getMnForum() {
if (mnForum == null) {
mnForum = new JMenu("Forum");
mnForum.add(getMntmTopic());
mnForum.add(getMntmReply());
}
return mnForum;
}
private JMenuItem getMntmReply() {
if (mntmReply == null) {
mntmReply = new JMenuItem("Reply");
mntmReply.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JPanel panel = new ReplyView();
getContentPane().removeAll();
getContentPane().add(panel);
getContentPane().validate();
getContentPane().repaint();
}
});
}
return mntmReply;
}
private JMenuItem getMntmTopic() {
if (mntmTopic == null) {
mntmTopic = new JMenuItem("Topic");
mntmTopic.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JPanel panel = new TopicListView();
getContentPane().removeAll();
getContentPane().add(panel);
getContentPane().validate();
getContentPane().repaint();
}
});
}
return mntmTopic;
}
}
TopicListView class:
public class TopicListView extends JPanel {
private JTable table;
private JScrollPane scrollPane;
private JLabel lblTopics;
/**
* Create the panel.
*/
public TopicListView() {
setLayout(null);
add(getTable());
add(getScrollPane());
add(getLblTopics());
}
**Code snippet for the table and the scrollpane:**
private void openReplyListView(){
JPanel panel = new ReplyListView();
getContentPane().removeAll();
getContentPane().add(panel);
getContentPane().validate();
getContentPane().repaint();
}
ReplyListView class (In general it's the same as TopicListView)
public class ReplyListView extends JPanel {
private JTable table;
private JScrollPane scrollPane;
private JLabel lblTest;
/**
* Create the panel.
*/
public ReplyListView() {
setLayout(null);
add(getTable());
add(getScrollPane());
add(getLblTest());
}
private JTable getTable() {
if (table == null) {
table = new JTable();
table.setBounds(414, 114, 464, 354);
}
return table;
}
private JScrollPane getScrollPane() {
if (scrollPane == null) {
scrollPane = new JScrollPane(getTable());
scrollPane.setBounds(414, 114, 464, 349);
}
return scrollPane;
}
private JLabel getLblTest() {
if (lblTest == null) {
lblTest = new JLabel("TEST");
lblTest.setFont(new Font("Tahoma", Font.PLAIN, 30));
lblTest.setBounds(593, 35, 81, 68);
}
return lblTest;
}
}
Your TopicListView have no LayoutManger (i.e. setLayout(null) in constructor).
It's usually a bad idea. (I'm pretty sure that's the cause of your problem)
Try something like this
private void openReplyListView(){
JPanel panel = new ReplyListView();
removeAll();
setLayout(new BorderLayout());
add(panel, BorderLayout.CENTER);
validate();
repaint();
}

Categories

Resources