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
Related
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;
}
}
}
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;
}
}
}
In my FlashCardPanel class, I have a subpanel,LabelPanel, with a Grid Bag Layout. It consists of a constructor with an edit button, a button to "flip" the card, and the label to display the term/definition. My problem is that every time I click my "Flip" Button to display the definition of my term, the flip button will change size, usually matching the length of the definition.
Images of the problem
http://postimg.org/gallery/ymww3axq/
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class FlashCardPanel extends JPanel{
private String term;
private String definition;
// shows the current text whether it is a term or definition
private JLabel currentLabel;
private static String NO_CARDS = "This set is empty";
//current card being displayed
private FlashCard currentCard;
//new card that is added to the deck
private FlashCard newCard;
// true = term is showing; false = definition is showing
private boolean termShowing = true;
private AddNewCard frame;
private CardSet cardSet;
private int cardIndex = 0;
private ButtonPanel bPanel;
private LabelPanel lPanel;
private static JButton flipButton;
private static JButton nextButton;
private static JButton prevButton;
private static JButton addCard;
private static JButton deleteCard;
private static JButton editButton;
public FlashCardPanel(CardSet cardSet) {
this.cardSet = cardSet;
this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
term = cardSet.get(0).getTerm();
definition = cardSet.get(0).getDefintion();
currentCard = cardSet.get(0);
createButtons();
lPanel = new LabelPanel();
bPanel = new ButtonPanel();
add(lPanel);
add(bPanel);
}
public FlashCardPanel() {
this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
add(lPanel);
add(bPanel);
}
private class LabelPanel extends JPanel {
public LabelPanel() {
this.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(15,15,15,15);
currentLabel = new JLabel(term);
currentLabel.setText(cardSet.get(0).getTerm());
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 0;
c.gridx = 0;
c.gridy = 0;
add(editButton,c);
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 0;
c.gridwidth = 0;
c.weightx = 0;
c.gridx = 2;
c.gridy = 0;
add(flipButton,c);
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 40;
c.weightx = 0;
c.gridwidth = 3;
c.gridx = 1;
c.gridy = 3;
add(currentLabel,c);
}
}
private class ButtonPanel extends JPanel {
public ButtonPanel() {
this.setLayout(new GridLayout(2,2));
add(prevButton);
add(nextButton);
add(addCard);
add(deleteCard);
}
}
/*
* creates buttons for the panel. Should be called before
* any subpanel is created.
*/
private void createButtons()
{
flipButton = new JButton(" Flip Card ");
flipButton.addActionListener(new ButtonListener());
flipButton.setActionCommand("1");
nextButton = new JButton(" Next Card ");
nextButton.addActionListener(new ButtonListener());
nextButton.setActionCommand("2");
prevButton = new JButton(" Previous Card ");
prevButton.addActionListener(new ButtonListener());
prevButton.setActionCommand("3");
addCard = new JButton(" Add Card ");
addCard.addActionListener(new ButtonListener());
addCard.setActionCommand("4");
deleteCard = new JButton(" Delete Card ");
deleteCard.addActionListener(new ButtonListener());
deleteCard.setActionCommand("5");
editButton = new JButton("Edit");
editButton.addActionListener(new ButtonListener());
editButton.setActionCommand("6");
}
private class ButtonListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e) {
int action = Integer.parseInt(e.getActionCommand());
switch(action){
case 1:
flipCard();
break;
case 2:
nextCard();
break;
case 3:
previousCard();
break;
case 4:
createFrame();
break;
case 5:
deleteCard();
case 6:
createFrame(term,definition);
}
}
}
private void flipCard()
{
if (!cardSet.isEmpty()) {
if (termShowing) {
termShowing = false;
currentLabel.setText(definition);
}
else {
termShowing = true;
currentLabel.setText(term);
}
}
else {
currentLabel.setText(NO_CARDS);
term = "";
definition = "";
JOptionPane.showMessageDialog(this, "This set is empty");
}
}
private void nextCard()
{
if (!cardSet.isEmpty()) {
if (cardIndex == cardSet.size()-1)
cardIndex = 0;
else
cardIndex++;
term = cardSet.get(cardIndex).getTerm();
definition = cardSet.get(cardIndex).getDefintion();
if(termShowing)
currentLabel.setText(term);
else
currentLabel.setText(definition);
currentCard = cardSet.get(cardIndex);
}
else JOptionPane.showMessageDialog(this, "This set is empty");
}
private void previousCard()
{
if (!cardSet.isEmpty()) {
if (cardIndex == 0)
cardIndex = cardSet.size()-1;
else
cardIndex--;
term = cardSet.get(cardIndex).getTerm();
definition = cardSet.get(cardIndex).getDefintion();
if(termShowing)
currentLabel.setText(term);
else
currentLabel.setText(definition);
currentCard = cardSet.get(cardIndex);
}
else JOptionPane.showMessageDialog(this, "This set is empty");
}
/*
* adding a card
*/
private void createFrame() {
frame = new AddNewCard(100,100,this);
}
/*
* editing an existing card
*/
private void createFrame(String t, String d)
{
frame = new AddNewCard(100,100,this,t,d);
}
public void addNewCard(String t, String d) {
newCard = new FlashCard(t,d);
cardSet.add(newCard);
if (cardSet.isEmpty()) currentLabel.setText(newCard.getTerm());
}
public void editCard(String t, String d) {
currentCard.setTerm(t);
currentCard.setDefinition(d);
if (termShowing) currentLabel.setText(t);
else currentLabel.setText(d);
}
/*
* Deletes current card on display
*/
private void deleteCard()
{
if (!cardSet.isEmpty()) {
// if on the last card of the set
if (cardIndex == cardSet.size()-1) cardIndex--;
cardSet.remove(currentCard);
if (!cardSet.isEmpty()) {
currentCard = cardSet.get(cardIndex);
currentLabel.setText(cardSet.get(cardIndex).getTerm());
}
else currentLabel.setText(NO_CARDS);
}
else JOptionPane.showMessageDialog(this, "This set is empty");
}
}
You have several options including:
using a nested JPanels each with its own layout. For instance the buttons could be placed into a GridLayout JPanel, and this placed into a BorderLayout JPanel with the label BorderLayout.CENTER
I suggest that the long definition text be displayed within a JTextArea, not a JLabel. If you make it non-editable and remove borders, it could look like a JLabel.
If you go this route, you will want to turn on word wrap on the JTextArea.
You could swap JTextArea with JLabel (for the term) using a CardLayout.
Note, for future questions, please pare down your problem. For instance, if this were my question, I'd create something like the code below, small, self contained, runnable and demonstrates the problem:
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class FlashCardPanel2 extends JPanel {
private static final long serialVersionUID = 1L;
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private JLabel currentLabel;
private String term = "Term";
private String definition = "Definition: This will be a very long String to "
+ "illustrate the problem that you are having, and to try to help you get "
+ "a solution";
private JButton editButton = new JButton("Edit");
private JButton flipButton = new JButton(new FlipAction("Flip"));
public FlashCardPanel2() {
this.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(15, 15, 15, 15);
currentLabel = new JLabel(term);
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 0;
c.gridx = 0;
c.gridy = 0;
add(editButton, c);
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 0;
c.gridwidth = 0;
c.weightx = 0;
c.gridx = 2;
c.gridy = 0;
add(flipButton, c);
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 40;
c.weightx = 0;
c.gridwidth = 3;
c.gridx = 1;
c.gridy = 3;
add(currentLabel, c);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class FlipAction extends AbstractAction {
public FlipAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
String text = currentLabel.getText();
text = (text.equals(term)) ? definition : term;
currentLabel.setText(text);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("FlashCardPanel2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new FlashCardPanel2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
And here's a potential solution with CardLayout and GridLayout and BorderLayout:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class FlashCardPanel3 extends JPanel {
private static final long serialVersionUID = 1L;
private static final String CURRENT_LABEL = "current label";
private static final String DEFINITION = "definition";
private JLabel currentLabel;
private JTextArea currentDefinitionArea = new JTextArea(6, 20);
private CardLayout cardLayout = new CardLayout();
private JPanel cardHolder = new JPanel(cardLayout);
private String term = "Term";
private String definition = "Definition: This will be a very long String to "
+ "illustrate the problem that you are having, and to try to help you get "
+ "a solution";
private JButton editButton = new JButton("Edit");
private JButton flipButton = new JButton(new FlipAction("Flip"));
public FlashCardPanel3() {
currentDefinitionArea.setOpaque(false);
currentDefinitionArea.setText(definition);
currentDefinitionArea.setWrapStyleWord(true);
currentDefinitionArea.setLineWrap(true);
currentDefinitionArea.setEditable(false);
currentDefinitionArea.setFocusable(false);
currentLabel = new JLabel(term, SwingConstants.CENTER);
cardHolder.add(currentLabel, CURRENT_LABEL);
cardHolder.add(new JScrollPane(currentDefinitionArea), DEFINITION);
JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 5, 0));
buttonPanel.add(editButton);
buttonPanel.add(flipButton);
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setLayout(new BorderLayout(5, 5));
add(buttonPanel, BorderLayout.PAGE_START);
add(cardHolder);
}
private class FlipAction extends AbstractAction {
public FlipAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
// String text = currentLabel.getText();
// text = (text.equals(term)) ? definition : term;
// currentLabel.setText(text);
cardLayout.next(cardHolder);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("FlashCardPanel2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new FlashCardPanel3());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
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);
}
I'd like this program I have to have some kind of "sum" button which will add in the column "Description" summarised information about the movie. Lets say I have "die hard" as a title, age 7 from radiobutton, and horror selected from the checkbox. Pressin the button would put "Die hard, 7, horror" under the column. I have no idea how to aproach this case.
package naplety.Swing;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListModel;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.JCheckBox;
public class SamodzielnaListaOsob extends JFrame implements ActionListener {
JButton dodaj, erease;
JTextField film;
DefaultListModel<String> listFilm;
DefaultTableModel tableFilm;
public SamodzielnaListaOsob(String title) {
super(title);
setDefaultCloseOperation(EXIT_ON_CLOSE);
final JTextField film = new JTextField("Wpisz tytul filmu", 10);
film.setBorder(BorderFactory.createTitledBorder("Film"));
JPanel p1 = new JPanel();
p1.add(film);
JButton dodaj = new JButton("Add to list");
dodaj.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String nowyFilm = film.getText();
if (nowyFilm != "") {
listFilm.addElement(nowyFilm);
film.setText("");
}
}
});
JButton erease = new JButton("Clear");
erease.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
film.setText("");
}
});
JButton dodajDoTabeli = new JButton("Add to table");
dodajDoTabeli.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String nowyFilm = film.getText();
if (nowyFilm != "") {
int ile = tableFilm.getRowCount();
tableFilm.addRow(new Object[] { ile + 1, nowyFilm });
}
}
});
JRadioButton sevenbutton = new JRadioButton("7");
JRadioButton twbutton = new JRadioButton("12");
JRadioButton sixbutton = new JRadioButton("16");
JRadioButton eightbutton = new JRadioButton("18");
ButtonGroup bg1 = new ButtonGroup();
bg1.add(sevenbutton);
bg1.add(twbutton);
bg1.add(sixbutton);
bg1.add(eightbutton);
JPanel radioPanel = new JPanel();
radioPanel.setLayout(new GridLayout(4, 0));
radioPanel.add(sevenbutton);
radioPanel.add(twbutton);
radioPanel.add(sixbutton);
radioPanel.add(eightbutton);
radioPanel.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(), "Age"));
radioPanel.setSize(200, 200);
JCheckBox Horror = new JCheckBox("Horror");
JCheckBox Komedia = new JCheckBox("Comedy");
JCheckBox Thriller = new JCheckBox("Thriller");
JCheckBoxMenuItem listac = new JCheckBoxMenuItem();
listac.add(Horror);
listac.add(Komedia);
listac.add(Thriller);
JPanel listaChceck = new JPanel();
listaChceck.add(Horror);
listaChceck.add(Komedia);
listaChceck.add(Thriller);
listaChceck.setLayout(new GridLayout(3, 0));
JPanel p2 = new JPanel();
p2.add(dodaj);
p2.add(erease);
p2.add(dodajDoTabeli);
p2.add(radioPanel);
p2.add(listaChceck);
listFilm = new DefaultListModel<String>();
listFilm.addElement("Achacy");
listFilm.addElement("Bonifacy");
listFilm.addElement("Cezary");
JList<String> lista = new JList<String>(listFilm);
JScrollPane sl = new JScrollPane(lista);
sl.setPreferredSize(new Dimension(150, 150));
sl.setBorder(BorderFactory.createTitledBorder("List"));
String[] kolumnyTabeli = { "Nr", "Movie", "Description" };
tableFilm = new DefaultTableModel(kolumnyTabeli, 0) {
};
JTable tabela = new JTable(tableFilm);
JScrollPane st = new JScrollPane(tabela);
st.setPreferredSize(new Dimension(300, 150));
st.setBorder(BorderFactory.createTitledBorder("Table"));
JPanel p3 = new JPanel();
p3.add(sl);
p3.add(st);
setPreferredSize(new Dimension(900, 900));
setVisible(true);
p1.add(p2);
p2.add(p3);
setContentPane(p1);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new SamodzielnaListaOsob("List of movies");
}
});
}
}
You need to declare your variables either before you try to access them, or declare them global, which I did. I prefer this way.
Use .pack() on your frame to when you start the program, something actually shows.
Learn to use LayoutManagers for a better look.
Use arrays of RadioButtons and CheckBoxes so its easier to loop through them. I has to manually write a bunch of if statements, which would not be necessary if I could loop through them.
To get is a RadioButton or CheckBox is selected, use .isSelected()
.setVisible(true) after you add all your components.
Here's is your refactored code. I did nothing else to it, but fix the issue posted in your question. It now adds the info the desciption, when you hit the Add Film button.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
public class SamodzielnaListaOsob extends JFrame {
JButton dodaj, erease;
JTextField film;
DefaultListModel<String> listFilm;
DefaultTableModel tableFilm;
JList<String> lista = null;
JRadioButton sevenbutton = new JRadioButton("7");
JRadioButton twbutton = new JRadioButton("12");
JRadioButton sixbutton = new JRadioButton("16");
JRadioButton eightbutton = new JRadioButton("18");
JCheckBox Horror = new JCheckBox("Horror");
JCheckBox Komedia = new JCheckBox("Comedy");
JCheckBox Thriller = new JCheckBox("Thriller");
ButtonGroup bg1 = new ButtonGroup();
public SamodzielnaListaOsob(String title) {
super(title);
setDefaultCloseOperation(EXIT_ON_CLOSE);
final JTextField film = new JTextField("Wpisz tytul filmu", 10);
film.setBorder(BorderFactory.createTitledBorder("Film"));
JPanel p1 = new JPanel();
p1.add(film);
JButton dodaj = new JButton("Add to list");
dodaj.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String nowyFilm = film.getText();
if (nowyFilm != "") {
listFilm.addElement(nowyFilm);
film.setText("");
}
}
});
JButton erease = new JButton("Clear");
erease.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
film.setText("");
}
});
JButton dodajDoTabeli = new JButton("Add to table");
dodajDoTabeli.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String nowyFilm = film.getText();
if (nowyFilm != "") {
int ile = tableFilm.getRowCount();
String title = lista.getSelectedValue();
int age;
if (sixbutton.isSelected()) {
age = 16;
} else if (sevenbutton.isSelected()) {
age = 7;
} else if (eightbutton.isSelected()) {
age = 18;
} else {
age = 12;
}
String genres = "";
if (Horror.isSelected()) {
genres += "Horror, ";
}
if (Komedia.isSelected()) {
genres += "Komedia, ";
}
if (Thriller.isSelected()) {
genres += "Thriller";
}
String desc = title + ", " + age + ", " + genres;
tableFilm.addRow(new Object[]{ile + 1, nowyFilm, desc});
}
}
});
bg1.add(sevenbutton);
bg1.add(twbutton);
bg1.add(sixbutton);
bg1.add(eightbutton);
JPanel radioPanel = new JPanel();
radioPanel.setLayout(new GridLayout(4, 0));
radioPanel.add(sevenbutton);
radioPanel.add(twbutton);
radioPanel.add(sixbutton);
radioPanel.add(eightbutton);
radioPanel.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(), "Age"));
radioPanel.setSize(200, 200);
JCheckBoxMenuItem listac = new JCheckBoxMenuItem();
listac.add(Horror);
listac.add(Komedia);
listac.add(Thriller);
JPanel listaChceck = new JPanel();
listaChceck.add(Horror);
listaChceck.add(Komedia);
listaChceck.add(Thriller);
listaChceck.setLayout(new GridLayout(3, 0));
JPanel p2 = new JPanel();
p2.add(dodaj);
p2.add(erease);
p2.add(dodajDoTabeli);
p2.add(radioPanel);
p2.add(listaChceck);
listFilm = new DefaultListModel<String>();
listFilm.addElement("Achacy");
listFilm.addElement("Bonifacy");
listFilm.addElement("Cezary");
lista = new JList<String>(listFilm);
JScrollPane sl = new JScrollPane(lista);
sl.setPreferredSize(new Dimension(150, 150));
sl.setBorder(BorderFactory.createTitledBorder("List"));
String[] kolumnyTabeli = {"Nr", "Movie", "Description"};
tableFilm = new DefaultTableModel(kolumnyTabeli, 0) {
};
JTable tabela = new JTable(tableFilm);
JScrollPane st = new JScrollPane(tabela);
st.setPreferredSize(new Dimension(300, 150));
st.setBorder(BorderFactory.createTitledBorder("Table"));
JPanel p3 = new JPanel();
p3.add(sl);
p3.add(st);
p1.add(p2);
p2.add(p3);
setContentPane(p1);
pack();
setPreferredSize(new Dimension(900, 900));
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new SamodzielnaListaOsob("List of movies");
}
});
}
}
Radio buttons and Check Buttons don't work like textfields. In a textfield, the useful values are picked up from the "text" member (example: getText()). A radioButton instead defines a set of fixed choices (well, you can make them dynamic, but it doesn't worth it, there are better components for that kind of work) like "yes" and "no". Usually, when you pickup some rabiobutton, you use the isChecked() method (returns boolean, it may be isChecked(), I don't remember) to react in one way or another. Example:
String age = 0;
if(sevenbutton.isSelected()){
age = 7;
}
Nonetheless, I think you can get the value from the text in the sevenbutton using getText(), but you're gonna need to check which radiobutton is checked anyway. A checkButton works in a pretty similar way, but for non-exclusive choices, so you need to use the isSelected() method, or similar, anyway.
Your method should look like:
private void addMovie(){
String age = "0";
String gender = "";
//Evaluate radioButtons
if(sevenbutton.isSelected()){
age = 7;
}
//Evaluate checkbuttons
if(Horror.isSelected()){
gender = gender+" horror";
}
String movie = film+" "+age+" "+gender;
//do anything else
}