Passing values between classes - java

I have a JPanel form which contains a JList and some JButton.
The JPanel looks like this
When I click the Add List button, a separate JFrame form is displayed.
The JFrame form will look like this
When the add button on the JFrame is clicked, I need to add the value of the JTextfield (named List Name) to the JList on the previous JPanel. I wonder how to pass the value from the JFrame to the JPanel? Any suggestion would be appreciated.
Here is a code of the JPanel form (using Designer GUI)
package multimediaproject;
public class musicPlayerPanel extends javax.swing.JPanel {
public musicPlayerPanel() {
initComponents();
}
private void initComponents() {
//...here is the generated code by using designer GUI
}
// Variables declaration - do not modify
//..generated code
// End of variables declaration
}
Here is the code of JFrame form (using Designer GUI)
package multimediaproject;
public class addListFrame extends javax.swing.JFrame {
public addListFrame() {
initComponents();
this.setLocation(515, 0);
setVisible(true);
}
private void initComponents() {
//..here is the generated code by using Designer GUI
}
private void addBtnActionPerformed(java.awt.event.ActionEvent evt){
//some validation
if(...)
{
//validation
}
else
{
//IF VALUE IS CORRECT, ADD the List Name JTextfield value to the JList on the previous JPanel
errorMessage.setText("");
}
}
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new addListFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
//....generated code
// End of variables declaration
}

UPDATE with your code.
You can take advantage of PropertyChangeListener and PropertyChangeSupport (This classes implements Observer Pattern).
I give you an example you for guidance:
public class MusicPlayerPanel extends JPanel {
private JList list;
private JButton addButton;
private PropertyChangeListener listener = new MyPropertyChangeListener();
//..in some place
addButton.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
JFrame form = new FrameForm();
form.addPropertyChangeListener(FrameForm.BUTTON_CLICKED,listener);
form.setVisible(true);
}
});
//in another place
private class MyPropertyChangeListener implements PropertyChangeListener{
#Override
public void propertyChange(PropertyChangeEvent evt){
if(evt == null)
return;
if(evt.getPropertyName().equals(FrameForm.BUTTON_CLICKED)){
String value = (String) evt.getNewValue();
((DefaultListModel)list.getModel()).addElement(value);
}
}
}
}
And the frame form like this:
public class AddListFrame extends JFrame{
private JTextField textfield;
private JButton submitButton;
public static final String BUTTON_CLICKED ="buttonClicked";
// in some place
submitButton.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent evt){
firePropertyChange(BUTTON_CLICKED,null,textfield.getText());
}
});
}
Note: In java by convention, classes start with uppercase and follow a camel style. This is very important for readability.

OK.This is easy if i understand your problem.
Step 1:Create setter and getter for your JList object reference.
Step 2:On button click , when you open new JFrame pass your panel reference in constructor of class which inherits JFrame.
Step 3:By doing this you are able to call getter method on panel reference.
Step 4:Now you have reference of JList,do what you want.
I hope this is best solution of your problem

