Trying to do a JTable which adds data from a JTextField - java

I'm trying to do code that adds a row to a JTable. I type but nothing shows up. My showMessageDialog also has an error.
Does anyone know how I can rewrite the code?
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import static javax.swing.JOptionPane.showMessageDialog;
public class JTABEL extends Component {
private JPanel panel1;
private JLabel Name;
private JLabel Age;
private JLabel Class;
private JTextField enterNameTextField;
private JTextField Agefield;
private JTextField EnterClassField;
private JTable Table;
private JButton saveButton;
public JTABEL() {
saveButton.addActionListener(this::actionPerformed);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Jtable");
frame.setContentPane(new JTABEL().panel1);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private void actionPerformed(ActionEvent e) {
if (enterNameTextField.getText().equals("") || Agefield.getText().equals("") ||
EnterClassField.getText().equals("")) {
showMessageDialog(this, "please Enter all Data");
} else {
String data[] = {enterNameTextField.getText(), Agefield.getText(),
EnterClassField.getText()};
DefaultTableModel tableModel = (DefaultTableModel) Table.getModel();
tableModel.addRow(new Object[]{enterNameTextField.getText(), Agefield.getText(),
EnterClassField.getText()});
showMessageDialog(this, "Add Data Successfully");
enterNameTextField.setText("");
Agefield.setText("");
EnterClassField.setText("");
}
}
}

Introduction
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section.
I created the following GUI.
Here's the same GUI after adding a couple of students.
Explanation
The model–view–controller (MVC) pattern is useful when creating a Swing application. The name implies that you create the model first, then the view, then the controller.
An application model is made up of one or more plain Java getter/setter classes.
A Swing view is one JFrame with one or more JPanels. The view displays the contents of the model. The view does not modify the model.
Each Swing ActionListener is a controller. The controllers update the model.
Model
I created two model classes. The Student class holds a name, age, and class.
The JTableModel class holds the DefaultTableModel for the JTable.
View
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 created a JFrame and two JPanels. One JPanel holds the JTable and the other JPanel holds the add student form. The JFrame has a default BorderLayout. I placed the table JPanel in the center and the form JPanel on the east side.
The table JPanel uses a BorderLayout. The JTable is placed inside of a JScrollPane. The JScrollPane is placed inside of the table JPanel in the center.
The form JPanel uses a GridBagLayout to create a form structure JPanel.
Complete explanations of all the Swing layout managers can be found in the Oracle tutorial.
Controller
The anonymous JButton ActionListener checks to see if the fields have been typed. If so, a Student instance is created and passed to the application model. If not, an error display pops up.
Code
Here's the complete runnable code. I made the additional classes inner classes so I could post the code as one block.
import java.awt.BorderLayout;
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.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
public class JTableExample implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new JTableExample());
}
private final JTableModel model;
private JFrame frame;
private JTextField nameField, ageField, classField;
public JTableExample() {
this.model = new JTableModel();
}
#Override
public void run() {
frame = new JFrame("JTable Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTablePanel(), BorderLayout.CENTER);
frame.add(createAddPanel(), BorderLayout.EAST);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createTablePanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JTable table = new JTable(model.getTableModel());
JScrollPane scrollPane = new JScrollPane(table);
panel.add(scrollPane, BorderLayout.CENTER);
return panel;
}
private JPanel createAddPanel() {
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(0, 5, 5, 5);
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 0;
JLabel label = new JLabel("Name:");
panel.add(label, gbc);
gbc.gridx++;
nameField = new JTextField(20);
panel.add(nameField, gbc);
gbc.gridx = 0;
gbc.gridy++;
label = new JLabel("Age:");
panel.add(label, gbc);
gbc.gridx++;
ageField = new JTextField(20);
panel.add(ageField, gbc);
gbc.gridx = 0;
gbc.gridy++;
label = new JLabel("Class:");
panel.add(label, gbc);
gbc.gridx++;
classField = new JTextField(20);
panel.add(classField, gbc);
gbc.gridwidth = 2;
gbc.gridx = 0;
gbc.gridy++;
JButton button = new JButton("Add Student");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
String name = nameField.getText().trim();
String ageString = ageField.getText().trim();
String level = classField.getText().trim();
if (name.isEmpty() || ageString.isEmpty() || level.isEmpty()) {
JOptionPane.showMessageDialog(
frame, "Please enter all information");
return;
}
int age = getAge(ageString);
if (age > 0) {
model.addStudent(new Student(name, age, level));
clearInputFields();
}
}
private int getAge(String ageString) {
int age = -1;
try {
age = Integer.valueOf(ageString);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(
frame, "Please enter a numeric age");
}
return age;
}
private void clearInputFields() {
nameField.setText("");
ageField.setText("");
classField.setText("");
nameField.requestFocus();
}
});
panel.add(button, gbc);
frame.getRootPane().setDefaultButton(button);
return panel;
}
public class JTableModel {
private final DefaultTableModel tableModel;
public JTableModel() {
this.tableModel = new DefaultTableModel();
tableModel.addColumn("Name");
tableModel.addColumn("Age");
tableModel.addColumn("Class");
}
public void addStudent(Student student) {
Object[] rowData = new Object[3];
rowData[0] = student.getName();
rowData[1] = student.getAge();
rowData[2] = student.getLevel();
tableModel.addRow(rowData);
}
public DefaultTableModel getTableModel() {
return tableModel;
}
}
public class Student {
private final int age;
private final String level, name;
public Student(String name, int age, String level) {
this.name = name;
this.age = age;
this.level = level;
}
public int getAge() {
return age;
}
public String getLevel() {
return level;
}
public String getName() {
return name;
}
}
}

Related

ActionListener, List Issue

