How do you get the font and graphic of a column he

2019-08-10 05:45发布

问题:

I am trying to get the graphic and font of a column header in a JTable. To do this I am using the code

Graphics g = myTable.getColumnModel().getColumn(i).getGraphics();
Font f = myTable.getColumnModel().getColumn(i).getFont();

However that produces a can't find symbol error

The full code for this program is

import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.lang.*;
import java.awt.event.*;
import javax.swing.event.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Comparator;
import java.text.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.table.*;
import java.lang.Object.*;
import javax.swing.text.*;
import java.awt.FontMetrics;
import java.awt.Font;
import java.awt.Graphics;


public class JtableIe
{
    JFrame myMainWindow = new JFrame("Compare Tables");

    JPanel  firstPanel = new JPanel();

    JScrollPane myScrollTable;
    JTable myTable;
    JTextField srchFld1;
    JTextField srchFld2;
    TableRowSorter sorter;
    JLabel srchLbl1 = new JLabel();
    JLabel srchLbl2 = new JLabel();
    DefaultTableModel model;

    int testMaxMinSize = 0;

    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    String []fontFamilies = ge.getAvailableFontFamilyNames();

    public void runGUI()
    {
        myMainWindow.setBounds(10, 10, 1296, 756);

        myMainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        myMainWindow.setLayout(new GridLayout(1,1));

        createFirstPanel();

        myMainWindow.getContentPane().add(firstPanel);

        myMainWindow.setVisible(true);
    }

    public void createFirstPanel()
    {
        firstPanel.setLayout(null);

        srchLbl1.setLocation(0,0);
        srchLbl1.setSize(150,26);
        srchLbl1.setText("Name Search:");
        firstPanel.add(srchLbl1);

        srchLbl2.setLocation(660,0);
        srchLbl2.setSize(150,26);
        srchLbl2.setText("ID Search:");
        firstPanel.add(srchLbl2);

        String[] aHeaders = {"Name","ID","Number 1","Number 2","Time","Date"};
        Object[][] aData = new Object[5][6];

        ///////Data////////
        aData[0][0] = "John";
        aData[0][1] = "JS96";
        aData[0][2] = "1";
        aData[0][3] = "186";
        aData[0][4] = "1h 23m";
        aData[0][5] = getJavaDate("12/11/2015");

        aData[1][0] = "David";
        aData[1][1] = "DB36";
        aData[1][2] = "2";
        aData[1][3] = "111852";
        aData[1][4] = "2h 55m";
        aData[1][5] = getJavaDate("12/11/2020");

        aData[2][0] = "Daniel";
        aData[2][1] = "DK73";
        aData[2][2] = "3";
        aData[2][3] = "2921";
        aData[2][4] = "1h 55m";
        aData[2][5] = getJavaDate("12/11/2014");

        aData[3][0] = "Janis";
        aData[3][1] = "JW84";
        aData[3][2] = "4";
        aData[3][3] = "6512";
        aData[3][4] = "12h 26m";
        aData[3][5] = getJavaDate("13/11/2015");

        aData[4][0] = "Adam";
        aData[4][1] = "AF98";
        aData[4][2] = "5";
        aData[4][3] = "7524";
        aData[4][4] = "5h 47m";
        aData[4][5] = getJavaDate("11/11/2015");
        //////////////
        model = new DefaultTableModel(aData, aHeaders)
        {
            @Override
            public Class<?> getColumnClass(int column) 
            {
                switch (column)
                {
                    case 5: return Date.class;
                    default: return Object.class;
                }
            }

            @Override
            public boolean isCellEditable(int row, int column) 
            {
               return false;//all cells false
            }
        };

        myTable = new JTable(model);

        myTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

        myTable.setAutoCreateRowSorter(true);

        sorter = new TableRowSorter(myTable.getModel());
        List sortKeys = new ArrayList();
        sortKeys.add(new RowSorter.SortKey(5, SortOrder.ASCENDING));
        sorter.setSortKeys(sortKeys);
        setRenderers();
        myTable.setRowSorter(sorter);

        DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
        centerRenderer.setHorizontalAlignment( SwingConstants.CENTER );
        myTable.setDefaultRenderer(Object.class, centerRenderer);

        DefaultRowSorter sorter = (DefaultRowSorter) myTable.getRowSorter();

        setMinPrefMax();

        myScrollTable = new JScrollPane(myTable); 
        myScrollTable.setSize(1296,756); 
        myScrollTable.setLocation(0,25); 
        System.out.println("Creating compare table");

        srchFld1 = new JTextField(10);
        srchFld1.setSize(550,26); 
        srchFld1.setLocation(100,0);
        srchFld1.setToolTipText("Enter Name");
        firstPanel.add(srchFld1);

        srchFld2 = new JTextField(10);
        srchFld2.setSize(550,26); 
        srchFld2.setLocation(740,0);
        srchFld2.setToolTipText("Enter ID");
        firstPanel.add(srchFld2);

        //////////////////////
        Document doc = srchFld1.getDocument();
        DocumentListener listener = new DocumentListener() 
        {

            @Override
            public void insertUpdate(DocumentEvent e) 
            {
                newFilter();
            }

            @Override
            public void removeUpdate(DocumentEvent e) 
            {
                newFilter();
            }

            @Override
            public void changedUpdate(DocumentEvent e) 
            {
                newFilter();
            }
        };
        doc.addDocumentListener(listener);

        ///////////////
        Document docb = srchFld2.getDocument();
        DocumentListener listenerb = new DocumentListener() {

            @Override
            public void insertUpdate(DocumentEvent e) 
            {
                newFilter();
            }

            @Override
            public void removeUpdate(DocumentEvent e) 
            {
                newFilter();
            }

            @Override
            public void changedUpdate(DocumentEvent e) 
            {
                newFilter();
            }
        };
        docb.addDocumentListener(listenerb);
        ///////////////

        firstPanel.add(myScrollTable);
    }

    public void setMinPrefMax()
    {
        for (int i = 0; i < myTable.getColumnCount(); i++) 
        {
            String Hello = myTable.getColumnModel().getColumn(i).getHeaderValue()+"";
            System.out.println(Hello);
            Graphics g = myTable.getColumnModel().getColumn(i).getGraphics();
            Font f = myTable.getColumnModel().getColumn(i).getFont();
            FontMetrics metrics = g.getFontMetrics(f);
            int minLength = metrics.stringWidth(Hello)+10;
            System.out.println(minLength);
            myTable.getColumnModel().getColumn(i).setMinWidth(minLength);
        }
    }

    private static final DateFormat DATE_FORMAT = new SimpleDateFormat("dd/MM/yyyy");

    private void setRenderers() 
    {
        DateRenderer dr = new DateRenderer();
        dr.setHorizontalAlignment(SwingConstants.CENTER);
        myTable.setDefaultRenderer(Date.class, dr);
    }

    private Date getJavaDate(String s) 
    {
        try 
        {
            SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
            Date d = sdf.parse(s);
            return d;
        } 

        catch (ParseException ex) 
        {
            Logger.getLogger(TableBasic.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }

    private void newFilter()
    {
        RowFilter rf = null;
        try 
        {
            List<RowFilter<Object,Object>> filters = new ArrayList<RowFilter<Object,Object>>(2);
            filters.add(RowFilter.regexFilter("(?i)"+srchFld1.getText(), 0));
            filters.add(RowFilter.regexFilter("(?i)"+srchFld2.getText(), 1));
            rf = RowFilter.andFilter(filters);
        } 
        catch (java.util.regex.PatternSyntaxException e) 
        {
            return;
        }
        sorter.setRowFilter(rf);
    }

    public static void main(String[] args)
    {
        JtableIe ji = new JtableIe();
        ji.runGUI();
    }

    private class DateRenderer extends DefaultTableCellRenderer 
    {

        private static final long serialVersionUID = 1L;

        @Override
        public Component getTableCellRendererComponent(JTable myTable, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            super.getTableCellRendererComponent(myTable, value, isSelected, hasFocus, row, column);
            if (!(value instanceof Date)) {
                return this;
            }
            setText(DATE_FORMAT.format((Date) value));
            return this;
        }
    }
}

And the code for TableBasic is

import java.awt.*;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.table.*;

public class TableBasic {

    private JFrame frame = new JFrame();
    private  String[] columnNames = {"Date", "String", "Long", "Boolean"};
    private Object[][] data = {
        {getJavaDate("13-11-2020"), "A", new Double(1), Boolean.TRUE},
        {getJavaDate("13-11-2018"), "B", new Double(2), Boolean.FALSE},
        {getJavaDate("12-11-2015"), "C", new Double(9), Boolean.TRUE},
        {getJavaDate("12-11-2015"), "D", new Double(4), Boolean.FALSE}
    };
    private DefaultTableModel model = new DefaultTableModel(data, columnNames) {
        @Override
        public Class<?> getColumnClass(int column) {
            return getValueAt(0, column).getClass();
        }
    };
    private JTable table = new JTable(model);
    private JScrollPane scrollPane = new JScrollPane(table);
    private static final DateFormat DATE_FORMAT = new SimpleDateFormat("dd/MM/yyyy");

    public TableBasic() {
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        table.setAutoCreateRowSorter(true);
        setRenderers();
        // DefaultRowSorter has the sort() method
        table.getRowSorter().toggleSortOrder(0);
        frame.add(scrollPane);
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private void setRenderers() {
        //TableColumnModel m = table.getColumnModel();
        //"Integer", "String", "Interger", "Double", "Boolean", "Double", "String", "Boolean", "Date"
        table.setDefaultRenderer(Date.class, new DateRenderer());
    }

    private Date getJavaDate(String s) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
            Date d = sdf.parse(s);
            return d;

        } catch (ParseException ex) {
            Logger.getLogger(TableBasic.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                TableBasic frame = new TableBasic();
            }
        });
    }

