问题
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;
}
}
来源:https://stackoverflow.com/questions/30527900/how-do-you-get-the-font-and-graphic-of-a-column-header-in-a-jtable