I am running into an issue with my program. The objective is to collect input (movie name, media type and the year) and append it to a list when "add movie" is clicked. Then when the "show movies" button is clicked the list will display in the text area. I'm not sure what I am missing or what I've done wrong.
import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
class MovieDatabase extends JFrame implements ActionListener{
//create LinkedList of Movie Objects
LinkedList<Movie> list = new LinkedList<Movie>();
//JPanel for input movie
private JPanel inputJPanel;
//JLable and JTextField for Movie Name
private JLabel movieJLabel;
private JTextField movieJTextField;
//JLable and JTextField for Media
private JLabel mediaJLabel;
private JTextField mediaJTextField;
//JLable and JTextField for Release Year
private JLabel yearJLabel;
private JTextField yearJTextField;
//JButton to add movie to a list
private JButton addJButton;
//JButton to show movie in text area
private JLabel showJLabel;
private JButton showJButton;
//JTextArea to display movies from list
private JTextArea showJTextArea;
private JPanel listJPanel;
//no argument constructor
public MovieDatabase(){
createUserInterface();
}
//create GUI window with components
private void createUserInterface(){
//get content pane window and set layout to null - no layout manager
Container contentPane = getContentPane();
contentPane.setLayout(null);
//set up input panel
inputJPanel = new JPanel();
inputJPanel.setLayout(null);
inputJPanel.setBorder(new TitledBorder("Input Movie")); //anonymous object
inputJPanel.setBounds(20,4,260,178);// (x,y,w,h)
contentPane.add(inputJPanel);
//set up input panel
showJLabel = new JLabel();
showJLabel.setLayout(null);
showJLabel.setText("Movies: ");
showJLabel.setBounds(300,0,260,25);// (x,y,w,h)
contentPane.add(showJLabel);
//set up payment JTextArea here
showJTextArea = new JTextArea();
showJTextArea.setBounds(300,30,300,145);// (x,y,w,h)
showJTextArea.setEditable(false);
contentPane.add(showJTextArea);
//show movies JButton
showJButton = new JButton();
showJButton.setBounds(480,175,110,30);
showJButton.setText("Show Movies");
contentPane.add(showJButton);
//movie name JLabel
movieJLabel = new JLabel();
movieJLabel.setBounds(10,24,100,21);// (x,y,w,h)
movieJLabel.setText("Movie Name:");
inputJPanel.add(movieJLabel);
//movie name JTextField
movieJTextField = new JTextField();
movieJTextField.setBounds(104,24,120,21);
movieJTextField.setHorizontalAlignment(JTextField.RIGHT);
inputJPanel.add(movieJTextField);
//media name JLabel
mediaJLabel = new JLabel();
mediaJLabel.setBounds(10,54,100,21);// (x,y,w,h)
mediaJLabel.setText("Media:");
inputJPanel.add(mediaJLabel);
//media name JTextField
mediaJTextField = new JTextField();
mediaJTextField.setBounds(104,54,120,21);
mediaJTextField.setHorizontalAlignment(JTextField.RIGHT);
inputJPanel.add(mediaJTextField);
//year name JLabel
yearJLabel = new JLabel();
yearJLabel.setBounds(10,84,100,21);// (x,y,w,h)
yearJLabel.setText("Release Year:");
inputJPanel.add(yearJLabel);
//year name JTextField
yearJTextField = new JTextField();
yearJTextField.setBounds(104,84,80,21);
yearJTextField.setHorizontalAlignment(JTextField.RIGHT);
inputJPanel.add(yearJTextField);
//add movie JButton
addJButton = new JButton();
addJButton.setBounds(92,138,94,24);
addJButton.setText("Add Movie");
inputJPanel.add(addJButton);
//set window properties
setTitle("Movie"); //set title bar
setSize(625, 250);//window size
setVisible(true); //display window
addJButton.addActionListener(this);
showJButton.addActionListener(this);
}
public void addButtonactionPerformed(ActionEvent e){
String movieName = movieJTextField.getText();
String media = mediaJTextField.getText();
int year = Integer.parseInt(yearJTextField.getText());
//create instance of Movie
Movie movie = new Movie(movieName, media, year);
list.add(movie);
movieJTextField.setText("");
mediaJTextField.setText("");
yearJTextField.setText("");
}
private void showButtonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
showJTextArea.setText("");
String str = String.format("%-20s%-20s%-20s\n", "Year", "Media", "Title");
showJTextArea.append(str);
for (Movie movie : list) {
str = String.format("%-20s%-19s%-22s\n", Integer.toString(movie.year), movie.media, movie.name);
showJTextArea.append(str);
}
}
}
class Movie{
String name;
String media;
int year;
public Movie(String n, String m, int y){
name = n;
media = m;
year = y;
}
public class MovieGUI {
public static void main(String[] args) {
MovieDatabase application = new MovieDatabase();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}//close and stop application
}
}
null layouts are going to come back to haunt you. There is no such thing as "pixel perfect" layouts, there are just to many variables associated with the differences in the way things get rendered between different hardware and OSs to even consider making this choice.
Take the time to learn how to use the layout managers Laying Out Components Within a Container
You've not implemented the requirements for ActionListener (showButtonActionPerformed suggests that you're using something like Netbeans form editor).
Maybe you should take a look at How to Write an Action Listener and How to Use Buttons, Check Boxes, and Radio Buttons
You might also want to look at How to Use Tables
To my mind, you need to take a slightly different tact and focus on separating the areas of responsibility. Collecting the movie information has nothing with either storing the results or displaying them, so I'd have those separated into it's own container, so you can more easily manage it.
This leads to the question of, "how do you notify interested parties when a user 'adds' a movie?". Interestingly, you're somewhat already familiar with the concept.
Essentially, you use a "listener" or, as it's more commonly known, an "observer pattern". This allows you to notify interested parties that something has happened, in this case, a user has created a new movie.
For example...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.EventListener;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new MovieManagerPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Movie {
String name;
String media;
int year;
public Movie(String n, String m, int y) {
name = n;
media = m;
year = y;
}
public String getName() {
return name;
}
public String getMedia() {
return media;
}
public int getYear() {
return year;
}
}
public class MovieManagerPane extends JPanel {
private JTextArea moviesTextArea;
private List<Movie> movies = new ArrayList<>(32);
public MovieManagerPane() {
setLayout(new BorderLayout());
moviesTextArea = new JTextArea(20, 40);
String str = String.format("%-20s%-20s%-20s\n", "Year", "Media", "Title");
moviesTextArea.append(str);
MoviePane moviePane = new MoviePane();
moviePane.setBorder(new CompoundBorder(new TitledBorder("Input Movie"), new EmptyBorder(4, 4, 4, 4)));
moviePane.addMovieListener(new MoviePane.MovieListener() {
#Override
public void movieWasAdded(MoviePane source, Movie movie) {
movies.add(movie);
String str = String.format("%-20s%-20s%-20s\n", movie.getYear(), movie.getMedia(), movie.getName());
moviesTextArea.append(str);
}
});
add(moviePane, BorderLayout.LINE_START);
add(moviesTextArea);
}
}
public class MoviePane extends JPanel {
public static interface MovieListener extends EventListener {
public void movieWasAdded(MoviePane source, Movie movie);
}
//JLable and JTextField for Movie Name
private JLabel movieJLabel;
private JTextField movieJTextField;
//JLable and JTextField for Media
private JLabel mediaJLabel;
private JTextField mediaJTextField;
//JLable and JTextField for Release Year
private JLabel yearJLabel;
private JTextField yearJTextField;
//JButton to add movie to a list
private JButton addJButton;
public MoviePane() {
setLayout(new GridBagLayout());
movieJLabel = new JLabel("Movie Name:");
mediaJLabel = new JLabel("Media:");
yearJLabel = new JLabel("Release Year:");
movieJTextField = new JTextField(10);
mediaJTextField = new JTextField(10);
yearJTextField = new JTextField(10);
addJButton = new JButton("Add Movie");
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = gbc.EAST;
gbc.insets = new Insets(4, 4, 4, 4);
add(movieJLabel, gbc);
gbc.gridy++;
add(mediaJLabel, gbc);
gbc.gridy++;
add(yearJLabel, gbc);
gbc.gridx++;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = gbc.WEST;
add(movieJTextField, gbc);
gbc.gridy++;
add(mediaJTextField, gbc);
gbc.gridy++;
add(yearJTextField, gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.gridwidth = 2;
gbc.fill = GridBagConstraints.NONE;
gbc.weighty = 1;
gbc.anchor = gbc.SOUTH;
add(addJButton, gbc);
addJButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
// Use a JSpinner or JFornattedTextField to avoid this
int year = Integer.parseInt(yearJTextField.getText());
Movie movie = new Movie(movieJTextField.getText(), mediaJTextField.getText(), year);
fireMovieWasAdded(movie);
} catch (NumberFormatException exp) {
JOptionPane.showMessageDialog(MoviePane.this, "Invalid year", "Error", JOptionPane.ERROR_MESSAGE);
}
}
});
}
public void addMovieListener(MovieListener listener) {
listenerList.add(MovieListener.class, listener);
}
public void removeMovieListener(MovieListener listener) {
listenerList.remove(MovieListener.class, listener);
}
protected void fireMovieWasAdded(Movie movie) {
MovieListener[] listeners = listenerList.getListeners(MovieListener.class);
if (listeners.length == 0) {
return;
}
for (MovieListener listener : listeners) {
listener.movieWasAdded(this, movie);
}
}
}
}
You may also want to take a look at How to Use Spinners and How to Use Formatted Text Fields for dealing with "non-string" input

