Edit User information by jtable - java

I have a jtable that show a text file contain on own.
Each line in text file is a user record.
I add a edit button to edit each selected row on table.
I use this code, But i don't understand how to do this:
public class AllUser extends AbstractTableModel {
UserInformation uiS = new UserInformation();
String[] col = {"ID", "Fname", "Lname", "Gender", "Date"};
List<UserInformation> Udata = new ArrayList<UserInformation>();
public AllUser() {
BufferedReader br = null;
try {
FileReader fr = new FileReader("xxx.txt");
br = new BufferedReader(fr);
String line;
while ((line = br.readLine()) != null) {
if (line.trim().length() == 0) {
continue;
}
Udata.add(initializeUserInfos(line));
}
} catch (IOException e) {
} finally {
if (br != null) {
try {
br.close();
} catch (IOException ioe) {
}
}
}
}
private UserInformation initializeUserInfos(String str) {
UserInformation Uinit = new UserInformation();
String[] CellArray = str.split(" ");
Uinit.setID(CellArray[0]);
Uinit.setFname(CellArray[1]);
Uinit.setLname(CellArray[2]);
Uinit.setGender(CellArray[3]);
Uinit.setDate(CellArray[4]);
return Uinit;
}
#Override
public String getColumnName(int colu) {
return col[colu];
}
#Override
public int getRowCount() {
return Udata.size();
}
#Override
public int getColumnCount() {
return col.length;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
UserInformation uinfoS = Udata.get(rowIndex);
Object value = null;
switch (columnIndex) {
case 0:
value = uinfoS.getID();
break;
case 1:
value = uinfoS.getFname();
break;
case 2:
value = uinfoS.getLname();
break;
case 3:
value = uinfoS.getGender();
break;
case 4:
value = uinfoS.getDate();
break;
default:
value = "...";
}
return value;
}
#Override
public void setValueAt(Object value, int rowIndex, int columnIndex) {
UserInformation userInfo = new UserInformation();
switch (columnIndex) {
case 0:
userInfo.setID((String) value);
break;
case 1:
userInfo.setFname((String) value);
break;
case 2:
userInfo.setLname((String) value);
break;
case 3:
userInfo.setGender((String) value);
break;
case 4:
userInfo.setDate((String) value);
break;
}
}
public Object getSelectedMember(int row){
UserInformation userInf=new UserInformation();
Object fname=userInf.getFname();
Object lname=userInf.getLname();
Object gender=userInf.getGender();
Object date=userInf.getDate();
return // ?
}
}
I add This getSelectedMember(int row) method to do this, But incorrect!
public class UserPage extends JFrame implements ActionListener {
private AllUser userModel;
private JTable uTable;
private JButton editButton;
public UserPage() {
userModel = new AllUser();
uTable = new JTable(userModel);
add(new JScrollPane(uTable), BorderLayout.CENTER);
add(buttonPanels(), BorderLayout.PAGE_START);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(800, 600);
}
public final JPanel buttonPanels() {
JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
editButton=new JButton("Edit");
editButton.addActionListener(this);
buttonsPanel.add(editButton);
return buttonsPanel;
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()== editButton){
int selectedRow=uTable.getSelectedRow();
if(selectedRow>0){
editUser(selectedRow);
}
else{
JOptionPane.showMessageDialog(null, "Select a user");
}
}
}
public void editUser(int row){
userModel.getSelectedMember(row);
new NewUserFrame_Edit().setVisible(true);
}
}
UserInformation Class:
public class UserInformation {
private String Fname;
private String Lname;
private String ID;
private String Gender;
private String Date;
public String getFname() {
return Fname;
}
public void setFname(String fname) {
this.Fname = fname;
}
public String getLname() {
return Lname;
}
public void setLname(String lname) {
this.Lname = lname;
}
public String getID() {
return ID;
}
public void setID(String i_d) {
this.ID = i_d;
}
public String getGender() {
return Gender;
}
public void setGender(String gndr) {
this.Gender = gndr;
}
public String getDate() {
return Date;
}
public void setDate(String date) {
this.Date = date;
}
#Override
public String toString() {
return ID + " " + Fname + " "
+ Lname + " " + Gender + " " + Date + "\n";
}
}
Sorry for long code.

It sould be like this: when user click a row in jtable and clicked a new page should open and then each old data should insert in own textfiled
Add a MouseListener to the table.
On a double click you create a JDialog that contains the text fields required to edit the data.
You then get the data from the table using the getValueAt(...) method.
the user then edits the data in the text fields.
When the user clicks the "Save" button on the dialog you get the data from each text field and update the table using the setValueAt(...) method.
if you want to save the data in your text file you then need to recreate the enitre file by writing out all the data from the table.

