How can i pass the data from one JPanel to other...? - java

I have a JFrame which contains 3 JPanels. I want to pass the JTextField value of one panel to other. Each panel is shown using JTabbedPane. I am getting null when i access the value of other text field. How can i access?

You don't show any code, and so it's impossible to know why you're getting "null" values. Two possible solutions if you want all three JPanels to hold JTextFields with the same content:
Put the shared JTextField outside of the JPanels held by the JTabbedPane and instead in a JPanel that holds the JTabbedPane, so that the field is always visible no matter what tab is displayed, or
Use several JTextFields but have them share the same Document or "model".
e.g.,
import java.awt.Dimension;
import javax.swing.*;
import javax.swing.text.PlainDocument;
public class SharedField extends JTabbedPane {
private static final int TAB_COUNT = 5;
private static final int MY_WIDTH = 600;
private static final int MY_HEIGHT = 300;
PlainDocument doc = new PlainDocument();
public SharedField() {
for (int i = 0; i < TAB_COUNT; i++) {
JTextField tField = new JTextField(10);
tField.setDocument(doc);
JPanel panel = new JPanel();
panel.add(tField);
add("Panel " + i, panel);
// to demonstrate some of the JTextFields acting like
// a label
if (i % 2 == 1) { // if i is odd
tField.setEditable(false);
tField.setBorder(null);
}
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(MY_WIDTH, MY_HEIGHT);
}
private static void createAndShowUI() {
JFrame frame = new JFrame("SharedField");
frame.getContentPane().add(new SharedField());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
Edit 1
I see that you've cross-posted this on java-forums.org/ where you show some of your code:
pacage Demotool;
Class:MainFrame
This is the actionPerformed code of first panel
both str and scrTxt is (public static)
public void actionPerformed(ActionEvent e)
{
String act=e.getActionCommand();
if(act.equals("ADD"))
{
str=scrnTxt.getText();
System.out.println("Hi :"+str);
Demotool.DemoTool.jtp.setSelectedIndex(1);
}
}
using the belove code i tried to access the data but I am getting null String:
System.out.println("Hello:"+Demotool.MainFrame.str);
Problems:
Don't use static variables or methods unless you have a good reason to do so. Here you don't.
You're may be trying to access the MainFrame.str variable before anything has been put into it, making it null, or you are creating a new MainFrame object in your second class, one that isn't displayed, and thus one whose str variable is empty or null -- hard to say.
Either way, this design is not good. You're better off showing us a small demo program that shows your problem with code that compiles and runs, an sscce, so we can play with and modify your code and better be able to show you a decent solution.
One such decent solution is to add a DocumentListener to the JTextField so that changes to the text held by the JTextField are "pushed" into the observers that are listening for changes (your other classes).
For example, using DocumentListeners:
import java.awt.Dimension;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
public class SharedField2 extends JTabbedPane {
private static final int LABEL_PANEL_COUNT = 4;
private static final int MY_WIDTH = 600;
private static final int MY_HEIGHT = 300;
public SharedField2() {
TextFieldPanel tfPanel = new TextFieldPanel();
LabelPanel[] labelPanels = new LabelPanel[LABEL_PANEL_COUNT];
add("TextFieldPanel", tfPanel);
for (int i = 0; i < labelPanels.length; i++) {
labelPanels[i] = new LabelPanel();
// add each label panel's listener to the text field
tfPanel.addDocumentListenerToField(labelPanels[i].getDocumentListener());
add("Label Panel " + i, labelPanels[i]);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(MY_WIDTH, MY_HEIGHT);
}
private static void createAndShowUI() {
JFrame frame = new JFrame("SharedField2");
frame.getContentPane().add(new SharedField2());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
class TextFieldPanel extends JPanel {
private JTextField tField = new JTextField(10);
public TextFieldPanel() {
add(tField);
}
public void addDocumentListenerToField(DocumentListener listener) {
tField.getDocument().addDocumentListener(listener);
}
}
class LabelPanel extends JPanel {
private DocumentListener myListener;
private JLabel label = new JLabel();
public LabelPanel() {
add(label);
myListener = new DocumentListener() {
#Override
public void changedUpdate(DocumentEvent e) {
updateLabel(e);
}
#Override
public void insertUpdate(DocumentEvent e) {
updateLabel(e);
}
#Override
public void removeUpdate(DocumentEvent e) {
updateLabel(e);
}
private void updateLabel(DocumentEvent e) {
try {
label.setText(e.getDocument().getText(0,
e.getDocument().getLength()));
} catch (BadLocationException e1) {
e1.printStackTrace();
}
}
};
}
public DocumentListener getDocumentListener() {
return myListener;
}
}

One simple solution will be making JTextField global so all panel can access it.
Make sure all your panel can access JTextField that is textField is globally accessible.
Following code demonstrate this:
JTextField textField = new JTextField(25);
JLabel labelForPanel2 = new JLabel(),labelForPanel3 = new JLabel();
private void panelDemo() {
JFrame frame = new JFrame();
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
JPanel panel3 = new JPanel();
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.addTab("Tab 1", panel1);
tabbedPane.addTab("Tab 2", panel2);
tabbedPane.addTab("Tab 3", panel3);
panel1.add(textField);
panel2.add(labelForPanel2);
panel3.add(labelForPanel3);
textField.addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
labelForPanel2.setText(textField.getText());
labelForPanel3.setText(textField.getText());
}
});
frame.add(tabbedPane);
frame.setVisible(true);
}

I don't know what exactly are you going to achieve, but maybe try data binding?
Take a look at BetterBeansBinding library.

Related

How to know which jtable has a selected row [duplicate]

I have a class whitch extends JPanel:
public class ButtonPanel extends JPanel {
private label;
public ButtonPanel() {
label=new JLabel("waiting for click");
add(label);
}
public void setButtonText() {
label.setText("just clicked");
}
}
I have several instances of that class which is added to JFrame. I want to create one instanse of MouseAdapter class and then add them as a mouse listener to all of the ButtonPanel components on my JFrame. I meen:
ButtonPanel butt1 = new ButtonPanel();
ButtonPanel butt2 = new ButtonPanel();
ButtonPanel butt3 = new ButtonPanel();
//... here goes code which add ButtonPanels to JFrame
MouseAdapterMod mam = new MouseAdapterMod();
butt1.addMouseListener(mam);
butt2.addMouseListener(mam);
butt3.addMouseListener(mam);
The MouseAdapterMod class I want to be separate from the other and locate in it's own package. It should looks like this:
public class MouseAdapterMod extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
//here goes the code of calling setButtonText method of ButtonPanel component on which the event had occurred
}
}
So the problem is that I don't know how to implement mouseClicked method to make it determine which of ButtonPanel generate the event and call the corresponding to that component setButtonText() method. Is anyone know how to do that?
I know that I can achieve this by including event handling functionality in the ButtonPanel class, but thats not appropriate way for me, cuz I want to keep the class structure as I described above and have only one instance of MouseAdapterMod class for handling all of the ButtonPanels.
The MouseEvent#getSource method will return which object has been clicked:
public class MouseAdapterMod extends MouseAdapter {
// usually better off with mousePressed rather than clicked
public void mousePressed(MouseEvent e) {
ButtonPanel btnPanel = (ButtonPanel)e.getSource();
btnPanel.setButtonText();
}
}
As the comments note, you're often better off listening for mousePressed or mouseReleased rather than mouseClicked because for mouseClicked to work, the press and release must be from the same point, and if the mouse shifts even a slight amount, the click won't register.
My test program:
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;
public class MainForButtonPanel extends JPanel {
public MainForButtonPanel() {
setLayout(new GridLayout(4, 4));
MouseAdapter myMA = new MouseAdapterMod();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
ButtonPanel btnPanel = new ButtonPanel();
btnPanel.addMouseListener(myMA);
add(btnPanel);
}
}
}
private static void createAndShowUI() {
JFrame frame = new JFrame("MainForButtonPanel");
frame.getContentPane().add(new MainForButtonPanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
class ButtonPanel extends JPanel {
private static final int TIMER_DELAY = 2000;
private static final String JUST_CLICKED = "just clicked";
private static final String WAITING_FOR_CLICK = "waiting for click";
private static final Color CLICKED_COLOR = Color.pink;
private JLabel label;
public ButtonPanel() {
label = new JLabel(WAITING_FOR_CLICK);
add(label);
}
public void setButtonText() {
label.setText(JUST_CLICKED);
setBackground(CLICKED_COLOR);
new Timer(TIMER_DELAY, new ActionListener() {
public void actionPerformed(ActionEvent ae) {
label.setText(WAITING_FOR_CLICK);
setBackground(null);
((Timer)ae.getSource()).stop();
}
}).start();
}
}
class MouseAdapterMod extends MouseAdapter {
// usually better off with mousePressed rather than clicked
public void mousePressed(MouseEvent e) {
ButtonPanel btnPanel = (ButtonPanel)e.getSource();
btnPanel.setButtonText();
}
}

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.

A individual class for each Card in java swing CardLayout

For architecture and design purposes I would like to design my GUI with a class for each card in a Java Swing CardLayout. and then have a mainapp that builds the GUI. I am having trouble doing this right now.
I would like to example have a class for the main menu with all the button locations etc. and then just instantiate that card and add it to the layout in another class. Does anyone know how to achieve this?
Perhaps you want to give your class that uses the CardLayout a public loadCard method, something like
public void loadCard(JComponent component, String key) {
cardHolderPanel.add(component, key);
}
where cardHolderPanel is the container that holds the cards.
Since your creating classes to act as cards, consider having them all extend from a base abstract class or an interface that has a method that allows this class to hold its own key String. Either that or simply use the JComponent name property to have a component hold its own key String, one that can easily be obtained via getName().
For a more detailed answer, you may need to give us more details on your current application and its structure.
very simple example that held Swing Objects generated from different Java Classes
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class OnTheFlyImageTest extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel cardPanel;
private CardLayout cardLayout;
public OnTheFlyImageTest() {
JPanel cp = new JPanel(new BorderLayout());
cp.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
cardLayout = new CardLayout(5, 5);
cardPanel = new JPanel(cardLayout);
cp.add(cardPanel);
for (int i = 0; i < 100; i++) {// Create random panels for testing.
String name = "ImagePanel" + (i + 1);
String image = (i & 1) == 0 ? "foo.gif" : "bar.gif";
ImagePanel imgPanel = new ImagePanel(name, image);
cardPanel.add(imgPanel, name);
cardLayout.addLayoutComponent(imgPanel, name);
}
JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 5, 5));
JButton prevButton = new JButton("< Previous");
prevButton.setActionCommand("Previous");
prevButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
cardLayout.previous(cardPanel);
}
});
buttonPanel.add(prevButton);
JButton nextButton = new JButton("Next >");
nextButton.setActionCommand("Next");
nextButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
cardLayout.next(cardPanel);
}
});
buttonPanel.add(nextButton);
JPanel temp = new JPanel(new BorderLayout());
temp.add(buttonPanel, BorderLayout.LINE_END);
cp.add(temp, BorderLayout.SOUTH);
setContentPane(cp);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("Test");
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new OnTheFlyImageTest().setVisible(true);
}
});
}
}
class ImagePanel extends JPanel {
private static final long serialVersionUID = 1L;
private String imgString;
private JLabel imgLabel;
public ImagePanel(String name, String imgString) {
setName(name);
this.imgString = imgString;
setLayout(new BorderLayout());
// Ensure size is correct even before any image is loaded.
setPreferredSize(new Dimension(640, 480));
}
#Override
public void setVisible(boolean visible) {
if (visible) {
System.err.println(getName() + ": Loading and adding image");
ImageIcon icon = new ImageIcon(imgString);
imgLabel = new JLabel(icon);
add(imgLabel);
}
super.setVisible(visible);
if (!visible) { // Do after super.setVisible() so image doesn't "disappear".
System.err.println(getName() + ": Removing image");
if (imgLabel != null) { // Before display, this will be null
remove(imgLabel);
imgLabel = null; // Hint to GC that component/image can be collected.
}
}
}
}