Input number in one Frame/Class/Window in a JTextField and show it in a JLabel in another

I am currently working on my own small project in Java to learn and better understand Object Oriented Programming.
It is a Banking Application that allows you to deposit and withdraw money and check your balance, but I think my code is all over the place.
I can't get the value of the TextField from one frame to a Label in another frame. How do I even link two JFrames together?
This is the Balance Class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Balance implements ActionListener {
JFrame balanceFrame = new JFrame("Balance");
JPanel balancePanel = new JPanel();
JLabel balanceLabel = new JLabel("Balance:");
JLabel refreshBalanceLabel = new JLabel();
JButton exitBalanceButton = new JButton("EXIT");
JButton backToMenuButton = new JButton("MENU");
JButton refreshButton = new JButton("REFRESH");
public void balance(){
balanceFrame.setSize(420, 400);
balanceFrame.add(balancePanel);
balancePanel.setLayout(null);
balanceFrame.setVisible(true);
balanceFrame.setDefaultCloseOperation(balanceFrame.EXIT_ON_CLOSE);
balanceLabel.setFont(new Font("Segoe UI", Font.PLAIN, 14));
balanceLabel.setBounds(10,50,80,25);
balancePanel.add(balanceLabel);
refreshBalanceLabel.setFont(new Font("Segoe UI", Font.PLAIN, 14));
refreshBalanceLabel.setBounds(80,50,80,25);
balancePanel.add(refreshBalanceLabel);
refreshButton.setBounds(100,220,100,25);
refreshButton.setFocusPainted(false);
balancePanel.add(refreshButton);
refreshButton.addActionListener(this);
exitBalanceButton.setBounds(100,160,100,25);
exitBalanceButton.setFocusPainted(false);
balancePanel.add(exitBalanceButton);
backToMenuButton.setBounds(240,160,100,25);
backToMenuButton.setFocusPainted(false);
balancePanel.add(backToMenuButton);
}
#Override
public void actionPerformed(ActionEvent e) {
Deposit depositObj = new Deposit();
refreshBalanceLabel.setText(depositObj.newBalanceAmount);
}
}
This is the Deposit Class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Deposit implements ActionListener {
String newBalanceAmount;
JFrame depositFrame = new JFrame("Deposit");
JPanel depositPanel = new JPanel();
JLabel amount = new JLabel("Amount:");
JTextField amountTextField = new JTextField();
JButton depositAmountButton = new JButton("DEPOSIT");
public void depositing() {
depositFrame.setSize(420, 400);
depositFrame.add(depositPanel);
depositPanel.setLayout(null);
depositFrame.setVisible(true);
depositFrame.setDefaultCloseOperation(depositFrame.EXIT_ON_CLOSE);
amount.setFont(new Font("Segoe UI", Font.PLAIN, 14));
amount.setBounds(10, 50, 80, 25);
depositPanel.add(amount);
amountTextField.setBounds(100, 50, 165, 25);
depositPanel.add(amountTextField);
depositAmountButton.setBounds(130, 160, 100, 25);
depositAmountButton.setFocusPainted(false);
depositPanel.add(depositAmountButton);
depositAmountButton.addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
String newBalanceAmount = amountTextField.getText();
Balance newBalance = new Balance();
amountTextField.setText(newBalanceAmount);
}
}
There are other classes and frames but they are not relevant to my problem right now.
Most of the code here is mine and some is from the internet so it all cramped together and it just doesn't work and I'm stuck.
I know the basics of java and am currently doing well on OOP but this one I don't understand yet.
How can I copy the input of the TextField(amountTextField) from the Deposit class into the (refreshBalanceLabel) in the Balance class?
Also, what's wrong with my code and how can I improve it overall?
Introduction
Let's see. I copied your Deposit class into my GUI. It wouldn't compile. I fixed the compilation errors and added a static main method so I could run it and see what your GUI looks like. It was a mess. Why did you make the GUI a fixed size? Why did you use absolute positioning for the Swing components. Why in the world do you need three buttons for a deposit?
Here's one way you could create a single JFrame GUI that combines the deposit function and the withdrawal function.
When you create a Swing GUI, you should try and make it as small as possible. The user can stretch the JFrame if he wants it to be bigger.
In order to create a GUI that looks like this, you have to understand how to layout a Swing GUI. Because this GUI looks like a form, I used a GridBagLayout to construct this GUI. I did not use absolute positioning.
I created an application model that holds account information and transaction information. The Account class holds a name, account number, and balance. The Transaction class holds a check number (optional), date, payee, and amount.
Once I had the application model, the Swing components that make up the GUI were straightforward. I used one JPanel to hold all these components. I added the components to my JPanel one by one, running a test after adding each component. Not every test was successful. Since I only added one component at a time, I generally knew where the error was.
As I said in my comment, go through the Oracle tutorial, Creating a GUI With JFC/Swing. Skip the Netbeans section. Learn how to construct a proper Swing GUI.
Edited to add
I created a somewhat complete checkbook GUI. The left JTable contains a register of all the transactions. The right is the control JPanel that allows me to add transactions.
I didn't do any error checking. The date must be input in a M/d/yy format.
As you can see, the balance is updated after each deposit or withdrawal transaction is entered.
The GUI is rather wide at 1309 x 525 pixels. Maybe the register should be displayed in a JDialog, but I like the instant feedback of seeing the transaction appear in the JTable.
Explanation
When I create a Swing GUI, I use the model / view / controller (MVC) pattern. This pattern allows me to separate my concerns and focus on one part of the application at a time.
I created 3 model classes, one view class, and 4 controller classes. Two of the controller classes deal with the JTable display, and the other two controller classes are the ActionListener classes for the deposit and withdrawal JButtons.
Model
The Checkbook class is the main plain Java getter / setter class that holds an instance of Account and a java.util.List of Transaction instances.
The Account class is a plain Java getter / setter class that holds an account name, account number, and account balance. The account balance is an int field that holds pennies. This ensures that adding deposits and deducting withdrawals don't cause any floating-point rounding errors.
The Transaction class is a plain Java getter / setter class that holds a check number, transaction date, payee, description, and amount. The amount is stored as a double since we don't do any arithmetic with a transaction.
I hope you're noticing a trend here. All application model classes are plain Java getter / setter classes. The view will deal with the Swing components.
View
The view consists of one JFrame, a table JPanel, and a control JPanel. The JFrame has a default BorderLayout, so I put the table JPanel in the center and the control JPanel on the right. If you expand the JFrame, all the extra space goes to the table JPanel.
The table JPanel holds a JScrollPane, which holds a JTable. The table JPanel uses a BorderLayout. I created a table model and a cell renderer for the JTable. These classes improve the visual appearance of the JTable and allow me to sort the table columns by the underlying class. As an example, the amount columns are Double values but displayed as comma-separated String values.
The control JPanel holds all of the entry fields for a deposit and a withdrawal transaction. I used the GridBagLayout to place the Swing components. There are quite a few Swing components on this JPanel. Perhaps, I should have made the control JPanel a separate class.
Controller
I'm not going to discuss the JTable controllers. This answer is already quite long.
I created two separate ActionListener classes, one for a deposit and one for a withdrawal. I didn't do any error checking. By writing separate ActionListener classes, each class remained straightforward and simple.
Epilog
It took me a few hours to create this GUI. I coded it one small piece at a time and tested each small piece many times. I found a couple of errors in the code as I was writing this answer.
Here's the complete runnable code. I made all the classes inner classes so I could post this as one block. Copy the code and run it in your IDE to see how it works.
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
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 java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
public class CheckbookGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new CheckbookGUI());
}
private final Checkbook checkbook;
private CheckbookTableModel tableModel;
private JFrame frame;
private JTable transactionTable;
private JTextField balanceField;
private JTextField depositDateField;
private JTextField depositAmountField;
private JTextField withdrawalCheckNumberField;
private JTextField withdrawalDateField;
private JTextField withdrawalPayeeField;
private JTextField withdrawalDescriptionField;
private JTextField withdrawalAmountField;
public CheckbookGUI() {
this.checkbook = new Checkbook();
}
#Override
public void run() {
frame = new JFrame("Checkbook GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTablePanel(), BorderLayout.CENTER);
frame.add(createTransactionPanel(), BorderLayout.AFTER_LINE_ENDS);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
System.out.println(frame.getSize());
}
private JPanel createTablePanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
String[] headers = { "Check #", "Date", "Payee", "Description",
"Deposit", "Withdrawal"};
tableModel = new CheckbookTableModel();
for (int index = 0; index < headers.length; index++) {
tableModel.addColumn(headers[index]);
}
for (int index = 0; index < checkbook.getTransactions().size(); index++) {
Transaction transaction = checkbook.getTransactions().get(index);
updateTableModel(transaction);
}
transactionTable = new JTable(tableModel);
transactionTable.setAutoCreateRowSorter(true);
int[] width = { 75, 100, 250, 250, 75, 75 };
int totalWidth = 0;
CheckbookCellRenderer cellRenderer = new CheckbookCellRenderer();
TableColumnModel columnModel = transactionTable.getColumnModel();
for (int index = 0; index < headers.length; index++) {
columnModel.getColumn(index).setCellRenderer(cellRenderer);
columnModel.getColumn(index).setPreferredWidth(width[index]);
totalWidth += width[index];
}
JScrollPane scrollPane = new JScrollPane(transactionTable);
panel.add(scrollPane, BorderLayout.CENTER);
Dimension d = panel.getPreferredSize();
d.width = totalWidth + 50;
panel.setPreferredSize(d);
return panel;
}
public void updateTableModel(Transaction transaction) {
Object[] object = new Object[6];
object[0] = transaction.getCheckNumber();
object[1] = transaction.getTransactionDate();
object[2] = transaction.getPayee();
object[3] = transaction.getDescription();
double amount = transaction.getAmount();
if (amount > 0.0) {
object[4] = transaction.getAmount();
object[5] = 0.0;
} else {
object[4] = 0.0;
object[5] = -transaction.getAmount();
}
tableModel.addRow(object);
}
private JPanel createTransactionPanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
Font titleFont = new Font("Segoe UI", Font.PLAIN, 24);
Font font = new Font("Segoe UI", Font.PLAIN, 14);
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.gridwidth = 1;
gbc.weightx = 1.0;
gbc.gridx = 0;
gbc.gridy = 0;
JLabel nameLabel = new JLabel(checkbook.getAccount().getAccountName());
nameLabel.setFont(titleFont);
panel.add(nameLabel, gbc);
gbc.gridx++;
JLabel accountNumberLabel = new JLabel(
checkbook.getAccount().getAccountNumber());
accountNumberLabel.setFont(titleFont);
accountNumberLabel.setHorizontalAlignment(JLabel.TRAILING);
panel.add(accountNumberLabel, gbc);
gbc.gridx = 0;
gbc.gridy++;
JLabel label = new JLabel("Balance:");
label.setFont(font);
panel.add(label, gbc);
gbc.gridx++;
balanceField = new JTextField(20);
balanceField.setEditable(false);
balanceField.setFont(font);
balanceField.setHorizontalAlignment(JTextField.TRAILING);
balanceField.setText(String.format("%,.2f",
checkbook.getAccount().getBalance()));
panel.add(balanceField, gbc);
gbc.gridx = 0;
gbc.gridy++;
label = new JLabel("Deposit");
label.setFont(titleFont);
panel.add(label, gbc);
gbc.gridx = 0;
gbc.gridy++;
label = new JLabel("Date:");
label.setFont(font);
panel.add(label, gbc);
gbc.gridx++;
depositDateField = new JTextField(20);
depositDateField.setFont(font);
panel.add(depositDateField, gbc);
gbc.gridx = 0;
gbc.gridy++;
label = new JLabel("Amount:");
label.setFont(font);
panel.add(label, gbc);
gbc.gridx++;
depositAmountField = new JTextField(20);
depositAmountField.setFont(font);
depositAmountField.setHorizontalAlignment(JTextField.TRAILING);
panel.add(depositAmountField, gbc);
gbc.gridwidth = 2;
gbc.gridx = 0;
gbc.gridy++;
JButton button = new JButton("Deposit");
button.addActionListener(new DepositListener(this, checkbook));
button.setFont(font);
panel.add(button, gbc);
gbc.gridx = 0;
gbc.gridy++;
label = new JLabel("Withdrawl");
label.setFont(titleFont);
panel.add(label, gbc);
gbc.gridx = 0;
gbc.gridy++;
label = new JLabel("Check Number:");
label.setFont(font);
panel.add(label, gbc);
gbc.gridx++;
withdrawalCheckNumberField = new JTextField(20);
withdrawalCheckNumberField.setFont(font);
withdrawalCheckNumberField.setHorizontalAlignment(JTextField.TRAILING);
panel.add(withdrawalCheckNumberField, gbc);
gbc.gridx = 0;
gbc.gridy++;
label = new JLabel("Date:");
label.setFont(font);
panel.add(label, gbc);
gbc.gridx++;
withdrawalDateField = new JTextField(20);
withdrawalDateField.setFont(font);
panel.add(withdrawalDateField, gbc);
gbc.gridx = 0;
gbc.gridy++;
label = new JLabel("Payee:");
label.setFont(font);
panel.add(label, gbc);
gbc.gridx++;
withdrawalPayeeField = new JTextField(20);
withdrawalPayeeField.setFont(font);
panel.add(withdrawalPayeeField, gbc);
gbc.gridx = 0;
gbc.gridy++;
label = new JLabel("Description:");
label.setFont(font);
panel.add(label, gbc);
gbc.gridx++;
withdrawalDescriptionField = new JTextField(20);
withdrawalDescriptionField.setFont(font);
panel.add(withdrawalDescriptionField, gbc);
gbc.gridx = 0;
gbc.gridy++;
label = new JLabel("Amount:");
label.setFont(font);
panel.add(label, gbc);
gbc.gridx++;
withdrawalAmountField = new JTextField(20);
withdrawalAmountField.setFont(font);
withdrawalAmountField.setHorizontalAlignment(JTextField.TRAILING);
panel.add(withdrawalAmountField, gbc);
gbc.gridwidth = 2;
gbc.gridx = 0;
gbc.gridy++;
button = new JButton("Withdrawal");
button.addActionListener(new WithdrawalListener(this, checkbook));
button.setFont(font);
panel.add(button, gbc);
return panel;
}
public void pack() {
frame.pack();
}
public void updateBalanceField() {
this.balanceField.setText(String.format("%,.2f",
checkbook.getAccount().getBalance()));
}
public JTextField getDepositDateField() {
return depositDateField;
}
public JTextField getDepositAmountField() {
return depositAmountField;
}
public JTextField getWithdrawalCheckNumberField() {
return withdrawalCheckNumberField;
}
public JTextField getWithdrawalDateField() {
return withdrawalDateField;
}
public JTextField getWithdrawalPayeeField() {
return withdrawalPayeeField;
}
public JTextField getWithdrawalDescriptionField() {
return withdrawalDescriptionField;
}
public JTextField getWithdrawalAmountField() {
return withdrawalAmountField;
}
public class CheckbookTableModel extends DefaultTableModel {
private static final long serialVersionUID = 1L;
#Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return Integer.class;
case 1:
return LocalDate.class;
case 4:
case 5:
return Double.class;
default:
return String.class;
}
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
}
public class CheckbookCellRenderer implements TableCellRenderer {
private DateTimeFormatter formatter;
private JLabel label;
public CheckbookCellRenderer() {
this.formatter = DateTimeFormatter.ofPattern("MMM d, yyyy");
Font font = new Font("Segoe UI", Font.PLAIN, 14);
this.label = new JLabel();
label.setFont(font);
}
#Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
label.setHorizontalAlignment(JLabel.LEADING);
switch (column) {
case 0:
if (Integer.valueOf(value.toString()) <= 0) {
label.setText("");
} else {
label.setHorizontalAlignment(JLabel.TRAILING);
label.setText(value.toString() + " ");
}
break;
case 1:
LocalDate date = (LocalDate) value;
label.setText(" " + formatter.format(date));
break;
case 4:
case 5:
double amount = Double.valueOf(value.toString());
if (amount <= 0.0) {
label.setText("");
} else {
label.setHorizontalAlignment(JLabel.TRAILING);
label.setText(String.format("%,.2f", amount) + " ");
}
break;
default:
label.setText(" " + value.toString());
break;
}
return label;
}
}
public class DepositListener implements ActionListener {
private final CheckbookGUI view;
private final Checkbook model;
public DepositListener(CheckbookGUI view, Checkbook model) {
this.view = view;
this.model = model;
}
#Override
public void actionPerformed(ActionEvent event) {
String date = view.getDepositDateField().getText().trim();
Double amount = Double.valueOf(view.getDepositAmountField().getText().trim());
Transaction transaction = new Transaction(null, date, "Deposit", "", amount);
model.addTransaction(transaction);
model.getAccount().addDeposit(amount);
view.updateBalanceField();
view.updateTableModel(transaction);
view.getDepositAmountField().setText("");
view.getDepositDateField().setText("");
}
}
public class WithdrawalListener implements ActionListener {
private final CheckbookGUI view;
private final Checkbook model;
public WithdrawalListener(CheckbookGUI view, Checkbook model) {
this.view = view;
this.model = model;
}
#Override
public void actionPerformed(ActionEvent event) {
String checkNumberString = view.getWithdrawalCheckNumberField().getText().trim();
String date = view.getWithdrawalDateField().getText().trim();
String payee = view.getWithdrawalPayeeField().getText().trim();
String description = view.getWithdrawalDescriptionField().getText().trim();
Double amount = Double.valueOf(view.getWithdrawalAmountField().getText().trim());
Integer checkNumber = null;
try {
checkNumber = Integer.valueOf(checkNumberString);
} catch (NumberFormatException e) {
}
Transaction transaction = new Transaction(checkNumber, date, payee,
description, -amount);
model.addTransaction(transaction);
model.getAccount().subtractWithdrawal(amount);
view.updateBalanceField();
view.updateTableModel(transaction);
view.getWithdrawalCheckNumberField().setText("");
view.getWithdrawalDateField().setText("");
view.getWithdrawalPayeeField().setText("");
view.getWithdrawalDescriptionField().setText("");
view.getWithdrawalAmountField().setText("");
}
}
public class Checkbook {
private final Account account;
private final List<Transaction> transactions;
public Checkbook() {
this.transactions = new ArrayList<>();
this.account = new Account("10002939", "John H. Smith");
this.account.addDeposit(1400.00);
Transaction transaction = new Transaction(
null, "4/1/21", "Starting Balance", "", 1400.00);
addTransaction(transaction);
}
public void addTransaction(Transaction transaction) {
this.transactions.add(transaction);
}
public Account getAccount() {
return account;
}
public List<Transaction> getTransactions() {
return transactions;
}
}
public class Account {
private int balance;
private final String accountNumber;
private final String accountName;
public Account(String accountNumber, String accountName) {
this.accountNumber = accountNumber;
this.accountName = accountName;
this.balance = 0;
}
public String getAccountNumber() {
return accountNumber;
}
public String getAccountName() {
return accountName;
}
public double getBalance() {
return 0.01 * balance;
}
public void addDeposit(double amount) {
this.balance += (int) (100.0 * amount);
}
public void subtractWithdrawal(double amount) {
this.balance -= (int) (100.0 * amount);
}
}
public class Transaction {
private final double amount;
private final int checkNumber;
private final DateTimeFormatter inputFormatter;
private final LocalDate transactionDate;
private final String description;
private final String payee;
public Transaction(Integer checkNumber, String transactionDateString,
String payee, String description, double amount) {
if (checkNumber == null) {
this.checkNumber = 0;
} else {
this.checkNumber = checkNumber;
}
this.inputFormatter = DateTimeFormatter.ofPattern("M/d/yy");
this.transactionDate = LocalDate.parse(transactionDateString, inputFormatter);
this.payee = payee;
this.description = description;
this.amount = amount;
}
public double getAmount() {
return amount;
}
public int getCheckNumber() {
return checkNumber;
}
public LocalDate getTransactionDate() {
return transactionDate;
}
public String getPayee() {
return payee;
}
public String getDescription() {
return description;
}
}
}

java frame not changing colour

I am unable to change the colour of my frame in Java code below. I know the code to change it would be frame.getContentPane().setBackground(Color.gray); However, this is not working for me, I am not sure what is the reason behind this, but if you are able to solve the problem do let me know, thank you.
public class UserLoginPage implements ActionListener {
//Put all JLabels,Frames and buttons here etc
JPanel panel = new JPanel();
JFrame frame = new JFrame();
JLabel userLabel = new JLabel("Username");
JLabel passwordLabel = new JLabel("Password");
JTextField userText = new JTextField();
JTextField passwordText = new JTextField();
JButton loginButton = new JButton("Login");
//Label for successful login
JLabel success = new JLabel();
//Default Constructor to add the frames and panels etc
public UserLoginPage(){
panel.setLayout(null);
userLabel.setBounds(10,20,80,25);
panel.add(userLabel);
passwordLabel.setBounds(10,50,80,25);
panel.add(passwordLabel);
userText.setBounds(100,20,165,25);
panel.add(userText);
passwordText.setBounds(100,50,165,25);
panel.add(passwordText);
loginButton.setBounds(10,80,80,25);
loginButton.addActionListener(this);
panel.add(loginButton);
success.setBounds(10,110,300,25);
panel.add(success);
//success.setText();
frame.setSize(500,500);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().setBackground(Color.gray);
frame.setVisible(true);
frame.add(panel);
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new UserLoginPage();
}
});
}
#Override
public void actionPerformed(ActionEvent e) {
String user = userText.getText();
String password = passwordText.getText();
System.out.println(user + ", " + password);
if(user.equals("Jackson") && password.equals("1234")){
JOptionPane.showMessageDialog(frame,"Login successful");
}
else{
JOptionPane.showMessageDialog(frame,"Invalid password or username");
}
}
}
You're adding panel, a JPanel to your JFrame, and since JFrame's contentPane uses a BorderLayout, this JPanel (which is opaque), will completely cover the contentPane, preventing visualization of the contentPane's background.
Solution:
Either make the panel not-opaque via panel.setOpaque(false); so that now its container's colors or images will show through
or leave it default opaque give it and not the contentPane the background color of choice.
Unrelated issue is here:
panel.setLayout(null)
You really don't want to be doing this for many reasons, including because this will make your GUI work well / look nice on only one platform. It also makes it very hard to upgrade and enhance the GUI later.
For example, and incorporating some of Andrew Thompson's suggestions, here is an example login GUI that is geared towards creating a JPanel, one that in this example is placed into a modal JDialog (similar to a JOptionPane but with more flexibility) and displayed. The code uses GridBagLayout along with GridBagConstraints when adding components to place them where I want them to be in a pleasing way that works on all platforms, and that allows ease and flexibility should I want to add more components:
import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class UserLoginPanel extends JPanel {
private static final Color BACKGROUND = new Color(200, 200, 200);
private JTextField userText = new JTextField(15);
private JPasswordField passwordText = new JPasswordField(15);
LoginAction loginAction = new LoginAction(this, "Login", KeyEvent.VK_L);
JButton loginButton = new JButton(loginAction);
public UserLoginPanel() {
super(new GridBagLayout());
setBackground(BACKGROUND);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
int insetGap = 4;
gbc.insets = new Insets(insetGap, insetGap, insetGap, insetGap);
add(new JLabel("User Name:"), gbc);
gbc.gridx = 1;
add(userText, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
add(new JLabel("Password"), gbc);
gbc.gridx = 1;
add(passwordText, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
gbc.gridwidth = 2;
add(loginButton, gbc);
insetGap = 8;
setBorder(BorderFactory.createEmptyBorder(insetGap, insetGap, insetGap, insetGap));
}
public String getUserName() {
return userText.getText();
}
public char[] getPassword() {
return passwordText.getPassword();
}
public static void main(String[] args) {
UserLoginPanel loginPanel = new UserLoginPanel();
JDialog dialog = new JDialog(null, "User Login", ModalityType.APPLICATION_MODAL);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.add(loginPanel);
dialog.pack();
dialog.setLocationByPlatform(true);
dialog.setVisible(true);
}
}
#SuppressWarnings("serial")
class LoginAction extends AbstractAction {
private UserLoginPanel loginPanel;
public LoginAction(UserLoginPanel loginPanel, String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, KeyEvent.VK_L);
this.loginPanel = loginPanel;
}
#Override
public void actionPerformed(ActionEvent e) {
String userName = loginPanel.getUserName();
char[] password = loginPanel.getPassword();
System.out.println("User Name: " + userName);
System.out.println("Password: " + new String(password));
Component source = (Component) e.getSource();
if (source != null) {
Window window = SwingUtilities.getWindowAncestor(source);
if (window != null) {
window.dispose();
}
}
}
}

JButton listener not firing

I seperated my codes into MVC model and now my confirm button action listener is not printing the username and password even though I added a Actionlistener for it. please help thanks.
Codes
LoginDialog.java
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
#SuppressWarnings("serial")
public class LoginDialog extends JDialog {
private JLabel nameLabel;
private JLabel passwordLabel;
private JTextField usernameTF;
private JPasswordField passwordTF;
private JButton confirmBtn;
private JButton cancelBtn;
private JPanel topPanel;
private JPanel buttonPanel;
private GridBagConstraints gbc;
public LoginDialog() {
this.setTitle("Authentication");
topPanel = new JPanel(new GridBagLayout());
buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
nameLabel = new JLabel("Name : ");
passwordLabel = new JLabel("Password : ");
usernameTF = new JTextField();
passwordTF = new JPasswordField();
confirmBtn = new JButton("Confirm");
cancelBtn = new JButton("Cancel");
buttonPanel.add(confirmBtn);
buttonPanel.add(cancelBtn);
gbc = new GridBagConstraints();
gbc.insets = new Insets(4, 4, 4, 4);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 0;
topPanel.add(nameLabel, gbc);
gbc.gridx = 1;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
topPanel.add(usernameTF, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0;
topPanel.add(passwordLabel, gbc);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx = 1;
gbc.gridy = 1;
gbc.weightx = 1;
topPanel.add(passwordTF, gbc);
this.add(topPanel);
this.add(buttonPanel, BorderLayout.SOUTH);
}
public void showLoginDialog() {
LoginDialog ld = new LoginDialog();
ld.setSize(400, 150);
ld.setVisible(true);
ld.setLocationRelativeTo(null);
}
public String getUsername() {
return usernameTF.getText();
}
public String getPassword() {
return new String(passwordTF.getPassword());
}
public void confirmBtnListner(ActionListener listener) {
confirmBtn.addActionListener(listener);
}
}
Controller.java
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Controller {
private LoginDialog loginDialog;
public Controller(LoginDialog loginDialog) {
this.loginDialog = loginDialog;
loginDialog.showLoginDialog();
loginDialog.confirmBtnListner(new BtnListener());
}
class BtnListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(loginDialog.getUsername());
System.out.println(loginDialog.getPassword());
}
}
public static void main(String[] args) {
LoginDialog loginDialog = new LoginDialog();
new Controller(loginDialog);
}
}
You are having two instances of LoginDialog class.
One you are creating in your controller and the other one is in your LoginDialog#showLoginDialog() method.
Let's list them:
1st instance - In the controller class named `loginDialog`
2nd instance - In the `LoginDialog` class named `ld`
Here ld is an object created within loginDialog object. But they are two different JDialog objects. When you call
loginDialog.showLoginDialog()
another object ld is created from within the method. The JDialog refered is set to visible by:
ld.setVisible(true)
So now,
Object `ld` is visible
And Object `loginDialog` is NOT yet visible as you havent done `loginDialog.setVisible(true)` yet.
Now are adding the ActionListener to the button within loginDialog object, which is not yet visible. While there is no ActionListener added to the Button within ld object.
Final conclusion:
Object ld is visible, but button within it has NO ActionListener.
Object loginDialog is NOT yet visible. But the button within it has an ActionListener.
The button you are clicking is a part of ld object which has NO action listener associated to it.
The button which has an ActionListener associated to it is a part of loginDialog object which is NOT visible.
Wanna check if I am right?
Just add these lines in your controller constructor:
loginDialog.setVisible(true);
loginDialog.setSize(400, 150);
loginDialog.setLocationRelativeTo(null);
I won't give you the full solution as we don't spoonfeed here on stack overflow. So it's a challange for you to adjust your code accordingly. :)
The method showLoginDialog() creates a new instance of your dialog, which does not have the actionlistener.
fix: don't create a new instance - use the one you have.
public void showLoginDialog() {
setSize(400, 150);
setVisible(true);
setLocationRelativeTo(null);
}