Create an extra column in table and fill the cell value with Edit. Then render the Edit cell with appropriate TableCellRenderer . Add MouseListener to table. Get the row and column number of the cell clicked on table. If the cell clicked contains value Edit , retrieve value at each column of that row and display it in a Panel containing JTextFields . Show that Panel using JOptionpane or in a JDialog. Here is the brief code demo for achieving this task:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.Component;
import java.awt.Color;
import java.awt.Point;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;
import java.awt.Cursor;
import javax.swing.BorderFactory;
import javax.swing.border.BevelBorder;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.JScrollPane;
import javax.swing.JOptionPane;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.event.TableModelListener;
import javax.swing.event.TableModelEvent;
import javax.swing.table.TableModel;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.DefaultTableCellRenderer;
class TableRowEdit extends JFrame
{
private JTable table;
private JScrollPane jsPane;
private TableModel myModel;
private JPanel dialogPanel;
private JTextField tf[];
private JLabel lbl[];
public void prepareAndShowGUI()
{
myModel = new MyModel();
table = new JTable(myModel);
jsPane = new JScrollPane(table);
table.getColumnModel().getColumn(2).setCellRenderer(new LabelCellRenderer());
table.addMouseListener(new MyMouseAdapter());
getContentPane().add(jsPane);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
prepareDialogPanel();
pack();
setVisible(true);
}
private void prepareDialogPanel()
{
dialogPanel = new JPanel();
int col = table.getColumnCount() - 1;
dialogPanel.setLayout(new GridLayout(col,2));
tf = new JTextField[col];
lbl = new JLabel[col];
for (int i = 0; i < col; i++)
{
lbl[i] = new JLabel(table.getColumnName(i));
tf[i] = new JTextField(10);
dialogPanel.add(lbl[i]);
dialogPanel.add(tf[i]);
}
}
private void populateTextField(String[] s)
{
for (int i = 0 ; i < s.length ; i++ )
{
tf[i].setText(s[i]);
}
}
public class LabelCellRenderer extends DefaultTableCellRenderer
{
public Component getTableCellRendererComponent(JTable table,Object oValue, boolean isSelected, boolean hasFocus, int row, int column)
{
Component c = super.getTableCellRendererComponent(table, oValue,isSelected, hasFocus,row, column);
String value = (String)oValue;
JLabel label =(JLabel)c;
label.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
label.setBackground(Color.lightGray);
label.setHorizontalTextPosition(SwingUtilities.CENTER);
label.setHorizontalAlignment(SwingUtilities.CENTER);
label.setText(value);
return label;
}
}
private class MyMouseAdapter extends MouseAdapter
{
#Override
public void mousePressed(MouseEvent evt)
{
int x = evt.getX();
int y = evt.getY();
int row = table.rowAtPoint(new Point(x,y));
int col = table.columnAtPoint(new Point(x,y));
if (col == 2)
{
String arr[] = new String[table.getColumnCount() - 1];
for (int i = 0 ; i < arr.length ; i++)
{
arr[i] = (String)table.getValueAt(row,i);
}
populateTextField(arr);
JOptionPane.showMessageDialog(TableRowEdit.this,dialogPanel,"Information",JOptionPane.INFORMATION_MESSAGE);
//Write here the code to save changed values to file and update to JTable also.
}
}
}
private class MyModel extends AbstractTableModel
{
String[] columns = {
"Roll No.",
"Name",
"Action"
};
String[][] inData = {
{"1","Huge Jackman","Edit"},
{"2","Thomas Andrews","Edit"},
{"3","Shiney","Edit"}
};
#Override
public void setValueAt(Object value, int row, int col)
{
inData[row][col] = (String)value;
}
#Override
public Object getValueAt(int row, int col)
{
return inData[row][col];
}
#Override
public int getColumnCount()
{
return columns.length;
}
#Override
public int getRowCount()
{
return inData.length;
}
#Override
public String getColumnName(int col)
{
return columns[col];
}
}
public static void main(String st[])
{
SwingUtilities.invokeLater( new Runnable()
{
#Override
public void run()
{
TableRowEdit td = new TableRowEdit();
td.prepareAndShowGUI();
}
});
}
}

Related

How to update Jtable immediately or automtically when I press a button