"when I click the add button, a separate jFrame form is displayed. The jFrame contain a jTextfield and a submit button."
Did you seriously create an entirely new JFrame for a JTextField and a JButton?!
Have you not heard of JOptionPane? That's exactly what you are trying to replicate. The only code you need is this:
String s = JOptionPane.showInputDialog(component, message);
model.addElement(s);
The first line will cover all your code for your custom JFrame.
Take a look at this example
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class JOPDemo extends JPanel {
JList list;
JButton button = new JButton("Add Name");
String name;
DefaultListModel model;
public JOPDemo() {
model = new DefaultListModel();
list = new JList(model);
setLayout(new BorderLayout());
add(list, BorderLayout.CENTER);
add(button, BorderLayout.SOUTH);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
name = JOptionPane.showInputDialog(this, "Enter a name");
model.addElement(name);
}
});
}
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
private static void createAndShowGui() {
JFrame frame = new JFrame();
frame.add(new JOPDemo());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Edit
What you can do is have an inner class which is your JFrame. Personally, I'd go with a JDialog though.
From comment: Have your frame as an inner class of your main class. That way it can access all the variables from your main class. You can have a String listName also in the GUI class. From the other frame when you hit add, it sets the listName in GUI class, then adds to the list.
public class GUI {
String listName;
JList list;
InnerFrame inner = new InnerFrame();
private class InnerFrame extends JFrame {
JButton addButton;
}
}

Related

split GUI in few classes

I'm writting a program and the GUi Class (main class) is overloaded.
I want to know if it's possible to split the class in several classes.
for example I made a class of constaints.
The main question is if I can keep all interface code in one class(where I'll addd and initialize JTetxFields,JButtons and other Jobjects) and then use them in another class.
for example:
in interface class there will be:
JTextField field = new JTextField(12);
JButton button = new JButton("Click");
and in main class I do smthng like this:
add(field);
add(button);
button.addActionListener(this);
public void actionPerformed(ActionEvent e) {
if(e.getSource==button){
field.setVisible(false);
}
if it's possible with creating new JFrame,then please tell me how to create new Frame and use it in main class.
Your main question -- can you create a class that is a repository of your GUI components and use them elsewhere, and the answer is yes you can, but I don't think that you should, at least not for simple components. You should keep your JTextFields, JButtons in the GUI classes that use them, but any major subsection of your GUI, such as a JPanel that contains components and that has a unique functionality, that can go in its own class.
More important is to separate out different functional parts of your program, especially you should try to separate out the logical or "model" part of your program from the GUI or "view" part. The details of how you do this will depend on the details of your program and overall problem.
For example:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class SeparateClasses {
private static void createAndShowGui() {
SeparateClassView mainPanel = new SeparateClassView();
new SeparateClassControl(mainPanel);
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
public class SeparateClassView extends JPanel {
private JTextField field1 = new JTextField(12);
private JTextField field2 = new JTextField(12);
private JTextField resultField = new JTextField("false", 5);
private JButton button = new JButton("Click");
public SeparateClassView() {
resultField.setEditable(false);
resultField.setFocusable(false);
add(new JLabel("Field 1:"));
add(field1);
add(new JLabel("Field 2:"));
add(field2);
add(button);
add(new JLabel("Two texts equivalent?:"));
add(resultField);
}
public void addButtonListener(ActionListener listener) {
button.addActionListener(listener);
field1.addActionListener(listener);
field2.addActionListener(listener);
}
public String getField1Text() {
return field1.getText();
}
public String getField2Text() {
return field2.getText();
}
public void setField1Text(String text) {
field1.setText(text);
}
public void setField2Text(String text) {
field2.setText(text);
}
public void setResult(boolean result) {
resultField.setText(String.valueOf(result));
}
}
public class SeparateClassControl implements ActionListener {
private SeparateClassView view;
public SeparateClassControl(SeparateClassView view) {
this.view = view;
view.addButtonListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
String text1 = view.getField1Text();
String text2 = view.getField2Text();
boolean result = SeparateClassModel.stringsEquivalent(text1, text2);
view.setResult(result);
}
}
public class SeparateClassModel {
public static boolean stringsEquivalent(String text1, String text2) {
return text1.equalsIgnoreCase(text2);
}
}

How to refresh instance of class if some action in another class was done

I have class DnyMesice what creates many instances of JButton. Every instance contains variable poznamkaDne. This class DnyMesice contains actionListener to find poznamkaDne value of pushed JButton.
I have class Gui what creates one instance of mentioned class DnyMesice and one instance of JTextArea.
How can I refresh value of JTextArea (names poznamkovePole) if some JButton (in class DnyMesice) is pushed?
public class DnyMesice extends JPanel {
public String poznamkaDne="first note";
jButton tlacitkoDen;
public void zobrazMesic(Calendar kalendar){
for (c=1; c<30; c++){
tlacitkoDen = new JButton(Integer.toString(denvMesici));
tlacitkoDen.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent evt) {
poznamkaDne="New note";
};
});
add(tlacitkoDen);
}
}
}
public class Gui extends JFrame {
...
public void zobrazKalendar(){
...
panel3 = new JPanel();
panel3.setLayout(new FlowLayout());
add(panel3);
JTextArea poznamkovePole;
poznamkovePole = new JTextArea();
poznamkovePole.setColumns(30);
poznamkovePole.setRows(5);
poznamkovePole.setText(panel2.poznamkaDne);
panel3.add(poznamkovePole);
}
Now the program shows in JTextArea only "first note" (which is defined during creating of instance JButton) but hot to refresh it after ActionListener action?
Maybe better if you will use:
Add to DnyMesice JTextArea link and in ActionListener change text.
public class DnyMesice extends JPanel {
private JTextArea poznamkaDne;
jButton tlacitkoDen;
public DnyMesice (JTextArea jTextArea){
this.poznamkaDne = jTextArea;
}
public void zobrazMesic(Calendar kalendar){
for (c=1; c<30; c++){
tlacitkoDen = new JButton(Integer.toString(denvMesici));
tlacitkoDen.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent evt) {
poznamkaDne.setText("New note");
};
});
add(tlacitkoDen);
}
}
}
P.S. - And please don't forget to use Code Conventions for the Java
Modify as follows:
// add these methods
public void setPoznamkaDne(String s) {
poznamkaDne = s;
}
public String getPoznamkaDne() {
return poznamkaDne;
}
// CHANGE this method (KEEP the rest of the code!)
public void actionPerformed(ActionEvent evt) {
setPoznamkaDne("New note");
};
poznamkovePole.setText(panel2.getPoznamkaDne());
These changes should allow you to update the text. BUT you need to either call poznamekovePole.setText() somehow, or implement an advanced listener class. I recommend combining your class like #Too Strong Magic said, above.