JTextField not positioned correctly

I've made a JFrame with two JPanels aligned within it, one with a width of 750 pixels and the other with a width of 250 pixels. So far that's worked fine. Next I wanted to add some JTextFields to the panel on the right, so I included them in the constructor. Now when I try to run the code the textfields are positioned in the centre of the other panel, and aren't fully expanded until something is typed in them (they look like thin white strips). I haven't set any layouts at the moment as I just want to draw the textfields initially and arrange them later, only I do want them to be in the correct panel. Why isn't this working?
Main class:
package forces;
import java.awt.BorderLayout;
import javax.swing.*;
public class PrimaryWindow extends JFrame{
private static final long serialVersionUID = 1L;
JFrame frame;
ForcePanel panel;
DataPanel dpanel;
public PrimaryWindow()
{
frame = new JFrame("Forces");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(1000,800);
frame.setResizable(false);
panel = new ForcePanel();
frame.add(panel);
dpanel = new DataPanel();
frame.add(dpanel);
frame.setVisible(true);
}
public static void main(String args[])
{
new PrimaryWindow();
}
}
Panel 1 (this is the 750 pixel panel):
package forces;
import javax.swing.*;
import java.awt.*;
public class ForcePanel extends JPanel {
boolean simulate = false;
private static final long serialVersionUID = 1L;
public ForcePanel()
{
this.setSize(750,800);
this.setBackground(Color.BLACK);
}
}
Panel 2 (where the text fields should be):
package forces;
import javax.swing.*;
import java.awt.Color;
import java.awt.BorderLayout;
public class DataPanel extends JPanel {
private static final long serialVersionUID = 1L;
JTextField slopeangle;
JTextField g;
JTextField objectmass;
public DataPanel()
{
this.setLayout(new BorderLayout());
this.setSize(250,800);
this.setBackground(Color.GRAY);
slopeangle = new JTextField(20);
g = new JTextField(20);
objectmass = new JTextField(20);
this.add(slopeangle);
this.add(g);
this.add(objectmass);
}
}
As has been mentioned, you will want to use layout managers to best arrange your components in your GUI. I would override the getPreferredSize() method of the graphics component but let everything else fall to its own innate preferred size. GridBagLayout could be used to easily arrange a grid of JTextFields, and BorderLayout is great for overall arrangements of the GUI. For instance:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.HashMap;
import java.util.Map;
import javax.swing.*;
#SuppressWarnings("serial")
public class PrimaryPanel extends JPanel {
private ForcePanel forcePanel = new ForcePanel();
private DataPanel dataPanel = new DataPanel();
public PrimaryPanel() {
setLayout(new BorderLayout());
add(forcePanel, BorderLayout.CENTER);
add(dataPanel, BorderLayout.LINE_END);
}
private static void createAndShowGUI() {
PrimaryPanel paintEg = new PrimaryPanel();
JFrame frame = new JFrame("PrimaryPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(paintEg);
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 ForcePanel extends JPanel {
private static final int PREF_W = 750;
private static final int PREF_H = 800;
public ForcePanel() {
setBackground(Color.black);
}
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H); }
}
#SuppressWarnings("serial")
class DataPanel extends JPanel {
private static final int TEXT_FIELD_COLUMNS = 10;
private static final int GAP = 5;
private static final Insets RIGHT_GAP_INSETS = new Insets(GAP, GAP, GAP, 2 * GAP);
private static final Insets BALANCED_INSETS = new Insets(GAP, GAP, GAP, GAP);
public static final String[] FIELD_LABELS = {
"Slope Angle", "G", "Object Mass",
"Time Steps", "Max Time", "Fubarlicious!"
};
private Map<String, JTextField> labelFieldMap = new HashMap<>();
public DataPanel() {
JPanel labelFieldPanel = new JPanel(new GridBagLayout());
int row = 0;
for (String fieldLabelLText : FIELD_LABELS) {
JLabel fieldLabel = new JLabel(fieldLabelLText);
JTextField textField = new JTextField(TEXT_FIELD_COLUMNS);
labelFieldPanel.add(fieldLabel, getGbc(row, 0));
labelFieldPanel.add(textField, getGbc(row, 1));
labelFieldMap.put(fieldLabelLText, textField);
row++;
}
setLayout(new BorderLayout(GAP, GAP));
add(labelFieldPanel, BorderLayout.PAGE_START);
}
public static GridBagConstraints getGbc(int row, int column) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = column;
gbc.gridy = row;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
if (column == 0) {
gbc.anchor = GridBagConstraints.LINE_START;
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = RIGHT_GAP_INSETS;
} else {
gbc.anchor = GridBagConstraints.LINE_END;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = BALANCED_INSETS;
}
return gbc;
}
}
Which would look like:

Categories

Resources