I'm trying to make a GUI interface using java swing that is able to add users to a text file that I treat as a database. The GUI interface has a JTable which pulls the existing items in the text file and displays it initially. Once I go to add a new item, it gets updated on the text file but not on the JTable. This is mainly because I only call the JTable once the way I set up my code. I'm wondering how I can call the JTable multiple times or make a button for it to call a refresh of the table and display the newly added items alongside the old items.
I want it to be able to either call the refresh of the table in the updateList
function or once the viewButton
is pressed which triggers an else if statement which can do that in the actionPerformed
function.
Here is my code:
class UserManager extends JFrame implements ActionListener {
private JTextField firstNameField, lastNameField, salaryField;
private JButton addButton, removeButton, viewButton, sortButton, getButton;
private JList<Employee> userList;
private ArrayList<Employee> users;
public UserManager() {
setTitle("Employee Manager");
setSize(300, 300);
setDefaultCloseOperation(EXIT_ON_CLOSE);
firstNameField = new JTextField(20);
lastNameField = new JTextField(20);
salaryField = new JTextField(20);
addButton = new JButton("Add");
addButton.addActionListener(this);
removeButton = new JButton("Remove");
removeButton.addActionListener(this);
viewButton = new JButton("Refresh List"); // POTENTIAL BUTTON TO REFRESH JTABLE?
viewButton.addActionListener(this);
sortButton = new JButton("Sort List");
sortButton.addActionListener(this);
// Pulling data from text file database
ArrayList<ArrayList<String>> databaseData = ReadFile();
users = new ArrayList<Employee>();
// Adding existing databaseData to users
for (int i = 0; i < databaseData.size(); i ) {
Employee user = new Employee(databaseData.get(i).get(0), databaseData.get(i).get(1), Integer.valueOf(databaseData.get(i).get(2)));
users.add(user);
}
userList = new JList<Employee>(users.toArray(new Employee[0]));
userList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JPanel firstNamePanel = new JPanel();
firstNamePanel.add(new JLabel("First Name:"));
firstNamePanel.add(firstNameField);
JPanel lastNamePanel = new JPanel();
lastNamePanel.add(new JLabel("Last Name:"));
lastNamePanel.add(lastNameField);
JPanel salaryPanel = new JPanel();
salaryPanel.add(new JLabel("Salary:"));
salaryPanel.add(salaryField);
JPanel buttonPanel = new JPanel();
buttonPanel.add(addButton);
buttonPanel.add(removeButton);
buttonPanel.add(viewButton);
buttonPanel.add(sortButton);
// Converting 2D arraylist to normal 2D array for JTable
String[][] data = databaseData.stream().map(u -> u.toArray(new String[0])).toArray(String[][]::new);
// Initializing column names of JTable
String[] columnNames = { "FName", "LName", "Salary" };
// Initializing the JTable (THIS IS WHAT I NEED TO REFRESH)
JTable j = new JTable(data, columnNames);
j.setBounds(1000, 1000, 900, 900);
// adding it to JScrollPane
JScrollPane table = new JScrollPane(j);
JPanel mainPanel = new JPanel(new GridLayout(5, 3));
mainPanel.add(firstNamePanel);
mainPanel.add(lastNamePanel);
mainPanel.add(salaryPanel);
mainPanel.add(buttonPanel);
mainPanel.add(table);
add(mainPanel);
}
public void actionPerformed(ActionEvent e) {
// "Add" button is clicked
if (e.getSource() == addButton) {
String firstName = firstNameField.getText();
String lastName = lastNameField.getText();
int salary = 0;
try {
salary = Integer.parseInt(salaryField.getText());
}
catch (NumberFormatException nfe) {
JOptionPane.showMessageDialog(this, "Please enter a valid salary", "Error", JOptionPane.ERROR_MESSAGE);
return;
}
// Error check to see if full name and age is entered
if (!firstName.equals("") && !lastName.equals("")) {
Employee user = new Employee(firstName, lastName, salary);
users.add(user);
updateList();
firstNameField.setText("");
lastNameField.setText("");
salaryField.setText("");
}
else {
JOptionPane.showMessageDialog(this, "Please enter a valid full name", "Error", JOptionPane.ERROR_MESSAGE);
}
}
// POTENTIAL BUTTON THAT REFRESHES JTABLE?
else if (e.getSource() == viewButton) {
}
}
// Updates the list after a CRUD operation is called
private void updateList() {
userList.setListData(users.toArray(new Employee[0]));
try {
FileWriter fw = new FileWriter("db.txt", false);
// BufferedWriter bw = new BufferedWriter(fw);
// PrintWriter pw = new PrintWriter(bw);
// Loop through each student and write to the text file
for (int i = 0; i < users.size(); i ) {
fw.write(toString(users.get(i).getFirstName(), users.get(i).getLastName(), users.get(i).getSalary()));
}
fw.close();
// CALL A REFRESH FOR THE TABLE HERE??
}
catch (IOException io) {
}
}
// Combing multiple string and ints into a string
public String toString(String firstName, String lastName, int salary) {
return firstName ", " lastName ", " salary "\n";
}
// Reading database
public static ArrayList<ArrayList<String>> ReadFile() {
try {
// Choose grades.txt file to look at
File myObj = new File("db.txt");
// Create scanner object
Scanner myReader = new Scanner(myObj);
// Create 2d list array to hold all the single list arrays of single information
ArrayList<ArrayList<String>> combinedArr = new ArrayList<ArrayList<String>>();
// While the file reader is still reading lines in the text
while (myReader.hasNextLine()) {
// Read strings of text in txt file
String data = myReader.nextLine();
// Get first and last name from a string
ArrayList<String> temp = GetName(data);
// Add the person and their salary to the combined array that holds everyones
combinedArr.add(temp);
}
// Close file once there are no more lines to read
myReader.close();
return combinedArr;
}
catch (FileNotFoundException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
// Return invalid list string with nothing if error
ArrayList<ArrayList<String>> Invalid = new ArrayList<ArrayList<String>>();
return Invalid;
}
// Parses name in db
public static ArrayList<String> GetName(String data) {
String first = "";
String last = "";
String sal = "";
// System.out.println(data[0])
for (int i = 0; i < data.length(); i ) {
if (data.charAt(i) == ',') {
// Start from 2 indexes after the first occurance of the comma
for (int j = i 2; j < data.length(); j ) {
if (data.charAt(j) == ',') {
for (int n = j 2; n < data.length(); n ) {
sal = data.charAt(n);
}
break;
}
last = data.charAt(j);
}
break;
}
first = data.charAt(i);
}
// Initializing package array to send all values
ArrayList<String> arr = new ArrayList<String>();
arr.add(first);
arr.add(last);
arr.add(sal);
return arr;
}
public static void main(String[] args) {
UserManager frame = new UserManager();
frame.setVisible(true);
}
}
class Employee {
// Initalizing variables
private String firstName;
private String lastName;
private int salary;
// Assigning variables
public Employee(String firstName, String lastName, int salary) {
this.firstName = firstName;
this.lastName = lastName;
this.salary = salary;
}
// return first name
public String getFirstName() {
return firstName;
}
// return last name
public String getLastName() {
return lastName;
}
// return salary
public int getSalary() {
return salary;
}
}
CodePudding user response:
Initializing the JTable (THIS IS WHAT I NEED TO REFRESH)
You don't refresh the table. The data for all Swing components is contained in a "model". You change the data in the model. When changes to the model are made the table is repainted to reflect the change.
So you could either:
- create a new
DefaultTableModel
(which is unnecessary) - update the existing
DefaultTableModel
, by using theaddRow(...)
method to update the model every time you write a new item to your file.
Instead of using code like:
JTable j = new JTable(data, columnNames);
You can use:
model = new DefaultTableModel(data, columnNames)
table = new JTable(model)
Now you can access the DefaultTableModel any time you need to by creating an instance variable in your class or by using the table.getModel()
method.
CodePudding user response:
Usually lists and tables are updated through their models. They represent the information shown to the user. You can try this.
Create in your class a new field. Use this field when initializing the table in your constructor.
private JTable userTable;
In your update function, try this:
DefaultTableModel model = new DefaultTableModel();
users = // fetch here for your users
for (int i = 0, i < user.length, i )
model.addRow(users[i]);
}
// finally set new model in your table
userTable.setModel(model);
userTable.doLayout();