I made a GUI using JTable(tableModel) and a JPanel where the user can add data through JTextFields to an Arraylist, but for some reason when I click the add JButton, the adding fails and points to the line where I want to add the arraylist row to the tableModel.
public final static ArrayList<Members> adat = new ArrayList<>();
DefaultTableModel tableModel;
String[][] dummy = new String[][]{{"001", "Jack Black", "London", "20"}};
String[] header = new String[]{"id", "Name", "City", "Age"};
tableModel = new DefaultTableModel(dummy, header);
JTable t = new JTable();
t.setModel(tableModel);
panel1.add(new JScrollPane(t));
frame.add(panel1);
JPanel jp = new EditPanel();
frame.add(jp);
public static void newData() { // the "add" button function
Members newMember = null;
try {
newMember = new Members(
Integer.parseInt(EditPanel.idEdit.getText()),
EditPanel.nameEdit.getText(),
EditPanel.cityEdit.getText(),
Integer.parseInt(EditPanel.ageEdit.getText())
);
adat.add(newMember);
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(null, ex.getMessage(), "Error in modification", ERROR_MESSAGE);
}
toTable();
}
and the method toTable() gets the members data from the arraylist to the JTable
static void toTable() { // adding the users data to the table
if (adat.size() > 0) {
for (int i = 0; i < adat.size(); i++) {
int id = adat.get(i).id;
String name = adat.get(i).name;
String city = adat.get(i).city;
int age = adat.get(i).age;
Object[] data = new Object[4];
data[0] = id;
data[1] = name;
data[2] = city;
data[3] = age;
tableModel.addRow(data); // this is the line where the error points
}
}
}
You're encountering an error at tableModel.addRow(data); because tableModel does not have a method called addRow (docs).
You probably mixed up the DefaultTableModel tableModel with the actual JTable t.
It should be t.addRow(data), although you need to make t global first!
Related
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;
}
}
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 the addRow(...) 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.
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();
I have JTable which has few columns.In that I have JComboBox. At program start I want them to be empty.I have one JButton on click action of button i have the code to add row dynamically in table.
But after adding the row i get garbage value in the cell having JComboBox. As shown in below figure :
And here is the code :
Code to add JComboBox in table
// Create columns names
String columnNames[] = { "Item", "Sun Item", "Required Quantity","Price","Gross Amount" };
// Create some data
final String dataValues[][] =
{
{ "", "", "","","", },
};
tableModel = new DefaultTableModel(dataValues, columnNames);
// Create a new table instance
table = new JTable( tableModel );
updateItemCombo();
TableColumn itemColumn = table.getColumnModel().getColumn(0);
itemColumn.setCellEditor(new DefaultCellEditor(comboItem));
public void updateItemCombo(){
Vector<String> s = new Vector<String>();
try{
setConnectin();
String str = "select * from ItemTable";
stmt = conn.createStatement();
rs = stmt.executeQuery(str);
while(rs.next())
{
String nm = rs.getString("Item_Name");
s.add(nm);
}
conn.close();
}catch(Exception e2){
e2.printStackTrace();
}
DefaultComboBoxModel<String> modelData = new DefaultComboBoxModel<String>(s);
comboItem.setModel(modelData);
}
Code to add row dynamically on button click :
btnAddOrder.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
tableModel.addRow(dataValues);
tableModel.fireTableDataChanged();
}
});
What should i do to remove this garbage value from table? Please help
The addRow(...) method takes a 1-Dimensional array as a parameter. You are attempting to add a 2-Dimensional array.
Also, do not use:
tableModel.fireTableDataChanged();
it is the job of the TableModel to invoke the appropriate fireXXX() method, which by the way in this case would be fireTableRowsInserted(...).
I have a JTable with the column names " Names " , " Quantity " and " Unit " .
I'm coding a program where you get the ingredients names.
So i need to get the whole row of one column and String it all up together,
because i need to store it in mySql and i have already set it all as String.
Any idea how i can do this ?
My code are as follows :
JTable Code:
DefaultTableModel model = (DefaultTableModel)table.getModel();
if(!txtQty.getText().trim().equals("")){
model.addRow(new Object[]{ingCB.getSelectedItem().toString(),txtQty.getText(),unitCB.getSelectedItem().toString()});
}else{
JOptionPane.showMessageDialog(null,"*Quantity field left blank");
}
Getting the values and for storing :
for(int i = 1; i<= i ; i++){
ingredients = table.getName();
}
This is for loop is wrong and it does not work because i have a constructor to take in Ingredients but because it is inside the loop, it cannot take it in.
Any suggestions please ? Thank you.
Constructor :
Food e2 = new Food(Name, Description, priceDbl, Image, Category, Ingredients, promotion );
e2.createFood();
I'm coding a program where you get the ingredients names. So i need to get the whole row of one column and String it all up together, because i need to store it in mySql and i have already set it all as String.
Want to do so, try this. Here I am getting result into ArrayList and String, as I am commented ArrayList you can avoid it.
public class TableValuePrint extends JFrame implements ActionListener{
private final JButton print;
private final JTable table;
private String str="";
public TableValuePrint() {
setSize(600, 300);
String[] columnNames = {"A", "B", "C"};
Object[][] data = {
{"Moni", "adsad", "Pass"},
{"Jhon", "ewrewr", "Fail"},
{"Max", "zxczxc", "Pass"}
};
table = new JTable(data, columnNames);
JScrollPane tableSP = new JScrollPane(table);
JPanel tablePanel = new JPanel();
tablePanel.add(tableSP);
tablePanel.setBackground(Color.red);
add(tablePanel);
setTitle("Result");
setSize(1000,700);
print=new JButton("Print");
JPanel jpi1 = new JPanel();
jpi1.add(print);
tablePanel.add(jpi1,BorderLayout.SOUTH);
print.addActionListener(this);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
TableValuePrint ex = new TableValuePrint();
ex.setVisible(true);
}
});
}
#Override
public void actionPerformed(ActionEvent ae) {
if(ae.getSource()==print){
// ArrayList list = new ArrayList();
for(int i = 0;i<table.getModel().getRowCount();i++)
{
//list.add(table.getModel().getValueAt(i, 0)); //get the all row values at column index 1
str=str+table.getModel().getValueAt(i,0).toString();
}
//System.out.println("List="+list);
System.out.println("String="+str);
}
}
}
Output
String=MoniJhonMax
basically what i am trying to do is, i have a JList which contain a list of available drive, if one of that drive selected by user then i will show all html files which located in selected drive in a JTable, so i put an event listener for my JList and then i create a JTable and put all data there and show it in the container. the code look like this:
static class HtmlListing implements ListSelectionListener
{
public void valueChanged(ListSelectionEvent event)
{
if (!event.getValueIsAdjusting())
{ //trying to remove and re-add controls in container.
EastCont.removeAll();
globarr = new ArrayList<File>(); // global variable
FileListing fl = new FileListing();
fl.walk(fileList1.getSelectedValue() + "work\\airasia\\html", 500, 0);
//if(globarr.size() > 0)
//{
Object[][] data = new Object[globarr.size()][globarr.size()];
for(int i = 0; i < globarr.size(); i++)
{
if(globarr.get(i).isFile())
{
String filename = globarr.get(i).getName().toString();
String date = sdf.format(globarr.get(i).lastModified());
Object[] obj = new Object[] {filename, filename.substring(filename.lastIndexOf(".") + 1), date, globarr.get(i).getAbsolutePath()};
data[i] = obj;
}
}
Object[] column = new Object[]{"name ", "type", "date modified", "path"};
DefaultTableModel model = new DefaultTableModel(data, column);
model.fireTableDataChanged();
table = new JTable(model)
{
private static final long serialVersionUID = 1L;
public boolean isCellEditable(int row, int column)
{
return false;
};
};
table.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
if (e.getClickCount() == 2)
{
int rowIdx = table.getSelectedRow(); // path to your new file
TableModel tm = table.getModel();
String path = tm.getValueAt(rowIdx, 3).toString();
File htmlFile = new File(path);
try // open the default web browser for the HTML page
{
Desktop.getDesktop().browse(htmlFile.toURI());
//Desktop.getDesktop().open(htmlFile);
}
catch (IOException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
});
table.removeColumn(table.getColumnModel().getColumn(3)); //hide column path from display
table.setFillsViewportHeight(true);
table.setIntercellSpacing(new Dimension(0, 5));
table.setShowGrid(false);
scrollPane = new JScrollPane(table);
EastCont = new JPanel();
EastCont.setLayout(new BorderLayout());
EastCont.add(scrollPane);
EastCont.setPreferredSize(new Dimension(1050, 1000));
//EastCont.repaint();
//EastCont.revalidate();
gui.add(EastCont, BorderLayout.EAST);
gui.revalidate();
gui.repaint();
// }
// else
// {
// EastCont.remove(table);
// gui.remove(EastCont);
// gui.revalidate();
// gui.repaint();
// }
}
this code work only for first time, but does not working for second time and so on, so what i miss here? any help would be great. thank you.
DefaultTableModel model = new DefaultTableModel(data, column);
//model.fireTableDataChanged();
//table = new JTable(model)
table.setModel( model );
Don't create a new table change reset the model of your current table. The rest of the code in that method is not necessary either since you are not creating any new GUI components.
Also, never invoke a fireXXX method. That is the responsibility of the TableModel.
I have 2 Jcombo Boxs: which is combo1 and combo2
I choose combo1 and I can get information for combo2 but The problem is I can get informatiob for combo2 but it is not updated. I also try to use updata.UI() but it doesn't help.
This is the code in side
public void actionPerformed(ActionEvent e) {
JComboBox cb = (JComboBox)e.getSource();
String uname1 = (String)cb.getSelectedItem();
combo2 = update(uname1);
combo2.updateUI();
}
This is code inside update
protected JComboBox update(String name) {
JComboBox tmp = new JComboBox();
//Read Content from XML file (University is bigger than Year)
NodeList nList = doc.getElementsByTagName("University");
System.out.println("Inside Fn " + name);
for(int i = 0 ; i < nList.getLength();i++) {
Element el = (Element)nList.item(i);
if(name.contentEquals(el.getAttributeNode("name").getNodeValue()))
{
NodeList tmpyList = el.getElementsByTagName("Year");
for(int j = 0 ; j < tmpyList.getLength();j++)
{
Element yl = (Element)tmpyList.item(j);
System.out.println(yl.getAttribute("yr"));
tmp.addItem(yl.getAttribute("yr"));
}
}
}
return tmp; //Return ComboBox to combo2
}
Thank you for your kindness, I try to use your code but it is not work (It still not update), please help me
This is my constructor
public JFrameExample() {
String[] comboboxdefault = { "Select" };
JComboBox combo1 = Universitylist();
JComboBox combo2 = new JComboBox(comboboxdefault);
JComboBox combo3 = new JComboBox(comboboxdefault);
uList.addActionListener(this);
yList.addActionListener(this);
dList.addActionListener(this);
JPanel student_information = new JPanel(new GridLayout(0,1));
uList.setName("University List");
yList.setName("Year List");
// University List
student_information.add(combo1);
// Database Year List
student_information.add(combo2);
// Programme List
student_information.add(combo3);
//Add Components to this container, using the default FlowLayout.
add(student_information);
}
This is the combo2 Update it is return String Array
protected String[] updateyList(String name)
{
String[] tmp = null;
//Read from XML file
for(int i = 0 ; i < nList.getLength();i++) {
Element el = (Element)nList.item(i);
if(name.contentEquals(el.getAttributeNode("name").getNodeValue()))
{
NodeList tmpyList = el.getElementsByTagName("Year");
tmp = new String[tmpyList.getLength()];
for(int j = 0 ; j < tmpyList.getLength();j++)
{
Element yl = (Element)tmpyList.item(j);
//Add to String Array
tmp[j] = yl.getAttribute("yr");
}
}
}
return tmp;
}
In the Action Perform
public void actionPerformed(ActionEvent e) {
JComboBox cb = (JComboBox)e.getSource();
String uname1 = (String)cb.getSelectedItem();
System.out.println(cb.getName()); // To make sure I got the combo1.
try {
//I change to the model method
DefaultComboBoxModel model = new DefaultComboBoxModel( updateyList(uname1) );
System.out.println(model.getSize());
combo2 = new JComboBox(); // If I don't have this line it will throw error Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
combo2.setModel(model);
} catch (ParserConfigurationException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (SAXException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
And this is for creating GUI function
private static void createAndShowLoginGUI() {
//Create and set up the window.
JFrame frame = new JFrame("Login");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
JFrameExample newContentPane = new JFrameExample();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
This is main function
public static void main(String[] args)
{
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowLoginGUI();
}
});
}
I think I did something wrong but I don't know where
There is no need to use the updateUI() method.
If you want to change the data in the second combo box then you should change the model (DON'T create a new combo box):
comboBox2.setModel(...);
It will repaint itself automaitcally. You can create a DefaultComboBoxModel and add the data directly to it.
Edit:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class ComboBoxTwo extends JFrame implements ActionListener
{
private JComboBox mainComboBox;
private JComboBox subComboBox;
private Hashtable subItems = new Hashtable();
public ComboBoxTwo()
{
String[] items = { "Select Item", "Color", "Shape", "Fruit" };
mainComboBox = new JComboBox( items );
mainComboBox.addActionListener( this );
// prevent action events from being fired when the up/down arrow keys are used
mainComboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
getContentPane().add( mainComboBox, BorderLayout.WEST );
// Create sub combo box with multiple models
subComboBox = new JComboBox();
subComboBox.setPrototypeDisplayValue("XXXXXXXXXX"); // JDK1.4
getContentPane().add( subComboBox, BorderLayout.EAST );
String[] subItems1 = { "Select Color", "Red", "Blue", "Green" };
subItems.put(items[1], subItems1);
String[] subItems2 = { "Select Shape", "Circle", "Square", "Triangle" };
subItems.put(items[2], subItems2);
String[] subItems3 = { "Select Fruit", "Apple", "Orange", "Banana" };
subItems.put(items[3], subItems3);
// mainComboBox.setSelectedIndex(1);
}
public void actionPerformed(ActionEvent e)
{
String item = (String)mainComboBox.getSelectedItem();
Object o = subItems.get( item );
if (o == null)
{
subComboBox.setModel( new DefaultComboBoxModel() );
}
else
{
subComboBox.setModel( new DefaultComboBoxModel( (String[])o ) );
}
}
public static void main(String[] args)
{
JFrame frame = new ComboBoxTwo();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
}
As you do now, you recreate the combo box every time (by returning the tmp in update method). This as it seems is not reflecting in the UI and maybe others will post the reason. But if you can change to update the combo values (changing the model or deleting the current values and adding the new ones) instead of recreating, then the following post can help you Dynamically change JComboBox