I have created a JTable with some information about formula 1 racing car drivers. The below code is for the JTable
import java.awt.LayoutManager;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import java.awt.event.*;
public class Test1 extends JFrame implements ActionListener {
JButton button;
Test1() {
//setBounds(100, 100, 500, 400);
JFrame frame = new JFrame();
button = new JButton();
//button.setBounds(50, 50, 20, 10);s
button.setText("Random Race");
button.addActionListener(this);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTable table = new JTable(new Model1Data());
frame.setBounds(100, 100, 500, 400);
JPanel panel = new JPanel();
frame.add(panel);
panel.add(new JScrollPane(table));
panel.add(button);
//add(new J
frame.setVisible(true);
//this.add(button);
pack();
}
#Override
public void actionPerformed(ActionEvent e) {
Formula1ChampionsManager d= new Formula1ChampionsManager();
d.button();
}
}
This is the code for the Model1Data. This is the code for the table to update its cells.
import javax.swing.table.AbstractTableModel;
public class Model1Data extends AbstractTableModel implements ChampionsManager {
String colNames[] = { "Name", "Team", "No of first Places", "Total Points" };
Class<?> colClasses[] = { String.class, String.class, Integer.class, Integer.class };
public int getRowCount() {
return myDrivers.size();
}
public int getColumnCount() {
return colNames.length;
}
public Object getValueAt(int rowIndex, int columnIndex) {
if (columnIndex == 0) {
return myDrivers.get(rowIndex).getName();
}
if (columnIndex == 1) {
return myDrivers.get(rowIndex).getTeam();
}
if (columnIndex == 2) {
return myDrivers.get(rowIndex).getfirstPlace();
}
if (columnIndex == 3) {
return myDrivers.get(rowIndex).totalPoints();
}
return null;
}
public String getColumnName(int columnIndex) {
return colNames[columnIndex];
}
public Class<?> getColumnClass(int columnIndex) {
return colClasses[columnIndex];
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex == 0) {
myDrivers.get(rowIndex).setName((String) aValue);
}
if (columnIndex == 1) {
myDrivers.get(rowIndex).setTeam((String) aValue);
}
if (columnIndex == 2) {
myDrivers.get(rowIndex).setfirstPlace((Integer) aValue);
}
if (columnIndex == 3) {
myDrivers.get(rowIndex).settotalPoints((Integer) aValue);
}
//fireTableCellUpdated(rowIndex, columnIndex);
}
}
This what the table GUI looks like Table GUI. When I click the button the values for No of first places and Total Points are changed randomly. But the table doesn't get updated with the values. If I pull on the side of the frame it gets updated. How do I get it to update when I click the button?
The JTable listens for changes in the TableModel. Hence class AbstractTableModel has methods such as fireTableCellUpdated(rowIndex, columnIndex) (which you commented out in your code - why?). If you override method setValueAt then you need to call that method, otherwise the JTable will not update when its data is changed. I'm guessing that changing the size of the JFrame causes a repaint of the JTable which causes the JTable to reload the data from its model (but I could be wrong).
Your class Model1Data should extend DefaultTableModel, rather than AbstractTableModel, since that class already contains all the functionality you require. The only method that class Model1Data needs to override is getColumnClass (which it already does). You also need to override at least one constructor. Since you didn't post a minimal, reproducible example, I'm guessing that this constructor may be appropriate. Hence the code for class Model1Data should be:
public class Model1Data extends javax.swing.table.DefaultTableModel {
Class<?> colClasses[] = { String.class, String.class, Integer.class, Integer.class };
public Model1Data(Object[] columnNames, int rowCount) {
super(columnNames, rowCount);
}
public Class<?> getColumnClass(int columnIndex) {
return colClasses[columnIndex];
}
}
And in class Test1 (which does not need to extend JFrame, by the way) you can create the JTable like so:
JTable table = new JTable(new Model1Data(new String[]{ "Name", "Team", "No of first Places", "Total Points" }, 0));
Edit
Here's my take on what you are trying to do. The below code can be copied as is, compiled and run. Just click on the Random Race button and the data in the JTable will update.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
public class Test1 {
private JTable table;
private void buildAndDisplayGui() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTable(), BorderLayout.CENTER);
frame.add(createButtonsPanel(), BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JButton createButton(String text, int mnemonic, ActionListener listener) {
JButton button = new JButton(text);
button.setMnemonic(mnemonic);
button.addActionListener(listener);
return button;
}
private JPanel createButtonsPanel() {
JPanel buttonsPanel = new JPanel();
buttonsPanel.add(createButton("Random Race", KeyEvent.VK_R, this::randomRace));
return buttonsPanel;
}
private JScrollPane createTable() {
table = new JTable(new Model1Data());
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
JScrollPane scrollPane = new JScrollPane(table);
return scrollPane;
}
/**
* Simulates a race and randomly determines placings of the drivers and assigns appropriate
* points scores.
*
* #param event - encapsulates button press event
*/
private void randomRace(ActionEvent event) {
Formula1ChampionsManager.simulate();
TableModel tm = table.getModel();
if (tm instanceof Model1Data) {
Model1Data model = (Model1Data) tm;
model.setRowCount(0);
model.init();
}
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
new Test1().buildAndDisplayGui();
});
}
}
class Model1Data extends DefaultTableModel {
private static final String[] COLUMN_NAMES = {"Name", "Team", "No of first Places", "Total Points"};
public Model1Data() {
super(COLUMN_NAMES, 0);
init();
}
public void addDriver(F1Driver driver) {
addRow(new Object[]{driver.getName(),
driver.getTeam(),
driver.getFirstPlace(),
driver.getTotalPoints()});
}
public void init() {
Formula1ChampionsManager.getDrivers()
.stream()
.forEach(this::addDriver);
}
}
class Formula1ChampionsManager {
private static List<F1Driver> drivers;
static {
drivers = List.of(new F1Driver("Lewis Hamilton", F1Teams.MERCEDES),
new F1Driver("Max Verstappen",F1Teams.RED_BULL),
new F1Driver("Charles Leclerc",F1Teams.FERRARI),
new F1Driver("Lando Norris",F1Teams.MCLAREN),
new F1Driver("Fernando Alonso",F1Teams.ALPINE),
new F1Driver("Pierre Gasly",F1Teams.ALPHATAURI),
new F1Driver("Sebastian Vettel",F1Teams.ASTON_MARTIN),
new F1Driver("Nicholas Latifi",F1Teams.WILLIAMS),
new F1Driver("Valtteri Bottas",F1Teams.ALFA_ROMEO),
new F1Driver("Mick Schumacher",F1Teams.HAAS));
}
public static List<F1Driver> getDrivers() {
return drivers;
}
public static void simulate() {
List<F1Driver> result = new ArrayList<>(drivers);
Collections.shuffle(result);
F1Driver first = result.get(0);
first.update(F1Driver.FIRST);
F1Driver second = result.get(1);
second.update(F1Driver.SECOND);
F1Driver third = result.get(2);
third.update(F1Driver.THIRD);
F1Driver fourth = result.get(3);
fourth.update(F1Driver.FOURTH);
F1Driver fifth = result.get(4);
fifth.update(F1Driver.FIFTH);
F1Driver sixth = result.get(5);
sixth.update(F1Driver.SIXTH);
F1Driver seventh = result.get(6);
seventh.update(F1Driver.SEVENTH);
F1Driver eighth = result.get(7);
eighth.update(F1Driver.EIGHTH);
F1Driver ninth = result.get(8);
ninth.update(F1Driver.NINTH);
F1Driver tenth = result.get(9);
tenth.update(F1Driver.TENTH);
}
}
enum F1Teams {
MERCEDES("Mercedes"),
RED_BULL("Red Bull"),
FERRARI("Ferrari"),
MCLAREN("McLaren"),
ALPINE("Alpine"),
ALPHATAURI("AlphaTauri"),
ASTON_MARTIN("Aston Martin"),
WILLIAMS("Williams"),
ALFA_ROMEO("Alfa Romeo"),
HAAS("Haas");
private String name;
private F1Teams(String name) {
this.name = name;
}
#Override // java.lang.Enum
public String toString() {
return name;
}
}
class F1Driver {
public static final int FIRST = 25;
public static final int SECOND = 18;
public static final int THIRD = 15;
public static final int FOURTH = 12;
public static final int FIFTH = 10;
public static final int SIXTH = 8;
public static final int SEVENTH = 6;
public static final int EIGHTH = 4;
public static final int NINTH = 2;
public static final int TENTH = 1;
private String name;
private F1Teams team;
private int firstPlace;
private int totalPoints;
public F1Driver(String name, F1Teams team) {
this(name, team, 0, 0);
}
public F1Driver(String name, F1Teams team, int firstPlace, int totalPoints) {
Objects.requireNonNull(name, "Missing name.");
this.name = name;
this.team = team;
this.firstPlace = firstPlace;
this.totalPoints = totalPoints;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public F1Teams getTeam() {
return team;
}
public void setTeam(F1Teams team) {
this.team = team;
}
public int getFirstPlace() {
return firstPlace;
}
public void setFirstPlace(int firstPlace) {
this.firstPlace = firstPlace;
}
public int getTotalPoints() {
return totalPoints;
}
public void setTotalPoints(int totalPoints) {
this.totalPoints = totalPoints;
}
#Override // java.lang.Object
public boolean equals(Object obj) {
boolean equal = this == obj;
if (!equal) {
if (obj instanceof F1Driver) {
F1Driver other = (F1Driver) obj;
equal = name != null &&
name.equals(other.name) &&
team == other.team;
}
}
return equal;
}
#Override // java.lang.Object
public int hashCode() {
return (String.valueOf(name) + String.valueOf(team)).hashCode();
}
#Override // java.lang.Object
public String toString() {
return String.format("%s [%s] %d [%d]", name, team, totalPoints, firstPlace);
}
public void update(int points) {
totalPoints += points;
if (points == FIRST) {
firstPlace++;
}
}
}
Here's how it looks when I run the above code.

Dynamic JTextField creation in JFrame on event

I am dynamically creating JTextField based on click event on '+' button. Below is screen shot.
The problem is when I click '+' button, fields created but not shown on JFrame. When I put the cursor on next row under 'item Name', text field becomes visible.
Where is the problem?
Below is my code.
CreateBill()
{
jf = new JFrame("Create Bill");
jf.getContentPane().setLayout(null);
jf.setExtendedState(JFrame.MAXIMIZED_BOTH);
jf.setBounds(0, 0, d1.width, d1.height);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
createRow(); // This will create first row by default.
jf.pack();
jf.setVisible(true);
}
private void createRow() {
textField = new JTextField();
textField.setToolTipText("item name");
textField.setBounds(143, 46+j, 288, 20);
textField.setColumns(10);
textField.getDocument().addDocumentListener(new DocumentListener()
{
#Override
public void insertUpdate(DocumentEvent e) {
updatePrice();
}
#Override
public void removeUpdate(DocumentEvent e) {
}
#Override
public void changedUpdate(DocumentEvent e) {
updatePrice();
}
});
AutoCompleteDecorator.decorate(textField, names, true);
jf.getContentPane().add(comboComplete);
jf.getContentPane().add(textField);
comboComplete.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e)
{
String ItemSel = textField.getText().trim();
for(Item s:items)
{
if(s.getItemName().equals(ItemSel))
{
textField_1.setText(String.valueOf(s.getUnitPrice()));
}
}
}
});
textFields.add(textField);
textField_1 = new JTextField();
textField_1.setEditable(false);
textField_1.setBounds(639, 46+j, 175, 20);
jf.getContentPane().add(textField_1);
textField_1.setColumns(10);
qty = new JTextField();
qty.setBounds(455, 46+j, 156, 20);
jf.getContentPane().add(qty);
qty.setColumns(10);
qty.getDocument().addDocumentListener(new DocumentListener()
{
#Override
public void insertUpdate(DocumentEvent e) {
getTotal();
}
#Override
public void removeUpdate(DocumentEvent e) {
}
#Override
public void changedUpdate(DocumentEvent e) {
getTotal();
}
});
textFields.add(qty);
textFields.add(textField_1);
textField_3 = new JTextField();
textField_3.setEditable(false);
textField_3.setBounds(1038, 46+j, 156, 20);
jf.getContentPane().add(textField_3);
textField_3.setColumns(10);
textFields.add(textField_3);
JButton button = new JButton("+");
button.setBounds(1235, 45+j, 89, 23);
jf.getContentPane().add(button);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("value of J"+j);
createRow(); // after pressing '+' button i am calling same method again. by changing value of j.
}
});
j=j+22;
jf.setVisible(true);
}
I want my all 4 text fields appear simultaneously.
You need to call repaint() on the container after adding a component to it. You also should call revalidate() too, before calling repaint, since this tells the layout managers to layout the new component, but you're using null layouts, something that you really want to avoid doing.
So my suggestion is to either 1) use nested JPanels with appropriate layout managers, and call revalidate and repaint on your containers after adding or removing components, or 2) yeah, use a Cardlayout to swap views as Andrew Thompson astutely recommends. You can have your second JPanel have a JTextField that uses the same Document as the previous JPanel, so it looks like both are using the same JTextField (as the top JTextField).
On looking further at your images, I have to wonder if a JTable might be an even better solution overall. And yeah, after you start using the layout managers, do also call pack() on your top level window after adding all components and before setting it visible.
For an example of a JTable implementation of this, something along the lines of...
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
#SuppressWarnings("serial")
public class CreateRowGui extends JPanel {
private static final Item[] ITEMS = {
new Item("Light Bulb", 2.00),
new Item("Toilet Paper", 3.00),
new Item("Toothpaste", 1.50),
new Item("Aspirin", 3.75) };
private ItemTableModel tableModel = new ItemTableModel();
private JTable table = new JTable(tableModel);
private AddRowAction addRowAction = new AddRowAction("Add Row", KeyEvent.VK_A);
public CreateRowGui() {
TableCellRenderer moneyRenderer = new DefaultTableCellRenderer() {
private NumberFormat currFormat = NumberFormat.getCurrencyInstance();
#Override
protected void setValue(Object value) {
if (value != null) {
value = currFormat.format(value);
}
super.setValue(value);
}
};
table.getColumnModel().getColumn(2).setCellRenderer(moneyRenderer);
table.getColumnModel().getColumn(3).setCellRenderer(moneyRenderer);
JPanel btnPanel = new JPanel();
btnPanel.add(new JButton(addRowAction));
btnPanel.add(new JButton("Remove Row")); // TODO: need Action for this
setLayout(new BorderLayout());
add(new JScrollPane(table));
add(btnPanel, BorderLayout.PAGE_END);
}
class AddRowAction extends AbstractAction {
private NewRowPanel newRowPanel = new NewRowPanel(ITEMS);
public AddRowAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
newRowPanel.reset();
int reply = JOptionPane.showConfirmDialog(table,
newRowPanel.getMainPanel(),
"Select Item and Quantity",
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.PLAIN_MESSAGE);
if (reply == JOptionPane.OK_OPTION) {
Item item = newRowPanel.getSelectedItem();
int quantity = newRowPanel.getQuantity();
tableModel.addRow(item, quantity);
}
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("CreateRowGui");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new CreateRowGui());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class NewRowPanel {
private JPanel mainPanel = new JPanel();
private JComboBox<Item> itemsCombo;
private JSpinner quantitySpinner = new JSpinner(new SpinnerNumberModel(0, 0, 20, 1));
#SuppressWarnings("serial")
public NewRowPanel(Item[] items) {
itemsCombo = new JComboBox<>(items);
itemsCombo.setRenderer(new DefaultListCellRenderer(){
#Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected,
boolean cellHasFocus) {
if (value != null) {
value = ((Item) value).getName();
} else {
value = "";
}
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
}
});
mainPanel.add(new JLabel("Item:"));
mainPanel.add(itemsCombo);
mainPanel.add(Box.createHorizontalStrut(15));
mainPanel.add(new JLabel("Quantity"));
mainPanel.add(quantitySpinner);
}
public void reset() {
itemsCombo.setSelectedIndex(-1);
quantitySpinner.setValue(0);
}
public JPanel getMainPanel() {
return mainPanel;
}
public Item getSelectedItem() {
return (Item) itemsCombo.getSelectedItem();
}
public int getQuantity() {
return (int) quantitySpinner.getValue();
}
}
class ItemTableModel extends AbstractTableModel {
private static final String[] COL_NAMES = { "Item Name", "Quantity", "Unit Price", "Total" };
private static final long serialVersionUID = 1L;
private List<ItemWithCount> itemsWithCount = new ArrayList<>();
#Override
public int getColumnCount() {
return 4;
}
#Override
public int getRowCount() {
return itemsWithCount.size();
}
#Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return super.getColumnClass(columnIndex);
case 1:
return Integer.class;
case 2:
case 3:
return Double.class;
}
return super.getColumnClass(columnIndex);
}
#Override
public String getColumnName(int column) {
return COL_NAMES[column];
}
#Override
public Object getValueAt(int row, int column) {
ItemWithCount itemWithCount = itemsWithCount.get(row);
switch (column) {
case 0:
return itemWithCount.getItem().getName();
case 1:
return itemWithCount.getCount();
case 2:
return itemWithCount.getItem().getUnitPrice();
case 3:
return itemWithCount.getCount() * itemWithCount.getItem().getUnitPrice();
}
return null;
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
ItemWithCount itemWithCount = itemsWithCount.get(rowIndex);
switch (columnIndex) {
case 1:
itemWithCount.setCount((int) aValue);
fireTableRowsUpdated(rowIndex, rowIndex);
break;
default:
break;
}
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 0 || columnIndex == 1;
}
public void addRow(Item item, int quantity) {
ItemWithCount itemWithCount = new ItemWithCount(item, quantity);
itemsWithCount.add(itemWithCount);
int row = itemsWithCount.size() - 1;
fireTableRowsInserted(row, row);
}
private class ItemWithCount {
private Item item;
private int count;
public ItemWithCount(Item item, int count) {
this.item = item;
this.count = count;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public Item getItem() {
return item;
}
}
}
class Item {
private String name;
private double unitPrice;
public Item(String name, double unitPrice) {
this.name = name;
this.unitPrice = unitPrice;
}
public String getName() {
return name;
}
public double getUnitPrice() {
return unitPrice;
}
public void setUnitPrice(double unitPrice) {
this.unitPrice = unitPrice;
}
#Override
public String toString() {
return "Item [name=" + name + ", unitPrice=" + unitPrice + "]";
}
}

