Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a different model of JTable?

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: table design with bold last column

Is it possible to design a table like this in Java? Please share you have any idea.

like image 807
Jay Marz Avatar asked Jan 21 '13 07:01

Jay Marz


People also ask

What is JTable model?

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);

How JTable is created?

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.


2 Answers

There's lot of different ways you could achieve this result...

enter image description here

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 JTables 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

like image 122
MadProgrammer Avatar answered Oct 16 '22 13:10

MadProgrammer


Override prepareRendere method of JTable. For column 1 which contains text use one font and for column 2 use another font.

enter image description here

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.)

enter image description here

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.

like image 23
Amarnath Avatar answered Oct 16 '22 12:10

Amarnath