    private class DateRenderer extends DefaultTableCellRenderer {

        private static final long serialVersionUID = 1L;

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            if (!(value instanceof Date)) {
                return this;
            }
            setText(DATE_FORMAT.format((Date) value));
            return this;
        }
    }
}

Note

The code causing the errors is in the for loop inside the method called setMinPrefMax()

回答1:

TableColumn extends Object... This is a model object, not a graphical one.

The reality is that the font/graphics stuff is all done in the JTable's TableCellRenderer. So if you're using a custom one you can look in that class. Otherwise, you'll need to look into the swing source code (src.zip)



回答2:

I was able to achieve my desired result, which was to have the minimum width of a column to be determined by the size of the columnn header. I have achieved this by using this code.

for (int i = 0; i < myTable.getColumnCount(); i++) 
{
    JTableHeader tableHeader = myTable.getTableHeader();
    FontMetrics headerFontMetrics = tableHeader.getFontMetrics(tableHeader.getFont());

    if(tableHeader == null) 
    {
        return;
    }

    int Test = headerFontMetrics.stringWidth(myTable.getColumnName(i));
    System.out.println("The width of the column header "+i+" is: "+Test);
    int minLength = Test+20;
    myTable.getColumnModel().getColumn(i).setMinWidth(minLength);
}

Edit

This code can be used to set the minimum, preferred, and maximum constraints depending on the column header and cell constraints.

public static int GetScreenWorkingWidth() 
{
    return java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds().width;
}

public void setMinPrefMax()
{
    for(int i = 0; i < myTable.getColumnCount(); i++) 
    {
        ////Min
        System.out.println("Column "+i);
        JTableHeader tableHeader = myTable.getTableHeader();
        FontMetrics headerFontMetrics = tableHeader.getFontMetrics(tableHeader.getFont());

        if(tableHeader == null) 
        {
            return;
        }

        int Test = headerFontMetrics.stringWidth(myTable.getColumnName(i));
        System.out.println("The width of the column header "+i+" is: "+Test);
        int minLength = Test+20;
        myTable.getColumnModel().getColumn(i).setMinWidth(minLength);
        ////Pref
        for(int row=0; row<myTable.getRowCount(); row++)
        {
            Font fontF1 = myTable.getFont();
            FontMetrics cVFontMetrics = myTable.getFontMetrics(fontF1);

            System.out.println(myTable.getValueAt(row, i));
            String Hello = myTable.getValueAt(row, i)+"";
            int Test2 = cVFontMetrics.stringWidth(Hello);
            System.out.println("The length of this string is: "+Test2);
            if(Test2>testMaxPrefSize)
            {
                testMaxPrefSize = Test2;
            } 
        }
        System.out.println("The maximum value for cells in column "+i+" is: "+testMaxPrefSize);
        myTable.getColumnModel().getColumn(i).setPreferredWidth(testMaxPrefSize+20);
        ////Max
        int testMaxSize = testMaxPrefSize+300;

        if(testMaxSize>GetScreenWorkingWidth())
        {
            myTable.getColumnModel().getColumn(i).setMaxWidth(GetScreenWorkingWidth());
        }

        else
        {
            myTable.getColumnModel().getColumn(i).setMaxWidth(testMaxSize);
        }

        testMaxPrefSize=0;
    }
}