Jtable need help loading columns from text file [JAVA]

I am trying to get the following text file to come up into this 'Jtable'.. I’m having a hard time getting all the data/columns to appear.. I know that it’s something easy I’m just new to java so any help would be appreciated.
My text file:
1;2;3;4;5;6
1b;2b;3b;4b;5b;6b
1C;2C;3C;4C;5C;6C
My code so far:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
public class JtableTest {
public static void main(String[] args) throws Exception{
Runnable r = new Runnable() {
public void run() {
new JtableTest ().createUI();
}
};
EventQueue.invokeLater(r);
}
private void createUI() {
try {
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
JTable table = new JTable();
String readLine = null;
// DatabaseTableModel tableModel = new DatabaseTableModel();
File file = new File ("JtableTest.txt");
FileReader reader = new FileReader(file);
BufferedReader bufReader = new BufferedReader(reader);//Need to close this
List<Dentry> studentList = new ArrayList<Dentry>();
while ((readLine = bufReader.readLine()) != null) {
String[] splitData = readLine.split(";");
Dentry dentry = new Dentry();
dentry.setName(splitData[0]);
dentry.setNumbers(Arrays.copyOfRange(splitData, 1, splitData.length));
studentList.add(dentry);
}
DatabaseTableModel tableModel = new DatabaseTableModel();
tableModel.setList(studentList);////////////
table.setModel(tableModel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(table));
frame.setTitle("File to JTable");
frame.pack();
frame.setVisible(true);
} catch(IOException ex) {}
}
class Dentry {
private String name;
private String[] number;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber(int index) {
String value = null;
if (index >= 0 && index < number.length) {
value = number[index];
}
return value;
}
public void setNumbers(String... number) {
this.number = number;
class DatabaseTableModel extends AbstractTableModel {
private List<Dentry> list = new ArrayList<Dentry>();
private String[] columnNames = {"1", "2", "3", "4", "5", "6"};
public void setList(List<Dentry> list) {
this.list = list;
fireTableDataChanged();
}
#Override
public String getColumnName(int column) {
return columnNames[column];
}
public int getRowCount() {
return list.size();
}
public int getColumnCount() {
return columnNames.length;
}
public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0:
return list.get(rowIndex).getName();
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
return list.get(rowIndex).getNumber(columnIndex);
default:
return null;
}
}
}
}
}
}
Your data contains 6 columns, but your pojo only allows for 2 (the name and a number).
Start by changing your pojo to support multiple columns
class Dentry {
private String name;
private String[] number;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber(int index) {
String value = null;
if (index >= 0 && index < number.length) {
value = number[index];
}
return value;
}
public void setNumbers(String... number) {
this.number = number;
}
}
All I've done here is allowed your to apply a variable length of numbers and provided a convenience method to access them.
Next, you need to change the way you're loading the data so you can supply all the other elements from the line in the file to your pojo
List<Dentry> studentList = new ArrayList<Dentry>();
while ((readLine = bufReader.readLine()) != null) {
String[] splitData = readLine.split(";");
Dentry dentry = new Dentry();
dentry.setName(splitData[0]);
dentry.setNumbers(Arrays.copyOfRange(splitData, 1, splitData.length));
studentList.add(dentry);
}
This just creates a copy of the splitData from the second element (index 1) to the last element inclusive.
I also changed the getVaueAt method to make it simpler to get the number for the specified column...
public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0:
return list.get(rowIndex).getName();
case 1:
case 2:
case 3:
case 4:
case 5:
return list.get(rowIndex).getNumber(columnIndex - 1);
default:
return null;
}
}
You could just use default as the pojo checks the range of the index, but this is a nice demonstration of the fall through nature of a switch statement.