use actionlistener to call void function in same class

I have problem to use action listener to call function void in same class.
example..
code:
public class Product extends JPanel {
JButton add;
JPanel pAdd;
JLabel test;
JFrame frame;
public Product() {
add = new JButton("Add Product");
add.addActionListener(new ButtonListener());
add(add);
}
public void panelAdd(){
pAdd = new JPanel();
pAdd.add(new JLabel("try"));
add(pAdd);
}
private class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
panelAdd();
}
}
}
How to make call the panelAdd void method?
When you add components to visible JFrame/JPanel/other components, you neet to call revalidate() andrepaint() methods after adding. Change your panelAdd() like next:
public void panelAdd(){
pAdd = new JPanel();
pAdd.add(new JLabel("try"));
add(pAdd);
revalidate();
repaint();
}
If you put
System.out.println("hi");
to
public void panelAdd(){
System.out.println("hi");
pAdd = new JPanel();
pAdd.add(new JLabel("try"));
add(pAdd);
}
you will see hi printed to your console , your code are working, but you have problem in Layout .

How to make a JList "refresh" method in a JPanel class

I'm a beginner at java and want to make a JFrame with tabs containing a seperate JPanel. One panel has a list where it displays things that you select in a different panel, so I want this panel to always display a list of stuff that you have selected in a different panel (I hope that makes sense). To do this, I need to make a method to refresh the JList. This is the Farthest that I've gotten on that:
public class PanelClass extends JPanel {
private JList list;
private DefaultListModel listModel = new DefaultListModel();
private ArrayList<SomeOtherClass> objectArray = new ArrayList<SomeOtherClass>();
public PanelClass() {
list.setModel(listModel);
}
public void refresh() {
updateListModel();
list.setModel(listModel);
}
public void updateListModel() {
if (objectArray.isEmpty()) {
System.out.println("No Objects In Array!");
} else {
listModel.clear();
for (SomeOtherClass SOC : objectArray) {
// SOC.getName() just returns a string
listModel.addElement(SOC.getName());
}
}
}
public void addObjectToArray(SomeOtherClass SOC) {
objectArray.add(SOC);
}
}
Could someone please tell me how to make a "refresh" method to constantly keep the JList up to date?
The AWT/Swing event model is based upon the widgets being event sources (in the MVC paradigm, they are both view and controller). Different widgets source different event types.
Look at the java.awt.event (primarily), and javax.swing.event packages for the listener interfaces you'll need to implement and register in order to produce your desired effect.
Basically, you write a Listener implementation, and register it with Widget1. When Widget1 detects an event, it will notify you, and you can then use the information it provides to update Widget2.
For instance, if a button being clicked would add an object to your list, you might have something like below (I usually put this code in the encompassing JFrame class, and make it implement the listener interfaces; but you can choose to use inner classes or separate listener classes):
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MyFrame extends JFrame implements ActionListener {
private JButton button = new JButton("Click me!");
private DefaultListModel<String> listModel = new DefaultListModel<String>();
private JList<String> list = new JList<String>(listModel);
private int counter = 1;
public MyFrame() {
setTitle("Test Updates");
JTabbedPane tabs = new JTabbedPane();
add(tabs, BorderLayout.CENTER);
JPanel panel = new JPanel();
panel.add(list);
tabs.add("Selections", panel);
panel = new JPanel();
button.addActionListener(this);
panel.add(button);
tabs.add("Options", panel);
pack();
}
#Override
public void actionPerformed(final ActionEvent event) {
if (button.equals(event.getSource())) {
listModel.addElement("Item " + counter++);
}
}
/* Test it! */
public static void main(String[] args) {
final MyFrame frame = new MyFrame();
frame.addWindowListener(new WindowAdapter() {
#Override public void windowClosing(final WindowEvent e) {
frame.setVisible(false);
frame.dispose();
System.exit(0);
}
});
frame.setVisible(true);
}
}
This code sample is minimal, but it should give you an idea of how to go about implementing what you want.
You can do it in two way. First : Write it in infinite thread loop so that it will constantly update JList. Second : You can call refresh() method whenever new SOC objects are added in your ArrayList. It means you can call refresh() method from addObjectToArray() method which ultimately call the refresh method only when you have some change in your ArrayList.
FYI : I did it in my project and I went for second option.

One JFrame opening another

I have a JFrame and JPanel full of Jsomethings with an actionlistener. When the user clicks an object I want to open another JFrame. Here is what I did:
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source == rejectionbutton){
RejectApp ra = new RejectApp();
ra.main(null);
}
}
(RejectApp calls a new JFrame.) So another JFrame opens on the screen with more options. It works OK (so far), but I want to know is this standard? I mean calling the main method like this?
Another question is, without using a cardlayout (which I don't want to use), is the best way to handle multiple panels, by doing this sort of thing?
I would change a few things. First off, usually an application has one JFrame and then if it needs to show another window does so as a modal or non-modal dialog such as can be obtained with a JDialog or JOptionPane. Having said that, it's even more common to have one JFrame and swap "views" in the JFrame -- swap contentPanes or other large panels via a CardLayout as this would mimic the behavior of many gui programs we all currently use.
Personally, I also try to gear my GUI creation towards creating a JPanel or JComponent rather than towards creating a top-level window. This way if I want to display the GUI as a stand alone app, a dialog, or an applet I can pop it into the contentPane of a JFrame or JDialog or JApplet respectively, or if as an inner panel of a more complex GUI, then insert it there, or in an application with a swapping view, then as a card in a CardLayout as noted above. The bottom line is I feel that this structure gives you the developer a lot more options in how you can use this GUI.
Also, I would avoid calling another class's main as you're doing (assuming this is the public static void main method) as you lose all benefits of OOPs. You also seem to be trying to call a static method in a non-static way (assuming I understand your program structure correctly).
For your second question, it begs a question of my own: why do you not want to use CardLayout?
edit: an example of what I meant is as follows:
import java.awt.Dimension;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class SwingEg {
private static void createAndShowUI() {
JFrame frame = new JFrame("Main JFrame");
frame.getContentPane().add(new MainGUI().getMainPanel());
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 MainGUI {
private static final Dimension MAIN_PANEL_SIZE = new Dimension(450, 300);
private JPanel mainPanel = new JPanel();
private JDialog modalDialog;
private JDialog nonModalDialog;
public MainGUI() {
JButton openModalDialogBtn = new JButton("Open Modal Dialog Window");
openModalDialogBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
openModalDialogBtnActionPerformed(e);
}
});
JButton openNonModalDialogBtn = new JButton("Open Non-Modal Dialog Window");
openNonModalDialogBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
openNonModalDialogBtnActionPerformed(e);
}
});
mainPanel.setPreferredSize(MAIN_PANEL_SIZE);
mainPanel.add(openModalDialogBtn);
mainPanel.add(openNonModalDialogBtn);
}
private void openModalDialogBtnActionPerformed(ActionEvent e) {
if (modalDialog == null) {
Window topWindow = SwingUtilities.getWindowAncestor(mainPanel);
modalDialog = new JDialog(topWindow, "Modal Dialog", ModalityType.APPLICATION_MODAL);
modalDialog.getContentPane().add(new DialogPanel().getMainPanel());
modalDialog.pack();
modalDialog.setLocationRelativeTo(topWindow);
modalDialog.setVisible(true);
} else {
modalDialog.setVisible(true);
}
}
private void openNonModalDialogBtnActionPerformed(ActionEvent e) {
if (nonModalDialog == null) {
Window topWindow = SwingUtilities.getWindowAncestor(mainPanel);
nonModalDialog = new JDialog(topWindow, "Non-Modal Dialog", ModalityType.MODELESS);
nonModalDialog.getContentPane().add(new DialogPanel().getMainPanel());
nonModalDialog.pack();
nonModalDialog.setLocationRelativeTo(topWindow);
nonModalDialog.setVisible(true);
} else {
nonModalDialog.setVisible(true);
}
}
public JPanel getMainPanel() {
return mainPanel;
}
}
class DialogPanel {
private static final Dimension DIALOG_SIZE = new Dimension(300, 200);
private JPanel dialogPanel = new JPanel();
public DialogPanel() {
dialogPanel.add(new JLabel("Hello from a dialog", SwingConstants.CENTER));
dialogPanel.setPreferredSize(DIALOG_SIZE);
}
public JPanel getMainPanel() {
return dialogPanel;
}
}
I would rather make a new instance of JFrame or a subclass, or call a new method who makes a new JFrame:
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source == rejectionbutton){
JFrame frame = new JFrame("New Frame");
//or
makeNewFrame();
}
}
Another simple Layout-Manager is the BorderLayout, it´s the default Layout-Manager of the JFrame class.
new YourJFrameNameHere().setVisible(true);
Replace YourJFrameNameHere with the JFrame name.
Simple, no?

Categories