I am having a small problem of showing results from my database to a JTable. It displays all of the data correctly, but at the moment it is showing "true" or "false" for boolean.
I know it must be because I am using getString, but does anyone know what to use in order to change it to a checkbox instead?
Current JTable:
My Database:
Code:
connection con=new connection();
Connection getcon=null;
Vector col = new Vector();
Vector dat= new Vector();
ResultSet rs = null;
try{
getcon = con.creatConnection();
col.add("Fanta");
col.add("Crisps");
col.add("Beer");
col.add("Wine");// create income table default colum names and sore it
col.add("Water");
col.add("Seat Row");
col.add("Seat");
col.add("Total Cost");
rs=getcon.createStatement().executeQuery("select*from orders"); //getting all the information from the table
dat.clear();
while(rs.next()){// if record source avilable
Vector v =new Vector();
v.add(rs.getString("Fanta").trim());
v.add(rs.getString("Crisps").trim());
v.add(rs.getString("Beer").trim());
v.add(rs.getString("Wine").trim());// getting income values from database and store in dat
v.add(rs.getString("Water").trim());
v.add(rs.getString("SeatRow").trim());
v.add(rs.getString("Seat").trim());
v.add(rs.getString("TotalCost").trim());
dat.add(v);
}
orderResults.setModel(new DefaultTableModel(dat, col));
}
catch(Exception ex){
JOptionPane.showMessageDialog(null, ex.getMessage());
}
First you have to save data as a Boolean in your model. So you should use this rs.getBoolean("Fanta") instead of rs.getString("Fanta").trim().
Second, you have to override a public Class getColumnClass(int column) method from your JTable. Your code could look like this:
JTable orderResults = new JTable() {
#Override
public Class getColumnClass(int column) {
// first 5 columns will be represented as an checkbox
if(column <= 4){
return Boolean.class;
}
// rest of them as a text
return String.class;
}
};
Related
Good afternoon guys, i'm trying to learn java programming and then i'm encountering some problem that i don't know why with my code when I'm learning about JTable.
So, what I'm trying to do is when i double clicked the row in JTable named TableGejala, the row that i double clicked will transfered into the other JTable named TableAturan and after that the row that i double clicked in TableGejala will be removed. For the part of transferring row from TableGejala to TableAturan successfully transferred when i double clicked the row, but it doesn't delete the correct row in TableGejala. Instead of deleting the row that i clicked, it delete the row below it.
For more details, this is my code to create TableGejala :
private void getTableGejala() {
while(tabel2.getRowCount() > 0){
for(int i=0;i < tabel2.getRowCount();i++){
tabel2.removeRow(i);
}
}
tabel2.addColumn("ID Gejala");
tabel2.addColumn("Nama Gejala");
TabelGejala.setModel(tabel2);
TabelGejala.setAutoResizeMode(TabelGejala.AUTO_RESIZE_ALL_COLUMNS);
}
And then this is my code to get data for my table from MySQL :
private void loadDataGejala(Boolean baru){
tabel2.getDataVector().removeAllElements();
try {
java.sql.Connection konek = (Connection) Koneksi.KoneksiDB.getConnection();
java.sql.Statement konek_statement = konek.createStatement();
String query_bukaTabel = "";
if(baru){
query_bukaTabel = "select id_gejala,nama_gejala from gejala";
}
else{
String idPkt = FieldID.getText();
query_bukaTabel = "select gejala.id_gejala,gejala.nama_gejala from gejala where gejala.id_gejala not in(select id_gejala from aturan2 where id_penyakit='"+idPkt+"')";
}
java.sql.ResultSet line_result = konek_statement.executeQuery(query_bukaTabel);
while (line_result.next()) {
Object[] getO = new Object[2];
getO[0] = line_result.getString("id_gejala");
getO[1] = line_result.getString("nama_gejala");
tabel2.addRow(getO);
}
line_result.close();
konek_statement.close();
}catch (Exception e) {}
}
This is my code to transfer the row and delete the row :
private void TabelGejalaMousePressed(java.awt.event.MouseEvent evt) {
if (evt.getClickCount()>=2){
int col = 0;
int row = 0;
row = TabelGejala.rowAtPoint(evt.getPoint());
col = TabelGejala.columnAtPoint(evt.getPoint());
String col1 = (String)TabelGejala.getValueAt(row, 0);
String col2 = (String)TabelGejala.getValueAt(row, 1);
DefaultTableModel model = (DefaultTableModel) TabelAturan.getModel();
DefaultTableModel old = (DefaultTableModel) TabelGejala.getModel();
old.removeRow(row);
model.addRow(new Object[]{col1, col2, 0});
TabelAturan.requestFocus();
TabelAturan.setRowSelectionInterval(TabelAturan.getRowCount()-1,TabelAturan.getRowCount()-1);
TabelAturan.editCellAt(TabelAturan.getRowCount()-1,2);
}
}
And this is the screenshot of my problem :
Before Double Clicked
After Double Clicked
Which part that makes my output get the wrong row to be deleted? please help me, and thank you in advance for any helps, even for reading my question :)
Firstly disable cell editable property in your first table(TabelGejala) to ensure proper deleting of row. I achieved this using the following code :-
//instance table model
DefaultTableModel tableModel = new DefaultTableModel(new Object[][]{},
new String[]{
"ID Gejala", "Nama Gejala"
}) {
#Override
public boolean isCellEditable(int row, int column) {
//all cells false
return false;
}
};
TabelGejala.setModel(tableModel);
then use jtable.getselectedrow() and jtable.getselectedcolumn() to get values from table. after addition of desired values to second table, simply delete the selected row. here is the code, derived from your code :-
private void TabelGejalaMousePressed(java.awt.event.MouseEvent evt) {
// TODO add your handling code here:
if (evt.getClickCount() >= 2) {
DefaultTableModel model = (DefaultTableModel) TabelAturan.getModel();
DefaultTableModel old = (DefaultTableModel) TabelGejala.getModel();
model.addRow(new Object[]{TabelGejala.getValueAt(TabelGejala.getSelectedRow(), 0), TabelGejala.getValueAt(TabelGejala.getSelectedRow(), 1), 0});
old.removeRow(TabelGejala.getSelectedRow());
TabelAturan.requestFocus();
TabelAturan.setRowSelectionInterval(TabelAturan.getRowCount() - 1, TabelAturan.getRowCount() - 1);
TabelAturan.editCellAt(TabelAturan.getRowCount() - 1, 2);
}
}
I have a jtable I populated from a database , but I want to enable or gray out some of this jtable lines ( lines that exist in another table of the same database) for the user cannot check the checkbox of these lines, but the rest of the lines ( lines that do not exist in this table ) can always be checked.
for (int m = 0; m < tb_doublon.getRowCount(); m++) {
Statement statdouble=null;
ResultSet rsdouble=null;
//I get the value of the cell of the column 1 :id, line : i
String id = (String)tb_doublon.getValueAt(m, 1);
String cli = (String)tb_doublon.getValueAt(m, 2);
//i browse the other table to enable or gray out the lines existing in that table with th id
String doubleexistant ="select * from doublon where id='"+id+"' and cli='"+cli+"'" ;
statdouble = conn.createStatement();
rsdouble = statdouble.executeQuery(doubleexistant);
while (rsdouble.next()) {
//i think this is here that i must enable or gray out the lines but i don't know how !!!!<br>
}
}
sir, you can create your checkboxes in an array for accessing them easier.
JCheckBox [] checkboxes= new JCheckBox[WIDTH];
if you found 2nd index to be duplicate you can simply disable the 2nd checkbox in your array
checkboxes[1].setEnabled(false);
Coloring a row can be perform using a modified TableCellRenderer. I have created a customized TableCellRenderer as follows.
ColorTableRenderer.java
It can add rows to be mark as gray, and clear all marked rows.
public class ColorTableRenderer extends DefaultTableCellRenderer {
//contains row indexes which need to color
private final List<Integer> colorIndexes = new ArrayList<>();
//add new index to show as color
public void addColorIndex(Integer index) {
colorIndexes.add(index);
}
//clear all color indexes
public void clearColorIndexes() {
colorIndexes.clear();
}
private boolean isColorIndex(Integer index) {
return colorIndexes.contains(index);
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (isColorIndex(row)) {//check if marked as colored
component.setBackground(Color.LIGHT_GRAY);//highlight color
} else {
component.setBackground(Color.WHITE);//other color
}
return component;
}
}
Using the ColorTableRenderer
Set the ColorTableRenderer to the table using one of following methods.
ColorTableRenderer renderer = new ColorTableRenderer();
//set TableCellRenderer into a specified JTable column class
table.setDefaultRenderer(String[].class, renderer);
//or, set TableCellRenderer into a specified JTable column
table.getColumnModel().getColumn(columnIndex).setCellRenderer(renderer);
Considering your code, you can add following modifications to make selected row color.
renderer.clearColorIndexes();
for (int m = 0; m < tb_doublon.getRowCount(); m++) {
Statement statdouble = null;
ResultSet rsdouble = null;
//I get the value of the cell of the column 1 :id, line : i
String id = (String) tb_doublon.getValueAt(m, 1);
String cli = (String) tb_doublon.getValueAt(m, 2);
//i browse the other table to enable or gray out the lines existing in that table with th id
String doubleexistant = "select * from doublon where id='" + id + "' and cli='" + cli + "'";
statdouble = conn.createStatement();
rsdouble = statdouble.executeQuery(doubleexistant);
while (rsdouble.next()) {
renderer.addColorIndex(m);
}
}
This is my tested screen-shot
Currently, this is my main screen:
()
I have 2 files: “patient.txt” and “treatment.txt” which hold records of multiple patients and treatments.
What I’m trying to do is to display all of those records in a nice JTable whenever I click “Display Treatments” or “Display Patients”, in a screen like so:
I am using an MVC model for this Hospital Management System (with HMSGUIModel.java, HMSGUIView.java, HMSGUIController.java, HMSGUIInterface.java files), and add records using the following code:
FileWriter tfw = new FileWriter(file.getAbsoluteFile(), true);
BufferedWriter tbw = new BufferedWriter(tfw);
tbw.write(this.view.gettNumber() + "," + this.view.gettName() + "," + this.view.gettDoctor() + "," + this.view.gettRoom());
tbw.newLine();
tbw.flush();
JOptionPane.showMessageDialog(null, "Successfully added treatment!"); }
Please help on how I can add a reader as well, to display all the records from the text file to a table?
Many thanks in advance!!
Keeping in line with your MVC, you could create a TableModel which knew how to read a give patient record.
Personally though, I'd prefer to separate the management of the patient data from the view, so the view didn't care about where the data came from.
To this end, I would start by creating a Patient object and a Treatment object, these would hold the data in a self contained entity, making the management simpler...
You would need to read this data in and parse the results...
List<Treatment> treatments = new ArrayList<Treatment>(25);
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String text = null;
while ((text = br.readline()) != null) {
String parts[] = text.split(",");
Treatmeant treament = new Treatment(parts[0],
parts[1],
parts[2],
parts[3]);
treatments.add(treament);
}
} // Handle exception as required...
I'd wrap this into a readTreatments method in some utility class to make it easier to use...
Around about here, I'd be considering using a stand alone database or even an XML document, but that's just me.
Once you have this, you can design a TableModel to support it...
public class TreatmentTableModel extends AbstractTableModel {
protected static final String[] COUMN_NAMES = {
"Treatment-Number",
"Treatment-Name",
"Doctor-in-charge",
"Room-No",
};
protected static final Class[] COLUMN_CLASSES = new Class[]{
Integer.class,
String.class,
Doctor.class,
Integer.class,
};
private List<Treatment> treatments;
public TreatmentTableModel() {
this.treatments = new ArrayList<>();
}
public TreatmentTableModel(List<Treatment> treatments) {
this.treatments = new ArrayList<>(treatments);
}
#Override
public int getRowCount() {
return treatments.size();
}
#Override
public int getColumnCount() {
return 4;
}
#Override
public String getColumnName(int column) {
return COUMN_NAMES[column];
}
#Override
public Class<?> getColumnClass(int columnIndex) {
return COLUMN_CLASSES[columnIndex];
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Treatment treatment = treatments.get(rowIndex);
Object value = null;
switch (columnIndex) {
case 0:
value = treatment.getNumber();
break;
case 1:
value = treatment.getName();
break;
case 2:
value = treatment.getDoctor();
break;
case 3:
value = treatment.getRoomNumber();
break;
}
return value;
}
}
Then you simply apply it to what ever JTable you need...
private JTable treatments;
//...
treatments = new JTable(new TreatmentTableModel());
add(new JScrollPane(treatments));
Then, we you need to, you would load the List of Treatments and apply it to the table...
File file = new File("...");
treatments.setModel(new TreatmentTableModel(TreatmentUtilities.readTreatments(file)));
Depending on your needs for the table, you can look at using the DefaultTableModel and populating your data using that model. The downside to that is, you may want special capability from your table, like not being able to edit cells, store more than strings, etc... in which case you might look in to extending AbstractTableModel and defining your own behavior for the model.
A simple thing to do would be to start with the default model and expand on that.
String[] myColumns = {"Treatment-Number","Treatment-Name", "Doctor-in-charge", "Room-No"};
// init a model with no data and the specified column names
DefaultTableModel myModel = new DefaultTableModel(new Object[myList.size()][4](), myColumns);
// assuming you have a list of lists...
int i = 0;
int j = 0;
for (ArrayList<Object> list : myList) {
for ( Object o : list ) {
myModel.setValueAt(o, i, j); // set the value at cell i,j to o
j++;
}
i++;
}
JTable myTable = new JTable(myModel); // make a new table with the specified data model
// ... do other stuff with the table
If you want to access the table data, you use myTable.getModel() and update the data. This will automatically update the view of the table (completing the MVC connection)
Look here for more info on using tables.
Since the program is too large I'll just paste the important parts of code. Here's the problem:
I have two JTables. First one collects data from DB and displays the list of all invoices stored in DB. The purpose of the second table is when you click on one row from the table, event handler needs to collect integer from column ID. Using this ID the second table will then display all the contest of that invoice (all the products stored in it).
First and second table work perfectly. The problem is that I have no idea how can I collect certain data (I basically just need ID column) from a selected row and then through a method I already made update the second JTable with new info. Here's my code if it helps:
(PS: once I learn how to do that, will the list on the left change every time by default when I select different row, or do I need to use validate/revalidate methods?)
public JPanel tabInvoices() {
JPanel panel = new JPanel(new MigLayout("", "20 [grow, fill] 10 [grow, fill] 20", "20 [] 10 [] 20"));
/** Labels and buttons **/
JLabel labelInv = new JLabel("List of all invoices");
JLabel labelPro = new JLabel("List of all products in this invoice");
/** TABLE: Invoices **/
String[] tableInvTitle = new String[] {"ID", "Date"};
String[][] tableInvData = null;
DefaultTableModel model1 = new DefaultTableModel(tableInvData, tableInvTitle);
JTable tableInv = null;
/** Disable editing of the cell **/
tableInv = new JTable(model1){
public boolean isCellEditable(int r, int c) {
return false;
}
};
/** Load the invoices from DB **/
List<Invoice> listInv = is.getAllInvoices();
for (int i = 0; i < listInv.size(); i++) {
model1.insertRow(i, new Object[] {
listInv.get(i).getID(),
listInv.get(i).getDate()
});
}
/** TABLE: Invoice Info **/
String[] tableInfTitle = new String[] {"ID", "Name", "Type", "Price", "Quantity"};
String[][] tableInfData = null;
DefaultTableModel model2 = new DefaultTableModel(tableInfData, tableInfTitle);
JTable tableInf = null;
/** Disable editing of the cell **/
tableInf = new JTable(model2){
public boolean isCellEditable(int r, int c) {
return false;
}
};
/** Load the products from DB belonging to this invoice **/
List<Product> listPro = is.getInvoiceInfo(1); // Here's where I need the ID fetched from selected row. For now default is 1.
for (int i = 0; i < listPro.size(); i++) {
model2.insertRow(i, new Object[] {
listPro.get(i).getID(),
listPro.get(i).getName(),
listPro.get(i).getType(),
listPro.get(i).getPrice(),
listPro.get(i).getQuantity()
});
}
/** Scroll Panes **/
JScrollPane scrollInv = new JScrollPane(tableInv);
JScrollPane scrollPro = new JScrollPane(tableInf);
panel.add(labelInv);
panel.add(labelPro, "wrap");
panel.add(scrollInv);
panel.add(scrollPro);
return panel;
}
For now, the right table only displays content of the first invoice:
With the help of following code you can get the value of selected clicked cell, so you just have to click on ID cell value (the Invoicee ID whose Products you want to see in second table) and with the help of following event handler you will get the value and then you can get data based on that ID and set to second table. (In the code below, table is the object of your first table)
(Off-course you will have to apply some validation too, to check that the selected (and clicked) cell is ID not the DATE)
table.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
int row = table.rowAtPoint(e.getPoint());
int col = table.columnAtPoint(e.getPoint());
Object selectedObj = table.getValueAt(row, col);
JOptionPane.showMessageDialog(null, "Selected ID is " + selectedObj);
}
});
I'm trying to populate a table with data from a database however i am having some issues with it. Could someone provide me with an example? (so the table takes in an Object[][] parameter for the data). I have the following basic code to display a table ;
class table extends JFrame
{
JTable table;
public table()
{
setLayout(new FlowLayout());
String[] columnNames = {"test","test","test"};
Object[][] data= {{"test","test","test"},{"test","test","test"}};
table = new JTable(data,columnNames);
table.setPreferredScrollableViewportSize(new Dimension(500,100));
table.setFillsViewportHeight(true);
JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane);
}
}
Two years ago, during my time in technical school, I wrote a little library help solve some of the problems proposed by the exercises, which included a a DatabaseTableModel.
The class extends from AbstractTableModel, which means you can set it as the your JTable's data source.
Here's the algorithm that constructs a model from a ResultSet:
public final void constructModel(ResultSet rs) throws SQLException {
ResultSetMetaData rsmd = rs.getMetaData();
rs.last();
rowCount = rs.getRow();
int columnCount = rsmd.getColumnCount();
// DatabaseColumn simply holds a name and a Class<?>.
columns = new DatabaseColumn[columnCount];
// This is the Object[][] array that you were talking about.
// It holds all the data from the ResultSet.
data = new Object[columnCount][rowCount];
for (int i = 0; i < columnCount; ++i) {
// Figure out the column name and type.
int j = i + 1;
String colName = rsmd.getColumnLabel(j);
Class<?> colClass = String.class;
try {
colClass = Class.forName(rsmd.getColumnClassName(j));
} catch (ClassNotFoundException ex) {
colClass = String.class;
}
columns[i] = new DatabaseColumn(colName, colClass);
// Get the data in the current column as an Object.
rs.beforeFirst();
for (int k = 0; rs.next(); ++k) {
data[i][k] = rs.getObject(j);
}
}
// Notify listeners about the changes so they can update themselves.
fireTableStructureChanged();
}
The class worked when I used it in school, but it isn't exactly production code. When I look at it today, I start to see problems.
One problem is that it is loading the entire contents of the ResultSet into memory. Could get ugly pretty quickly.
Also, the algorithm isn't exactly optimal. It loops around with the database cursor as if it was nothing; I suppose that it would be less costly for the database if it had retrieved all the objects in the current row first and assigned them to their appropriate columns before moving on to the next row.
Nevertheless, I think it is a good enough starting point.