简体   繁体   中英

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: 桌面设计用粗体的最后一栏

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

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

PS:

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.

Yet another way to do it. Use an appropriate CellRenderer to achieve various styles and manage text alignement. As for making the TableHeader disappear, simply set it to null on the JTable .

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.util.Random;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableCellRenderer;

public class TestTableHeader {

    public static class BoldTableCellRenderer extends DefaultTableCellRenderer {

        public BoldTableCellRenderer() {
            setHorizontalAlignment(RIGHT);
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            Component renderer = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            renderer.setFont(renderer.getFont().deriveFont(Font.BOLD));
            return renderer;
        }
    }

    protected void initUI() {
        Vector<Vector<Object>> datas = new Vector<Vector<Object>>();
        Vector<String> colNames = new Vector<String>();
        for (int i = 0; i < 2; i++) {
            colNames.add("Col-" + (i + 1));
        }
        for (int i = 0; i < 15; i++) {
            Vector<Object> data = new Vector<Object>();
            data.add("John Smith (" + (i + 1) + ")");
            data.add(new Random().nextInt(4000));
            datas.add(data);
        }

        table = new JTable(datas, colNames);
        table.setShowGrid(false);
        table.getColumnModel().getColumn(1).setCellRenderer(new BoldTableCellRenderer());
        table.setFillsViewportHeight(false);
        table.setTableHeader(null);
        table.setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, Color.GRAY));
        JLabel label = new JLabel("Top 10 by Loan Balance");
        label.setFont(label.getFont().deriveFont(15.0f));
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        scrollpane = new JScrollPane(table);
        scrollpane.setRowHeaderView(null);
        frame.add(label, BorderLayout.NORTH);
        frame.add(scrollpane, BorderLayout.CENTER);
        frame.setSize(300, 200);
        frame.setVisible(true);
    }

    private JTable table;
    private JScrollPane scrollpane;

    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
            UnsupportedLookAndFeelException {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestTableHeader().initUI();
            }
        });
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM