So I want to have a CardLayout class that switches between a menu page and a main app page, but I want to design those two panels in their own classes, then add an ActionListener and a CardLayout in a different class, and have the ActionListener use a button created in one of the panel classes.
Here is a (Not so short) SSCCE that kind of covers what I'm trying to say:
import java.awt.*;
import javax.swing.*;
public class MenuPanel extends Frame{
JPanel menuPanel;
JButton login;
JButton signup;
public MenuPanel(){
menuPanel = new JPanel(new GridBagLayout());
login = new JButton("Login");
signup = new JButton("Signup");
menuPanel.add(login);
menuPanel.add(signup);
}
}
import java.awt.*;
import javax.swing.*;
public class MainPanel extends JFrame{
JPanel menuPanel;
JButton login;
JButton signup;
public MainPanel(){
mainPanel = new JPanel(new GridBagLayout());=
menuPanel.setBackground(Color.grey);
}
}
import java.awt.*;
import javax.swing.*;
public class CardLayout extends Frame implements ActionL {
//Now how do I add the frames from the other classes so that I can add them to my CardLayout?
CardLayout cl = new CardLayout();
JPanel panelCont;
public CardLayout() {
frame.add(panelCont);
panelCont = new JPanel(cl);
//Here is where I'm having trouble
panelCont.add(menuPanel, "1");
panelCont.add(mainPanel, "2");
cl.show(panelCont, "1");
login.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
cl.show(panelCont, "2");
}
});
}
}
public class Main {
public static void main(String[] args) {
new CardLayout();
}
}
You cannot add Frames to another component. Frame is a top level component with a native peer. You should subclass from something else (JPanel?) instead
Also, btw what you are doing is not good design. Generally, in MVC Swing design, all view and control aspects should be in one class. Don't split the view into multiple classes unless each of those classes stands up as its own reusable widget
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay close attention to the Concurrency in Swing and the Laying Out Components Within a Container sections.
In Java Swing, you create one JFrame and as many JPanels as you need to create the GUI.
I created a card JPanel, a menu JPanel, and a login JPanel in three separate classes. The card JPanel class creates the JPanel with the CardLayout. The menu JPanel creates the JPanel that contains the menu JButtons. The login JPanel class creates the JPanel that contains the login Swing components.
Here's the JFrame with the menu JPanel.
Here's the GUI after you left-click on the Login JButton.
Notice how I named the classes. CardPanel, MenuPanel, LoginPanel. By appending Panel to the end of the class name, that tells me they use a JPanel.
When I create a separate ActionListener class, I'd name it ButtonListener or SignupListener.
The only ActionListener I created ties the menu login JButton to displaying the login JPanel. Since it consists of one line, I made it an anonymous class using a lambda expression.
Here's the complete runnable code. I made all the additional classes inner classes so I could post this code as one block. You can and should put these classes in separate files.
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class CardLayoutExample implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new CardLayoutExample());
}
#Override
public void run() {
JFrame frame = new JFrame("CardLayout Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new CardPanel().getPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public class CardPanel {
private final CardLayout cardLayout;
private final JPanel panel;
public CardPanel() {
this.cardLayout = new CardLayout();
this.panel = createCardPanel();
}
private JPanel createCardPanel() {
JPanel panel = new JPanel(cardLayout);
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
panel.add(new MenuPanel(this).getPanel(), "menu");
panel.add(new LoginPanel().getPanel(), "login");
return panel;
}
public void showLoginPanel() {
cardLayout.show(panel, "login");
}
public JPanel getPanel() {
return panel;
}
}
public class MenuPanel {
private final CardPanel cardPanel;
private final JPanel panel;
public MenuPanel(CardPanel cardPanel) {
this.cardPanel = cardPanel;
this.panel = createMenuPanel();
}
private JPanel createMenuPanel() {
JPanel panel = new JPanel(new GridLayout(0, 1, 5, 5));
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JButton login = new JButton("Login");
login.addActionListener(event -> cardPanel.showLoginPanel());
panel.add(login);
JButton signup = new JButton("Signup");
panel.add(signup);
return panel;
}
public JPanel getPanel() {
return panel;
}
}
public class LoginPanel {
private final JPanel panel;
private final JPasswordField passwordField;
private final JTextField useridField;
public LoginPanel() {
this.useridField = new JTextField(30);
this.passwordField = new JPasswordField(30);
this.panel = createLoginPanel();
}
private JPanel createLoginPanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.fill = GridBagConstraints.NONE;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 0;
JLabel label = new JLabel("Userid:");
panel.add(label, gbc);
gbc.gridx++;
panel.add(useridField, gbc);
gbc.gridx = 0;
gbc.gridy++;
label = new JLabel("Password:");
panel.add(label, gbc);
gbc.gridx++;
panel.add(passwordField, gbc);
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridwidth = 2;
gbc.gridx = 0;
gbc.gridy++;
JButton button = new JButton("Submit");
panel.add(button, gbc);
return panel;
}
public String getUserid() {
return useridField.getText();
}
public char[] getPassword() {
return passwordField.getPassword();
}
public JPanel getPanel() {
return panel;
}
}
}
Related
I am creating a MDI Application by Java.
I design a JInternalFrame
public class account extends javax.swing.JInternalFrame
{account GUI here}
that show data get from SQL. On this account, I create a JButton named btnReName
private javax.swing.JButton btnReName;
to open a new JDialog ReName.
public class ReName extends javax.swing.JDialog
This JDialog ReName is created to change the name in SQL. After rename successfull, I click on a JButton named btnConfirm
private javax.swing.JButton btnConfirm;
to close this JDialog. After click button Confirm, a JOption appear
like that. I want after click OK, the JDialog ReName is closed, and at the same time, the data on the JInternalFrame account update exactly to what i changed in this JDialog ReName by re-query data from SQL(in other words, i want to update the account by clicking on a Button btnConfirm created on ReName that opened by this JInternalFrame account)
but i dont know how to design it.
Can someone guide me how to create the Button with the function like i was description?
Link to my full-code
The below code does what you want. I did not find a minimal, reproducible example in your question so I guessed that you are using a JTable to display the Player Information. I also only added the Rename button since your question only concerns that button. Here is the code.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
public class GamePlay {
private JFrame frame;
private void createAndShowGui() {
frame = new JFrame("Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JDesktopPane desktop = new JDesktopPane();
Account iFrame = new Account("iFrame");
iFrame.setVisible(true);
desktop.add(iFrame);
frame.setContentPane(desktop);
frame.setSize(600, 580);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> new GamePlay().createAndShowGui());
}
}
class Account extends JInternalFrame implements ActionListener {
private JButton btnReName;
private JTable table;
public Account(String title) {
super(title);
String[] columnNames = {"Ten Nguoi Choi","So Lan Thang","So Lan Choi"};
Object[][] data = {{"Player Name", 1, 7},
{"Nguoi choi 1", 10, 10},
{"Nguoi choi 2", 10, 100},
{"Nguoi choi 3", 0, 10}};
DefaultTableModel model = new DefaultTableModel(data, columnNames);
table = new JTable(model);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane, BorderLayout.CENTER);
btnReName = new JButton("Rename");
btnReName.addActionListener(this);
JPanel panel = new JPanel();
panel.add(btnReName);
add(panel, BorderLayout.LINE_END);
pack();
}
public void actionPerformed(ActionEvent event) {
ReName dlg = new ReName(this);
dlg.setVisible(true);
}
public void changeName(String newName) {
int row = table.getSelectedRow();
if (row >= 0) {
table.setValueAt(newName, row, 0);
}
}
}
class ReName extends JDialog implements ActionListener {
private Account account;
private JButton btnConfirm;
private JButton cancel;
private JPasswordField passwordField;
private JTextField nameTextField;
public ReName(Account acct) {
account = acct;
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
add(createForm(), BorderLayout.CENTER);
add(createButtons(), BorderLayout.PAGE_END);
pack();
setLocationRelativeTo(acct);
}
public void actionPerformed(ActionEvent event) {
JOptionPane.showMessageDialog(this,
"Successful",
"Noitication",
JOptionPane.INFORMATION_MESSAGE);
dispose();
account.changeName(nameTextField.getText());
}
private JPanel createButtons() {
JPanel panel = new JPanel();
btnConfirm = new JButton("Confirm");
btnConfirm.addActionListener(this);
cancel = new JButton("Cancel");
panel.add(cancel);
panel.add(btnConfirm);
return panel;
}
private JPanel createForm() {
JPanel form = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets.bottom = 5;
gbc.insets.left = 5;
gbc.insets.right = 5;
gbc.insets.top = 5;
JLabel nameLabel = new JLabel("Enter new name:");
form.add(nameLabel, gbc);
gbc.gridx = 1;
nameTextField = new JTextField(10);
form.add(nameTextField, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
JLabel passwordLabel = new JLabel("Password:");
form.add(passwordLabel, gbc);
gbc.gridx = 1;
passwordField = new JPasswordField(10);
form.add(passwordField, gbc);
return form;
}
}
When I run the above code, the GUI initially looks as follows (using JDK 11 on Windows 10)
This is a screen capture after selecting the name to change and pressing button Rename.
This is a screen capture after entering the new name and pressing button Confirm.
And finally, a screen capture after pressing button OK. Notice that the first column of the selected row in the JTable has changed to what was entered in the JDialog.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GUI_Borrower extends JFrame implements ActionListener {
JPanel panel = new JPanel();
JLabel lblName = new JLabel("Name:");
JLabel lblProg = new JLabel("Program:");
JLabel lblId = new JLabel("Library ID: ");
JLabel lblTitle = new JLabel("Add Borrower");
JTextField txtName = new JTextField(10);
JTextField txtProg = new JTextField(10);
JTextField txtId = new JTextField(10);
static int counter = 19000;
JButton btnSubmit = new JButton("Submit");
public GUI_Borrower() {
super("Add Borrower");
makeFrame();
showFrame();
}
public void makeFrame() {
lblTitle.setFont(new Font("Forte", Font.PLAIN, 40));
lblTitle.setForeground(Color.BLUE);
add(lblTitle);
add(lblName);
add(txtName);
add(lblProg);
add(txtProg);
add(lblId);
add(txtId);
panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
panel.add(btnSubmit);
btnSubmit.addActionListener(this);
}
public void showFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 200);
setLocationRelativeTo(null);
setVisible(true);
}
public void actionPerformed(ActionEvent ae) {
Object source = ae.getSource();
if (ae.getActionCommand().equals("Confirm")) {
txtName.setText("");
txtProg.setText("");
btnSubmit.setText("Submit");
} else if (source == btnSubmit) {
if (txtName.getText().equals("") && txtProg.getText().equals("")) {
txtId.setText("No entry of both");
} else if (txtName.getText().equals("")) {
txtId.setText("No entry of Name");
} else if (txtProg.getText().equals("")) {
txtId.setText("No entry of Program");
} else {
counter++;
txtId.setText("" + counter);
btnSubmit.setText("Confirm");
}
}
}
public static void main(String[] args) {
new GUI_Borrower();
}
}
I tried adding BoxLayout because all the text fields and labels are on one line. So I tried box Layout and failed.
Can anyone show me how to make it like the title one line, label Different line, button different line?
Like this:
As camickr says in his comment, you generally use a GridBagLayout to create a form.
I reworked your code because I hope to show a better way to code a GUI panel.
Here's the GUI.
The major changes I made include:
All Swing applications must start with a call to the SwingUtilities invokeLater method. This method ensures that all Swing components are created and executed on the Event Dispatch Thread.
I organized the GUI code into three methods so I could focus on one part of the GUI at a time. The JFrame is created in the run method. The title JPanel is created in the createTitlePanel method. The form JPanel is created in the createFormPanel method. The code for the JFrame will rarely change from Swing application to Swing application.
I use Swing components. I don't extend Swing components, or any Java class, unless I intend to override one of the class methods.
The createFormPanel class uses the GridBagLayout to organize the labels and text fields in columns. You can think of the GridBagLayout as a flexible grid. The cells of the grid don't have to be the same size. The Oracle tutorial, How to Use GridBagLayout, has another example.
I put the ActionListener in a separate class. I made it an inner class in this example so I could paste the code as one file. Generally, you should put separate classes in separate files. It makes each class shorter and easier to understand.
Here's the runnable, example code.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class BorrowerGUI implements Runnable {
private static int ID_COUNTER = 19000;
public static void main(String[] args) {
SwingUtilities.invokeLater(new BorrowerGUI());
}
private JButton btnSubmit;
private JTextField txtName;
private JTextField txtProg;
private JTextField txtId;
#Override
public void run() {
JFrame frame = new JFrame("Add Borrower");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTitlePanel(), BorderLayout.BEFORE_FIRST_LINE);
frame.add(createFormPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createTitlePanel() {
JPanel panel = new JPanel(new FlowLayout());
JLabel lblTitle = new JLabel("Add Borrower");
lblTitle.setFont(new Font("Forte", Font.PLAIN, 40));
lblTitle.setForeground(Color.BLUE);
panel.add(lblTitle);
return panel;
}
private JPanel createFormPanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.gridx = 0;
gbc.gridy = 0;
JLabel lblName = new JLabel("Name:");
panel.add(lblName, gbc);
gbc.gridx++;
txtName = new JTextField(20);
panel.add(txtName, gbc);
gbc.gridx = 0;
gbc.gridy++;
JLabel lblProg = new JLabel("Program:");
panel.add(lblProg, gbc);
gbc.gridx++;
txtProg = new JTextField(20);
panel.add(txtProg, gbc);
gbc.gridx = 0;
gbc.gridy++;
JLabel lblId = new JLabel("Library ID:");
panel.add(lblId, gbc);
gbc.gridx++;
txtId = new JTextField(20);
txtId.setEditable(false);
panel.add(txtId, gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.gridwidth = 2;
btnSubmit = new JButton("Submit");
btnSubmit.addActionListener(new SubmitListener());
panel.add(btnSubmit, gbc);
return panel;
}
public class SubmitListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent ae) {
Object source = ae.getSource();
if (ae.getActionCommand().equals("Confirm")) {
txtName.setText("");
txtName.requestFocus();
txtProg.setText("");
txtId.setText("");
btnSubmit.setText("Submit");
} else if (source == btnSubmit) {
if (txtName.getText().equals("") &&
txtProg.getText().equals("")) {
txtId.setText("No entry of both");
} else if (txtName.getText().equals("")) {
txtId.setText("No entry of Name");
} else if (txtProg.getText().equals("")) {
txtId.setText("No entry of Program");
} else {
ID_COUNTER++;
txtId.setText("" + ID_COUNTER);
btnSubmit.setText("Confirm");
}
}
}
}
}
Edited to add: If you want the title JLabel to be right-justified, you'll have to switch to a BorderLayout. I added an empty border so the text wouldn't be on the right edge of the JFrame.
Here's the changed method.
private JPanel createTitlePanel(String title) {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10));
JLabel lblTitle = new JLabel(title);
lblTitle.setFont(new Font("Forte", Font.PLAIN, 40));
lblTitle.setForeground(Color.BLUE);
panel.add(lblTitle, BorderLayout.AFTER_LINE_ENDS);
return panel;
}
This may come off as an odd question, but I would like to make a program that makes a new Jbutton instance in an existing group every time a button(called new) is pressed. It will be added under the previously added button, all buttons must be part of a group(so when one button is pressed it will deselect previously selected button if the button in the group is pressed) and should be able to make an infinite number of buttons given n number of clicks. Here is what I have so far, but honestly I don't even know how to approach this one.
public static void makebuttonpane() {
buttonpane.setLayout(new GridBagLayout());
GridBagConstraints d = new GridBagConstraints();
nbutton = new JButton("New");
d.insets = new Insets(10, 10, 0, 10);
d.anchor = GridBagConstraints.PAGE_START;
buttonpane.add(nbutton,d);
nbutton.addActionListener(new ButtonMaker());
//d.anchor = GridBagConstraints.CENTER;
}
public static void addbutton(JButton button) {
System.out.println("button made");
buttonpane.removeAll();
nbutton = new JButton("New");
d.insets = new Insets(10, 10, 0, 10);
d.anchor = GridBagConstraints.PAGE_START;
buttonpane.add(nbutton,d);
nbutton.addActionListener(new ButtonMaker());
d.gridx=0;
System.out.println(ButtonMaker.getNumb());
d.gridy= ButtonMaker.getNumb();
buttonpane.add(button,d);
frame.setVisible(true);
buttonpane.validate();
}
public static void makebuttonpane() {
buttonpane.setLayout(new GridBagLayout());
GridBagConstraints d = new GridBagConstraints();
nbutton = new JButton("New");
d.insets = new Insets(10, 10, 0, 10);
d.anchor = GridBagConstraints.PAGE_START;
buttonpane.add(nbutton,d);
nbutton.addActionListener(new ButtonMaker());
//d.anchor = GridBagConstraints.CENTER;
}
public static void addbutton(JButton button) {
System.out.println("button made");
buttonpane.removeAll();
nbutton = new JButton("New");
d.insets = new Insets(10, 10, 0, 10);
d.anchor = GridBagConstraints.PAGE_START;
buttonpane.add(nbutton,d);
nbutton.addActionListener(new ButtonMaker());
d.gridx=0;
System.out.println(ButtonMaker.getNumb());
d.gridy= ButtonMaker.getNumb();
buttonpane.add(button,d);
frame.setVisible(true);
buttonpane.validate();
}
class ButtonMaker implements ActionListener{
public static int i=1;
public void actionPerformed(ActionEvent e) {
//System.out.println("I hear you");
//System.out.println(i);
JButton button = new JButton("Button "+i);
MultiListener.addbutton(button);
i++;
}
public static int getNumb() {
return i;
}
}
It adds the first button instance but pressing 'New' only changes that first created button instead of making a new one underneath
I created a GUI that adds a JButton when you click on the "Add Button" button.
Feel free to modify this any way you want.
Mainly, I separated the construction of the JFrame, the construction of the JPanel, and the action listener. Focusing on one part at a time, I was able to code and test this GUI quickly.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class JButtonCreator implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new JButtonCreator());
}
private static int buttonCount = 0;
private JButtonPanel buttonPanel;
#Override
public void run() {
JFrame frame = new JFrame("JButton Creator");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buttonPanel = new JButtonPanel();
JScrollPane scrollPane = new JScrollPane(
buttonPanel.getPanel());
frame.add(scrollPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public class JButtonPanel {
private ButtonGroup buttonGroup;
private JPanel buttonPanel;
private JPanel panel;
public JButtonPanel() {
createPartControl();
}
private void createPartControl() {
panel = new JPanel();
panel.setPreferredSize(new Dimension(640, 480));
panel.setLayout(new BorderLayout());
buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(0, 5));
buttonGroup = new ButtonGroup();
panel.add(buttonPanel, BorderLayout.CENTER);
JButton newButton = new JButton("Add Button");
newButton.addActionListener(new ButtonListener(this));
panel.add(newButton, BorderLayout.AFTER_LAST_LINE);
}
public void addJButton() {
String text = "Button " + ++buttonCount;
JButton button = new JButton(text);
buttonPanel.add(button);
buttonGroup.add(button);
}
public JPanel getPanel() {
return panel;
}
}
public class ButtonListener implements ActionListener {
private JButtonPanel buttonPanel;
public ButtonListener(JButtonPanel buttonPanel) {
this.buttonPanel = buttonPanel;
}
#Override
public void actionPerformed(ActionEvent event) {
buttonPanel.addJButton();
buttonPanel.getPanel().revalidate();;
}
}
}
I have been trying to pass the info of my JTextField that is in a JDialog into my JFrame. Both the JDialog and JFrame are in separate classes. I have tried to store the JTextField into a JLable using the .setText and .getText and then passing the JLable into the JFrame but with no luck.
I know there are many similar questions but I have tried many different approaches but still no luck. I am relatively new to Java and do not know all the in's and out's. Any help is very appreciated!
My code for the JFrame:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JPanel;
public class StockApp extends JFrame implements PropertyChangeListener {
private JPanel main = new JPanel();
private JPanel north = new JPanel();
private JPanel center = new JPanel();
private JPanel south = new JPanel();
private JButton buyStock = new JButton("Buy Stock");
private JButton sellStock = new JButton("Sell Stock");
public TestTest variables = new TestTest();
private JLabel stockNameNorth = new JLabel("Stock Name");
private JLabel stockPriceNorth = new JLabel("Stock Price");
String stockName = variables.getStockName();
String stockPrice = variables.getStockPrice();
public StockApp() {
setTitle("StockApp");
getContentPane().setBackground(Color.white);
setSize(400,400);
setLocation(500,200);
setVisible(true);
main.setLayout(new BorderLayout());
north.setLayout(new FlowLayout());
center.setLayout(new FlowLayout());
south.setLayout(new FlowLayout());
stockNameNorth.setText(stockName);
stockPriceNorth.setText(stockPrice);
add(main);
north.add(stockNameNorth);
north.add(stockPriceNorth);
south.add(buyStock);
south.add(sellStock);
main.add(north, BorderLayout.NORTH);
main.add(center, BorderLayout.CENTER);
main.add(south, BorderLayout.SOUTH);
}
}
And Dialog:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TestTest extends JDialog implements ActionListener {
private JPanel main = new JPanel();
private JPanel north = new JPanel();
private JPanel center = new JPanel();
private JPanel south = new JPanel();
private JLabel stockNameLabel = new JLabel("Stock name: ");
private JLabel stockPriceLabel = new JLabel("Stock price(£): ");
private JTextField stockNameIn = new JTextField(5);
private JTextField stockPriceIn = new JTextField(5);
private JButton buttonOK = new JButton("OK");
public JLabel stockPrice = new JLabel();
public JLabel stockName = new JLabel();
public TestTest() {
getContentPane().setBackground(Color.white);
setSize(400,400);
setLocation(500,200);
setModal(false);
setVisible(true);
getRootPane().setDefaultButton(buttonOK);
main.setLayout(new BorderLayout());
north.setLayout(new FlowLayout());
center.setLayout(new FlowLayout());
south.setLayout(new FlowLayout());
add(main);
north.add(stockNameLabel);
north.add(stockNameIn);
center.add(stockPriceLabel);
center.add(stockPriceIn);
south.add(buttonOK);
main.add(north, BorderLayout.NORTH);
main.add(center, BorderLayout.CENTER);
main.add(south, BorderLayout.SOUTH);
buttonOK.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == buttonOK){
stockName.setText(stockNameIn.getText());
stockPrice.setText(stockPriceIn.getText());
dispose();
new StockApp();
}
}
public String getStockName() {
return stockNameIn.getText();
}
public String getStockPrice() {
return stockPriceIn.getText();
}
}
I am trying to pass the stockName and stockPrice variables from the JDialog into the JFrame. I then want the name and price to display at the top of the JFrame.
For demonstration, what the problem is, we need less Fields and Buttons.
So far, no component of StockApp needs to be accessed from different methods, so there is no need to make them visible outside of the ctor.
More explanations in the code.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
public class StockApp extends JFrame {
public StockApp() {
// move those unreferenced panels here, so we don't have to reason about them:
JPanel main = new JPanel();
JPanel north = new JPanel();
JPanel center = new JPanel();
JPanel south = new JPanel();
// add price later, when name works
JButton buyStock = new JButton("Buy Stock");
JLabel stockNameNorth = new JLabel("Stock Name");
// critical change: Make the label, which you like to update,
// accessible by whom it should be updated:
TestTest variables = new TestTest (stockNameNorth);
setTitle ("StockApp");
getContentPane().setBackground(Color.white);
setSize (600,400);
setLocation (500,200);
setVisible (true);
// make the close-frame action terminate the program:
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
main.setLayout (new BorderLayout());
north.setLayout (new FlowLayout());
center.setLayout (new FlowLayout());
south.setLayout (new FlowLayout());
add (main);
north.add (stockNameNorth);
south.add (buyStock);
main.add (north, BorderLayout.NORTH);
main.add (center, BorderLayout.CENTER);
main.add (south, BorderLayout.SOUTH);
}
// Main method to start the damn thing
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new StockApp ();
}
});
}
}
// no need to make this class public in a short test:
class TestTest extends JDialog implements ActionListener {
// this are elements, visible outside the construction phase,
// we need to have access to from more than one method.
// Make this important distinction visible to the reader:
JLabel name;
JTextField stockNameIn = new JTextField (5);
JButton buttonOK = new JButton ("OK");
// add the JLabel to update to the ctor, so that it can't be forgotten
// to be set
public TestTest (JLabel pname) {
// we copy the reference to the label, to have access to it in
// the actionPerformed method.
name = pname;
JPanel main = new JPanel();
JPanel north = new JPanel();
JPanel center = new JPanel();
JPanel south = new JPanel();
JLabel stockNameLabel = new JLabel ("Stock name: ");
getContentPane().setBackground(Color.white);
// different size/location than frame, so that they don't hide
// each other completly
setSize (400,600);
setLocation (700,300);
setModal (false);
setVisible (true);
getRootPane().setDefaultButton(buttonOK);
main.setLayout (new BorderLayout());
north.setLayout (new FlowLayout());
center.setLayout (new FlowLayout());
south.setLayout (new FlowLayout());
add (main);
north.add (stockNameLabel);
north.add (stockNameIn);
south.add (buttonOK);
main.add (north, BorderLayout.NORTH);
main.add (center, BorderLayout.CENTER);
main.add (south, BorderLayout.SOUTH);
buttonOK.addActionListener(this);
}
// here we need access to the button - was it the OK-Button, clicked?
// and the textfield stockNameIn, to read the text
// and the name field from the frame, to set the text
public void actionPerformed(ActionEvent e) {
if (e.getSource () == buttonOK) {
name.setText (stockNameIn.getText());
dispose();
}
}
}
Whenever I press "clear" in my Java GUI, it never works, please help me finish this. If i replace "textPanel" with another button, it works, otherwise with "textpanel" it doesn't.
Here is a lightweight version of my code demonstrating the problem:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MainFrame extends JFrame {
private TextPanel textPanel;
private FormPanel formpanel;
public MainFrame(){
super("My Frame");
createLayout();
createFrame();
}
public void createFrame(){
setSize(600, 600);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public void createLayout(){
BorderLayout myLayout = new BorderLayout();
setLayout(myLayout);
textPanel = new TextPanel();
formpanel = new FormPanel();
// adding components
add(textPanel, BorderLayout.CENTER);
add(formpanel, BorderLayout.WEST);
}
public static void main(String[] args){
new MainFrame();
}
public static class FormPanel extends JPanel {
private JButton clear;
private TextPanel textPanel;
public FormPanel(){
clear = new JButton("Clear Cart!");
textPanel=new TextPanel();
add(clear);
clear.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent aev){
System.out.println("Test");
textPanel.setText("");
}
});
createGrid();
}
/* this methods simply creates the layout */
void createGrid(){
//creating layout
setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
gc.gridy++;
gc.weightx = .1;
gc.weighty = .1;
gc.gridx = 2;
gc.gridy=5;
gc.anchor = GridBagConstraints.LINE_START;
gc.insets = new Insets(0,0,0,0);
add(clear, gc);
}
}
public static class TextPanel extends JPanel {
private JTextArea textArea;
TextPanel (){
textArea = new JTextArea();
setLayout(new BorderLayout());
JScrollPane p = new JScrollPane(textArea);
add(p, BorderLayout.CENTER);
}
public void appendSomeText(String t){
textArea.append(t);
}
public void setText(String s){
textArea.setText(s);
}
}
}
You have two instances of TextPanel, one in MainFrame and the other one in FormPanel. TextPanel that is defined in FormPanel is actually not added to the panel, so textPanel.setText(""); has no effect on it as it is not visible.
When the text appended with Add To Cart! button it actually goes through a method in MainFrame - formEventOccurred() that executes textPanel.appendSomeText(). This is the other instance of TextPanel that is part of MainFrame and that is actually visible.
Looks like you need to move the duplicated logic from the main frame to the panels. Usually you should not extend JFrame as you are not adding any new functionality.