Java : Swing : Hide frame after button pressed

I have a button in a java frame that when pressed it reads a value from a text field and uses that string as a port name attempting to connect to a serial device.
If this connection is successful the method returns true if not it returns false. If it returns true I want the frame to disappear. A series of other frames specifed in other classes will then appear with options to control the serial device.
My problem is: the button is connected to an action listener, when pressed this method is invoked. If I try to use the frame.setVisible(true); method java throws a abstract button error because I'm effectively telling it to disappear the frame containing the button before the button press method has exited. Removing the frame.setVisible(true); allow the program to run correctly however I am left with a lingering connection frame that is no longer any use.
How to I get the frame to disappear upon pressing a the button?
package newimplementation1;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
*
* #author Zac
*/
public class ConnectionFrame extends JPanel implements ActionListener {
private JTextField textField;
private JFrame frame;
private JButton connectButton;
private final static String newline = "\n";
public ConnectionFrame(){
super(new GridBagLayout());
textField = new JTextField(14);
textField.addActionListener(this);
textField.setText("/dev/ttyUSB0");
connectButton = new JButton("Connect");
//Add Components to this panel.
GridBagConstraints c = new GridBagConstraints();
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.HORIZONTAL;
add(textField, c);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
c.weighty = 1.0;
add(connectButton, c);
connectButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
boolean success = Main.mySerialTest.initialize(textField.getText());
if (success == false) {System.out.println("Could not connect"); return;}
frame.setVisible(false); // THIS DOES NOT WORK!!
JTextInputArea myInputArea = new JTextInputArea();
myInputArea.createAndShowGUI();
System.out.println("Connected");
}
});
}
public void actionPerformed(ActionEvent evt) {
// Unimplemented required for JPanel
}
public void createAndShowGUI() {
//Create and set up the window.
frame = new JFrame("Serial Port Query");
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
//Add contents to the window.
frame.add(new ConnectionFrame());
frame.setLocation(300, 0);
//Display the window.
frame.pack();
frame.setVisible(true);
frame.addComponentListener(new ComponentAdapter() {
#Override
public void componentHidden(ComponentEvent e) {
System.out.println("Exiting Gracefully");
Main.mySerialTest.close();
((JFrame)(e.getComponent())).dispose();
System.exit(0);
}
});
}
}
Running your snippet (after removing/tweaking around the custom classes), throws an NPE. Reason is that the frame you'r accessing is null. And that's because it's never set. Better not rely on any field, let the button find its toplevel ancestor and hide that, like in
public void actionPerformed(final ActionEvent e) {
boolean success = true;
if (success == false) {
System.out.println("Could not connect");
return;
}
Window frame = SwingUtilities.windowForComponent((Component) e
.getSource());
frame.setVisible(false); //no problem :-)
}
Your problem is with this line:
frame.add(new ConnectionFrame());
You're creating a new ConnectionFrame object, and so the frame that your button tries to close on is not the same as the one being displayed, and this is the source of your problem.
If you change it to,
//!! frame.add(new ConnectionFrame());
frame.add(this);
so that the two JFrames are one and the same, things may work more smoothly.
But having said that, your whole design smells bad and I'd rethink it in a more OOP and less static fashion. Also, use dialogs where dialogs are needed, not frames, and rather than dialogs consider swapping views (JPanels) via CardLayout as a better option still.
Myself, I'd create a "dumb" GUI for this, one that creates a JPanel (here in my example it extends a JPanel for simplicity, but I'd avoid extending if not necessary), and I'd let whoever is calling this code decide what to do with the information via some control. For e.g.,
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class ConnectionPanel extends JPanel {
private JTextField textField;
private JButton connectButton;
private ConnectionPanelControl control;
public ConnectionPanel(final ConnectionPanelControl control) {
super(new GridBagLayout());
this.control = control;
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (control != null) {
control.connectButtonAction();
}
}
};
textField = new JTextField(14);
textField.addActionListener(listener);
textField.setText("/dev/ttyUSB0");
connectButton = new JButton("Connect");
GridBagConstraints c = new GridBagConstraints();
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.HORIZONTAL;
add(textField, c);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
c.weighty = 1.0;
add(connectButton, c);
connectButton.addActionListener(listener);
}
public String getFieldText() {
return textField.getText();
}
}
Again, something outside of the simple GUI would make decisions on what to do with the text that the textfield contains and what to do with the GUI that is displaying this JPanel:
public interface ConnectionPanelControl {
void connectButtonAction();
}
Also, you will likely do any connecting in a background thread so as to not freeze your GUI, probably a SwingWorker. Perhaps something like this:
import java.awt.event.ActionEvent;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
#SuppressWarnings("serial")
public class MyMain extends JPanel {
public MyMain() {
add(new JButton(new ConnectionAction("Connect", this)));
}
private static void createAndShowGui() {
JFrame frame = new JFrame("My Main");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new MyMain());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
#SuppressWarnings("serial")
class ConnectionAction extends AbstractAction {
private MyMain myMain;
private ConnectionPanel cPanel = null;
private JDialog dialog = null;
public ConnectionAction(String title, MyMain myMain) {
super(title);
this.myMain = myMain;
}
#Override
public void actionPerformed(ActionEvent e) {
if (dialog == null) {
dialog = new JDialog(SwingUtilities.getWindowAncestor(myMain));
dialog.setTitle("Connect");
dialog.setModal(true);
cPanel = new ConnectionPanel(new ConnectionPanelControl() {
#Override
public void connectButtonAction() {
final String connectStr = cPanel.getFieldText();
new MySwingWorker(connectStr).execute();
}
});
dialog.getContentPane().add(cPanel);
dialog.pack();
dialog.setLocationRelativeTo(null);
}
dialog.setVisible(true);
}
private class MySwingWorker extends SwingWorker<Boolean, Void> {
private String connectStr = "";
public MySwingWorker(String connectStr) {
this.connectStr = connectStr;
}
#Override
protected Boolean doInBackground() throws Exception {
// TODO: make connection and then return a result
// right now making true if any text in the field
if (!connectStr.isEmpty()) {
return true;
}
return false;
}
#Override
protected void done() {
try {
boolean result = get();
if (result) {
System.out.println("connection successful");
dialog.dispose();
} else {
System.out.println("connection not successful");
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
Your code would be much more readable if you named JFrame instances xxxFrame, and JPanel instances xxxPanel. Naming JPanel instances xxxFrame makes things very confusing.
It would also help if you pasted the stack trace of the exception.
I suspect the problem comes from the fact that frame is null. This is due to the fact that the frame field is only initialized in the createAndShowGUI method, but this method doesn't display the current connection panel, but a new one, which thus have a null frame field:
ConnectionFrame firstPanel = new ConnectionFrame();
// The firstPanel's frame field is null
firstPanel.createAndShowGUI();
// the firstPanel's frame field is now not null, but
// the above call opens a JFrame containing another, new ConnectionFrame,
// which has a null frame field
The code of createAndShowGUI should contain
frame.add(this);
rather than
frame.add(new ConnectionFrame());
for Swing GUI is better create only once JFrame and another Top-Level Containers would be JDialog or JWindow(un-decorated by default),
simple example here
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SuperConstructor extends JFrame {
private static final long serialVersionUID = 1L;
public SuperConstructor() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setPreferredSize(new Dimension(300, 300));
setTitle("Super constructor");
Container cp = getContentPane();
JButton b = new JButton("Show dialog");
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
FirstDialog firstDialog = new FirstDialog(SuperConstructor.this);
}
});
cp.add(b, BorderLayout.SOUTH);
JButton bClose = new JButton("Close");
bClose.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
System.exit(0);
}
});
add(bClose, BorderLayout.NORTH);
pack();
setVisible(true);
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
SuperConstructor superConstructor = new SuperConstructor();
}
});
}
private class FirstDialog extends JDialog {
private static final long serialVersionUID = 1L;
FirstDialog(final Frame parent) {
super(parent, "FirstDialog");
setPreferredSize(new Dimension(200, 200));
setLocationRelativeTo(parent);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setModalityType(Dialog.ModalityType.DOCUMENT_MODAL);
JButton bNext = new JButton("Show next dialog");
bNext.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
SecondDialog secondDialog = new SecondDialog(parent, false);
}
});
add(bNext, BorderLayout.NORTH);
JButton bClose = new JButton("Close");
bClose.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
setVisible(false);
}
});
add(bClose, BorderLayout.SOUTH);
pack();
setVisible(true);
}
}
private int i;
private class SecondDialog extends JDialog {
private static final long serialVersionUID = 1L;
SecondDialog(final Frame parent, boolean modal) {
//super(parent); // Makes this dialog unfocusable as long as FirstDialog is visible
setPreferredSize(new Dimension(200, 200));
setLocation(300, 50);
setModal(modal);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setTitle("SecondDialog " + (i++));
JButton bClose = new JButton("Close");
bClose.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
setVisible(false);
}
});
add(bClose, BorderLayout.SOUTH);
pack();
setVisible(true);
}
}
}
better would be re-use Top-Level Containers, as create lots of Top-Level Containers on Runtime (possible memory lack)

Categories

Resources