I want to add on my system another design/model of JTable
. It is a simple design but for me (as a novice) I have difficulties setting this kind of table. I want the table to be look like this:
Is it possible to design a table like this in Java? Please share you have any idea.
The TableModel interface specifies the methods the JTable will use to interrogate a tabular data model. The JTable can be set up to display any data model which implements the TableModel interface with a couple of lines of code: TableModel myData = new MyTableModel(); JTable table = new JTable(myData);
JTable(): A table is created with empty cells. JTable(int rows, int cols): Creates a table of size rows * cols. JTable(Object[][] data, Object []Column): A table is created with the specified name where []Column defines the column names.
There's lot of different ways you could achieve this result...
Here, I've replaced the header with my own implementation, set the default cell renderer for type Double
to my own TableCellRenderer
and adjust some of the inbuilt properties of the table.
public class FancyTable {
public static void main(String[] args) {
new FancyTable();
}
public FancyTable() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JTable table = new JTable(new LoanModel());
table.setTableHeader(new SingleColumnTableHeader());
table.setFillsViewportHeight(true);
table.setShowHorizontalLines(true);
table.setShowVerticalLines(false);
table.setGridColor(Color.LIGHT_GRAY);
table.setDefaultRenderer(Double.class, new CurrencyRenderer());
JScrollPane scrollPane = new JScrollPane(table);
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(scrollPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class LoanModel extends AbstractTableModel {
private List<Loan> loans;
public LoanModel() {
loans = new ArrayList<Loan>(25);
loans.add(new Loan("Davies S.J", 2500000));
loans.add(new Loan("Lucas M.M", 1700000));
loans.add(new Loan("Smith R.B", 600000));
loans.add(new Loan("Jones T.T", 435000));
loans.add(new Loan("Brown R.B", 600000));
loans.add(new Loan("Walls T.T", 435000));
loans.add(new Loan("Healy R.B", 600000));
loans.add(new Loan("Taylor T.T", 435000));
loans.add(new Loan("Ginns R.B", 600000));
loans.add(new Loan("Murphy H", 435000));
}
@Override
public int getRowCount() {
return loans.size();
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
Class clazz = String.class;
switch (columnIndex) {
case 1:
clazz = Double.class;
break;
}
return clazz;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Object value = null;
Loan loan = loans.get(rowIndex);
switch (columnIndex) {
case 0:
value = loan.getName();
break;
case 1:
value= loan.getAmount();
break;
}
return value;
}
}
public class Loan {
private String name;
private double amount;
public Loan(String name, double amount) {
this.name = name;
this.amount = amount;
}
public String getName() {
return name;
}
public double getAmount() {
return amount;
}
}
public class CurrencyRenderer extends DefaultTableCellRenderer {
private Font boldFont;
public CurrencyRenderer() {
setHorizontalAlignment(JLabel.RIGHT);
boldFont = getFont().deriveFont(Font.BOLD);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (value instanceof Double) {
value = NumberFormat.getCurrencyInstance().format(value);
}
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
setFont(boldFont);
return this;
}
}
public class SingleColumnTableHeader extends JTableHeader {
private JLabel renderer;
public SingleColumnTableHeader() {
setBackground(Color.WHITE);
renderer = new JLabel("Top Ten Loan Balances");
renderer.setBorder(new EmptyBorder(4, 0, 4, 0));
}
@Override
public Dimension getPreferredSize() {
return renderer.getPreferredSize();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
FontMetrics fm = g2d.getFontMetrics();
Insets insets = getInsets();
int width = getWidth() - (insets.left + insets.right);
int height = getHeight() - (insets.top + insets.bottom);
renderer.setBounds(insets.left, insets.top, width, height);
renderer.paint(g2d);
g2d.setColor(Color.LIGHT_GRAY);
g2d.setStroke(new BasicStroke(2f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g2d.drawLine(insets.left, insets.top + height - 1, insets.left + width, insets.top + height - 1);
g2d.dispose();
}
}
}
You just as easily create your own custom JTable
and override configureEnclosingScrollPane
to set your own component for the table header, but, personally, I think that's over kill.
Being able to supply my own renderers is a far more flexible approach and promotes re-use of the component elements, with out producing tightly couple code...
You might find it handy to read through How to use Tables
Updated
It occurred to me, after something Guillaume said, you could simply set the JTable
s header to null
. Then, once you've added the table to the scroll pane, you could simply user JScrollPane#setColumnHeaderView
to set the header to something like a JLabel
.
It would easier the having to implement you own JTableHeader
Override prepareRendere method of JTable. For column 1 which contains text use one font and for column 2 use another font.
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
public class JTableExample {
public static void main(String[] args) {
Object[] column = {"Column One", "Column Two"};
Object[][] data = {{"One", "Two"}, {"Three", "Four"}, {"Five", "Five"}};
JTable toDoTable = new JTable(data, column) {
@Override
public Component prepareRenderer(TableCellRenderer renderer, int rowIndex,
int columnIndex) {
if(columnIndex == 1) {
setFont(new Font("Arial", Font.BOLD, 12));
} else {
setFont(new Font("Arial", Font.ITALIC, 12));
}
return super.prepareRenderer(renderer, rowIndex, columnIndex);
}
};
JScrollPane jpane = new JScrollPane(toDoTable);
JPanel panel = new JPanel();
JFrame frame = new JFrame();
frame.setSize(new Dimension(400, 100));
frame.setTitle("JTable Font Setting Example");
panel.add(jpane);
frame.add(new JScrollPane(panel));
frame.setVisible(true);
}
}
UPDATE:
As MadProgrammer and Guillaume Polet has suggested. I modified my approach using DefaultTableCellRenderer
(using Guillaume Polet code as reference.)
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
public class JTableExample {
public static void main(String[] args) {
Object[] column = {"Column One", "Column Two"};
Object[][] data = {{"One", "Two"}, {"Three", "Four"}, {"Five", "Five"}};
JTable table = new JTable(data, column);
table.getColumnModel().getColumn(1).setCellRenderer(new CustomTableCellRenderer());
table.setShowGrid(false);
table.setTableHeader(null);
JLabel label = new JLabel("Top 10 by Loan Balance");
label.setFont(label.getFont().deriveFont(15.0f));
JScrollPane scroll = new JScrollPane(table);
JFrame frame = new JFrame();
frame.setSize(new Dimension(400, 100));
frame.setTitle("JTable Font Setting Example");
frame.add(label, BorderLayout.NORTH);
frame.add(scroll, BorderLayout.CENTER);
frame.setVisible(true);
}
}
class CustomTableCellRenderer extends DefaultTableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object aValue,
boolean isSelected, boolean hasFocus, int rowIndex, int columnIndex) {
Component component = super.getTableCellRendererComponent(table, aValue, isSelected, hasFocus, rowIndex, columnIndex);
component.setFont(component.getFont().deriveFont(Font.BOLD));
return component;
}
}
P.S:
table.setTableHeader(null): => For hiding the columns use.
DefaultTableCellRenderer: => This Returns the default table cell renderer. So use this to make column-1 font style.
table.setShowGrid(false); => This will make the lines in the JTable as not visible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With