java: Get row data from popupmenu actionListener event

I'm having a little scenario here that maybe a duplicate. I have JTable where i show some data, i have a mouselistener that listens for right clicks on the table and displays a popup menu with one menuitem. My goal is that when the user clicks the menuitem, i get the values from the table and feed them into a custom dialog which has some fill in fields, so that the user doesn't have to feed the whole dialog by hand since i will feed the dialog with the values selected on the table. but my problem is that the menuitem actionevent doesn't have a way of getting the point so that i can use table.getRowAt(). i have read another comment (check here https://stackoverflow.com/a/4122082/1788917) where i have been told that i can save the row number in a variable that can then be accessed by the actionlistener for the menuitem.
i want it to look like this
theScrollPane.getViewport().add(myJTable, null);
JMenuItem menuItem = new JMenuItem(clickMe);
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
menuItemActionPerformed(e);
}
});
MouseListener popupListener = new PopupListener();
popupMenu.add(menuItem);
myJTable.addMouseListener(popupListener);
protected void menuItemActionPerformed (ActionEvent e) {
// what to do here to get the table row data
// and send it to my custom dialog via it's constructor ???
}
// a simple nested class for the popup
class PopupListener extends MouseAdapter {
public void mousePressed(MouseEvent e) {
int row = myJTable.rowAtPoint(e.getPoint());
int selectedRow = myJTable.getSelectedRow();
// just to make sure the popup appears only where the row is
// selected
if (row == selectedRow) {
showPopup(e);
}
}
public void mouseReleased(MouseEvent e) {
int row = myJTable.rowAtPoint(e.getPoint());
int selectedRow = myJTable.getSelectedRow();
if (row == selectedRow) {
showPopup(e);
}
}
private void showPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
popupMenu.show(e.getComponent(), e.getX(), e.getY());
}
}
}
so my question is, is saving the row number the only way that i can do this or is there a better way?
i have read another comment (check here https://stackoverflow.com/a/4122082/1788917) where i have been told that i can save the row number in a variable
You read the wrong comment.
If you read the answer above that link (ie. the one with 7 votes) you will see the solution is to select the row you clicked on BEFORE showing the popup menu. Then in your menu item Action you can reference
table.getSelectedRow();
I have tried your case referring to this case and I am able to get the row and show it in a JDialog. I just modified my old code to do this. I haven't thoroughly tested.
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
public class AllTableExample {
private JTabbedPane tabbedPane;
private JTable allTable;
private AllTableModel allTableModel;
public AllTableExample() {
List<TableData> data = new ArrayList<TableData>();
data.add(new TableData("John1", "A", "Maths", "Hellen1"));
data.add(new TableData("John2", "A", "Maths", "Hellen2"));
data.add(new TableData("John3", "A", "Maths", "Hellen3"));
data.add(new TableData("John4", "A", "Maths", "Hellen4"));
data.add(new TableData("John5", "A", "Maths", "Hellen5"));
allTableModel = new AllTableModel(data);
}
public void createUI() {
JFrame frame = new JFrame();
tabbedPane = new JTabbedPane();
tabbedPane.add("All", getAllTablePanel());
frame.add(tabbedPane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Table Model Example.");
frame.pack();
frame.setVisible(true);
}
private JPanel getAllTablePanel() {
JPanel panel = new JPanel();
allTable = new JTable(allTableModel);
JScrollPane scroll = new JScrollPane(allTable);
panel.add(scroll);
allTable.addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent e) {
int r = allTable.rowAtPoint(e.getPoint());
if (r >= 0 && r < allTable.getRowCount()) {
allTable.setRowSelectionInterval(r, r);
} else {
allTable.clearSelection();
}
int rowindex = allTable.getSelectedRow();
if (rowindex < 0)
return;
if (e.getComponent() instanceof JTable) {
JDialog dialog = new JDialog();
int selectedRow = allTable.getSelectedRow();
dialog.setTitle("Edit Row: " + selectedRow);
TableData data = ((AllTableModel) allTable.getModel()).getTableData().get(selectedRow);
List<TableData> tempData = new ArrayList<TableData>();
tempData.add(data);
AllTableModel tempModel = new AllTableModel(tempData);
JTable table = new JTable(tempModel);
dialog.add(new JScrollPane(table));
dialog.setVisible(true);
}
}
});
return panel;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
new AllTableExample().createUI();
}
};
EventQueue.invokeLater(r);
}
}
class AllTableModel extends AbstractTableModel {
List<TableData> tableData = new ArrayList<TableData>();
Object[] columnNames = {"Name", "Grade", "Subject", "Staff"};
public AllTableModel(List<TableData> data) {
tableData = data;
}
public List<TableData> getTableData() {
return tableData;
}
#Override
public String getColumnName(int column) {
return columnNames[column].toString();
}
#Override
public int getColumnCount() {
return columnNames.length;
}
#Override
public int getRowCount() {
return tableData.size();
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
TableData data = tableData.get(rowIndex);
switch (columnIndex) {
case 0:
return data.getName();
case 1:
return data.getGrade();
case 2:
return data.getSubject();
case 3:
return data.getStaff();
default:
return null;
}
}
}
class TableData {
private String name;
private String grade;
private String subject;
private String staff;
public TableData(String name, String grade, String subject, String staff) {
super();
this.name = name;
this.grade = grade;
this.subject = subject;
this.staff = staff;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getStaff() {
return staff;
}
public void setStaff(String staff) {
this.staff = staff;
}
}
Note: Store the row number of the table on which the pop-up opened such that after the changes in the popup dialog we have to update the original row.

JTable in JScrollPane not displaying properly in Mac OS X

The following code does not work on Mac OS X 10.6.8 but does on everything else I test, Mac OS X Lion and Windows 7. The obvious explanation would be differences in Apple's java. The table data does not show properly, if at all, on Mac. Here is the code
package com.dramble.dance;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.List;
public class TableDemo extends JPanel {
public TableDemo() {
super(new GridLayout(1,0));
TableModel tableModel = new TableModel();
JTable table = new JTable(tableModel);
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane);
for(int i = 0 ; i <= 1900 ; i ++) {
DataRow row = new DataRow(i,"Firstname"+i,"Lastname"+i);
tableModel.appendRow(row);
tableModel.fireTableRowsInserted(i, i);
}
}
private static void createAndShowGUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TableDemo newContentPane = new TableDemo();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private class DataRow {
private String fname, lname;
private Integer id;
public String getFname() {
return fname;
}
public String getLname() {
return lname;
}
public Integer getId() {
return id;
}
public DataRow(Integer id, String fname, String lname) {
super();
this.fname = fname;
this.lname = lname;
this.id = id;
}
}
private class TableModel extends AbstractTableModel {
List<DataRow> data;
private String[] columnNames = {"ID #","First Name","Last Name"};
private Class[] columnTypes = {int.class, String.class, String.class};
public TableModel() {
this.data = new ArrayList<DataRow>();
}
#Override
public int getColumnCount() {
return columnNames.length;
}
#Override
public String getColumnName(int col) {
return columnNames[col];
}
#Override
public int getRowCount() {
return this.data.size();
}
#Override
public Object getValueAt(int row, int col) {
DataRow dataRow = this.data.get(row);
Object returnValue = null;
switch (col) {
case 0:
returnValue = dataRow.getId();
break;
case 1:
returnValue = dataRow.getFname();
break;
case 2:
returnValue = dataRow.getLname();
break;
}
return returnValue;
}
public void appendRow(DataRow row) {
this.data.add(row);
}
#Override
public boolean isCellEditable(int rowIndex, int vColIndex) {
return false;
}
#Override
public Class getColumnClass(int col) {
return columnTypes[col];
}
}
}
Here is an image of the expected behavior as exhibited in Windows
Here is the same code on Mac OS X 10.6.8
The problem lies in the AbstractTableModel, which came as a surprise to me for some reason, I figured it would be EDT and thread related for sure. The problem is in my array for the columnTypes and using int.class. Changing this to Integer.class fixed my issue.
Absent a complete example, it's hard to guess. What you have looks OK, but two thing stand out:
I'm wary of frame.setContentPane(newContentPane), which replaces the frame's content pane with your TableDemo. As TableDemo is a JPanel, it inherits a UI delegate that varies by platform. Instead, consider frame.add(newContentPane), which forwards to the content pane.
Your appendRowData() method in DanceTableModel should fireTableRowsInserted(), so callers can't forget to do so.

Categories