在Panel上绘制JTable行和列

我正在编写一个应用程序,我必须在canvas上绘制JTable组件。 但经过我的几次尝试仍然无法绘制完整的JTable画面。 我尝试使用getCellRect api使用JTable的特定单元格的大小绘制,但是当数据很大时无法在canvas上绘制特定单元格。 以下是示例代码: –

import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.*; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.table.*; import java.util.*; import java.awt.*; public class SimpleTableDemo extends JPanel { private boolean DEBUG = false; private int spacing = 6; private Map columnSizes = new HashMap(); String[] columnNames = {"First Name", "Last Name", "Sport", "# of Years", "Vegetarian"}; Object[][] data = { {"Kathy", "Smith", "SnowboardingXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", new Integer(5), new Boolean(false)}, {"John", "Doe", "Rowing", new Integer(3), new Boolean(true)}, {"Sue", "Black", "Knitting", new Integer(2), new Boolean(false)}, {"Jane", "White", "Speed reading", new Integer(20), new Boolean(true)}, {"Joe", "Brown", "Pool", new Integer(10), new Boolean(false)} }; final JTable table = new JTable(data, columnNames); Panel1 panel; public SimpleTableDemo() { super(new GridLayout(3,0)); table.setPreferredScrollableViewportSize(new Dimension(500, 70)); //table.setFillsViewportHeight(true); if (DEBUG) { table.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { printDebugData(table); } }); } //Create the scroll pane and add the table to it. JScrollPane scrollPane = new JScrollPane(table); //Add the scroll pane to this panel. add(scrollPane); panel = new Panel1(); Rectangle rect = table.getCellRect(0,0,true); panel.setX(table.getWidth()); panel.setY(0); panel.setWidth(rect.width); panel.setHeight(rect.height); panel.setStr(table.getModel().getValueAt(0,0).toString()); panel.setModel(table); add(panel); final JComboBox jNumberComboBoxSize = new JComboBox(); jNumberComboBoxSize.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "11", "12", "14", "16", "18", "20", "24", "30", "36", "48", "72" })); jNumberComboBoxSize.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jNumberComboBoxSizeActionPerformed(jNumberComboBoxSize); } }); JPanel panel2 = new JPanel(); panel2.add(jNumberComboBoxSize); add(panel2); adjustColumns(); } private void jNumberComboBoxSizeActionPerformed(JComboBox jNumberComboBoxSize) { int fontSize = Integer.parseInt(jNumberComboBoxSize.getSelectedItem().toString()); table.setRowHeight(fontSize); table.setFont(new Font("Serif", Font.BOLD, fontSize)); Rectangle rect = table.getCellRect(0,0,true); panel.setX(0); panel.setY(0); // panel.setWidth(rect.width); panel.setHeight(rect.height); panel.setStr(table.getModel().getValueAt(0,0).toString()); panel.setModel(table); panel.repaint(); table.revalidate(); } private void printDebugData(JTable table) { int numRows = table.getRowCount(); int numCols = table.getColumnCount(); javax.swing.table.TableModel model = table.getModel(); System.out.println("Value of data: "); for (int i=0; i < numRows; i++) { System.out.print(" row " + i + ":"); for (int j=0; j < numCols; j++) { System.out.print(" " + model.getValueAt(i, j)); } System.out.println(); } System.out.println("--------------------------"); } /* * Adjust the widths of all the columns in the table */ public void adjustColumns() { TableColumnModel tcm = table.getColumnModel(); for (int i = 0; i < tcm.getColumnCount(); i++) { adjustColumn(i); } } /* * Adjust the width of the specified column in the table */ public void adjustColumn(final int column) { TableColumn tableColumn = table.getColumnModel().getColumn(column); if (! tableColumn.getResizable()) return; int columnHeaderWidth = getColumnHeaderWidth( column ); int columnDataWidth = getColumnDataWidth( column ); int preferredWidth = Math.max(columnHeaderWidth, columnDataWidth); panel.setWidth(preferredWidth); updateTableColumn(column, preferredWidth); } /* * Calculated the width based on the column name */ private int getColumnHeaderWidth(int column) { TableColumn tableColumn = table.getColumnModel().getColumn(column); Object value = tableColumn.getHeaderValue(); TableCellRenderer renderer = tableColumn.getHeaderRenderer(); if (renderer == null) { renderer = table.getTableHeader().getDefaultRenderer(); } Component c = renderer.getTableCellRendererComponent(table, value, false, false, -1, column); return c.getPreferredSize().width; } /* * Calculate the width based on the widest cell renderer for the * given column. */ private int getColumnDataWidth(int column) { int preferredWidth = 0; int maxWidth = table.getColumnModel().getColumn(column).getMaxWidth(); for (int row = 0; row = maxWidth) break; } return preferredWidth; } /* * Get the preferred width for the specified cell */ private int getCellDataWidth(int row, int column) { // Inovke the renderer for the cell to calculate the preferred width TableCellRenderer cellRenderer = table.getCellRenderer(row, column); Component c = table.prepareRenderer(cellRenderer, row, column); int width = c.getPreferredSize().width + table.getIntercellSpacing().width; return width; } /* * Update the TableColumn with the newly calculated width */ private void updateTableColumn(int column, int width) { final TableColumn tableColumn = table.getColumnModel().getColumn(column); if (! tableColumn.getResizable()) return; width += spacing; // Don't shrink the column width width = Math.max(width, tableColumn.getPreferredWidth()); columnSizes.put(tableColumn, new Integer(tableColumn.getWidth())); table.getTableHeader().setResizingColumn(tableColumn); tableColumn.setWidth(width); } /** * Create the GUI and show it. For thread safety, * this method should be invoked from the * event-dispatching thread. */ private static void createAndShowGUI() { //Create and set up the window. JFrame frame = new JFrame("SimpleTableDemo"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Create and set up the content pane. SimpleTableDemo newContentPane = new SimpleTableDemo(); newContentPane.setOpaque(true); //content panes must be opaque frame.setContentPane(newContentPane); //Display the window. frame.pack(); frame.setVisible(true); } public static void main(String[] args) { //Schedule a job for the event-dispatching thread: //creating and showing this application's GUI. javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } } class Panel1 extends JPanel { int x; int y; int width; int height; String str; JTable model; public void setModel(JTable model) { this.model = model; } public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; } public void setWidth(int w) { this.width = w; } public void setHeight(int h) { this.height = h; } public void setStr(String s) { this.str = s; } public void paint(Graphics g) { super.paint(g); int initX= 0; for(int row=0;row < 5; ++row) { initX = x; for (int col=0;col < 5;++col) { g.drawRect(x,y,width,height); g.drawString(model.getModel().getValueAt(row,col).toString(),x + 10,y + 10); x = x + width; } x = initX; y = y + height; } } };

我修改了此代码以重绘具有字体大小和边框的列单元格。 我想绘制所有这些表格自定义,请看看并提出建议。

谢谢

SimpleTableDemo.java

  package com.swing.data; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.GridLayout; import java.awt.Rectangle; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.HashMap; import java.util.Map; import javax.swing.BorderFactory; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; public class SimpleTableDemo extends JPanel { private boolean DEBUG = false; private int spacing = 6; private Map columnSizes = new HashMap(); String[] columnNames = {"First Name","Last Name","Sport","# of Years","Vegetarian"}; Object[][] data = { {"Kathy", "Smith","SnowboardingXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", new Integer(5), new Boolean(false)}, {"John", "Doe","Rowing", new Integer(3), new Boolean(true)}, {"Sue", "Black","Knitting", new Integer(2), new Boolean(false)}, {"Jane", "White","Speed reading", new Integer(20), new Boolean(true)}, {"Joe", "Brown","Pool", new Integer(10), new Boolean(false)} }; JTable table = new JTable(data, columnNames); Panel1 panel; public SimpleTableDemo() { super(new GridLayout(3,0)); table.setPreferredScrollableViewportSize(new Dimension(500, 70)); if (DEBUG) { table.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { printDebugData(table); } }); } //Create the scroll pane and add the table to it. JScrollPane scrollPane = new JScrollPane(table); //Add the scroll pane to this panel. add(scrollPane); panel = new Panel1(); // Rectangle rect = table.getCellRect(0,0,true); // // // panel.setX(table.getWidth()); // // panel.setY(0); // panel.setWidth(rect.width); // panel.setHeight(rect.height); // panel.setStr(table.getModel().getValueAt(0,0).toString()); panel.setModel(table); add(panel); final JComboBox jNumberComboBoxSize = new JComboBox(); jNumberComboBoxSize.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "11", "12", "14", "16", "18", "20", "24", "30", "36", "48", "72" })); jNumberComboBoxSize.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jNumberComboBoxSizeActionPerformed(jNumberComboBoxSize); } }); JPanel panel2 = new JPanel(); panel2.add(jNumberComboBoxSize); add(panel2); adjustColumns(); } private void jNumberComboBoxSizeActionPerformed(JComboBox jNumberComboBoxSize) { int fontSize = Integer.parseInt(jNumberComboBoxSize.getSelectedItem().toString()); table.setRowHeight(fontSize); setBorder(new Font("Serif", Font.BOLD, fontSize)); table.setFont(new Font("Serif", Font.BOLD, fontSize)); panel.setFont(new Font("Serif", Font.BOLD, fontSize)); Rectangle rect = table.getCellRect(0,0,true); panel.setX(0); panel.setY(0); panel.setHeight(rect.height); panel.setStr(table.getModel().getValueAt(0,0).toString()); panel.setModel(table); panel.repaint(); table.revalidate(); } public void setBorder(Font f) { BorderCellRenderer cellRenderer = new BorderCellRenderer(); cellRenderer.setColumnBorder(BorderFactory.createLineBorder(Color.BLACK, 2)); cellRenderer.setFont(f); table.getColumnModel().getColumn(0).setCellRenderer(cellRenderer); table.getColumnModel().getColumn(1).setCellRenderer(cellRenderer); } private void printDebugData(JTable table) { int numRows = table.getRowCount(); int numCols = table.getColumnCount(); javax.swing.table.TableModel model = table.getModel(); System.out.println("Value of data: "); for (int i=0; i < numRows; i++) { System.out.print(" row " + i + ":"); for (int j=0; j < numCols; j++) { System.out.print(" " + model.getValueAt(i, j)); } System.out.println(); } System.out.println("--------------------------"); } /* * Adjust the widths of all the columns in the table */ public void adjustColumns() { TableColumnModel tcm = table.getColumnModel(); for (int i = 0; i < tcm.getColumnCount(); i++) { adjustColumn(i); } } /* * Adjust the width of the specified column in the table */ public void adjustColumn(int column) { TableColumn tableColumn = table.getColumnModel().getColumn(column); if (! tableColumn.getResizable()) return; int columnHeaderWidth = getColumnHeaderWidth( column ); int columnDataWidth = getColumnDataWidth( column ); int preferredWidth = Math.max(columnHeaderWidth, columnDataWidth); panel.setWidth(preferredWidth); updateTableColumn(column, preferredWidth); } /* * Calculated the width based on the column name */ private int getColumnHeaderWidth(int column) { TableColumn tableColumn = table.getColumnModel().getColumn(column); Object value = tableColumn.getHeaderValue(); TableCellRenderer renderer = tableColumn.getHeaderRenderer(); if (renderer == null) { renderer = table.getTableHeader().getDefaultRenderer(); } Component c = renderer.getTableCellRendererComponent(table, value, false, false, -1, column); return c.getPreferredSize().width; } /* * Calculate the width based on the widest cell renderer for the * given column. */ private int getColumnDataWidth(int column) { int preferredWidth = 0; int maxWidth = table.getColumnModel().getColumn(column).getMaxWidth(); for (int row = 0; row 
= maxWidth) break; } return preferredWidth; } /* * Get the preferred width for the specified cell */ private int getCellDataWidth(int row, int column) { // Inovke the renderer for the cell to calculate the preferred width TableCellRenderer cellRenderer = table.getCellRenderer(row, column); Component c = table.prepareRenderer(cellRenderer, row, column); int width = c.getPreferredSize().width + table.getIntercellSpacing().width; return width; } /* * Update the TableColumn with the newly calculated width */ private void updateTableColumn(int column, int width) { final TableColumn tableColumn = table.getColumnModel().getColumn(column); if (! tableColumn.getResizable()) return; width += spacing; // Don't shrink the column width width = Math.max(width, tableColumn.getPreferredWidth()); columnSizes.put(tableColumn, new Integer(tableColumn.getWidth())); table.getTableHeader().setResizingColumn(tableColumn); tableColumn.setWidth(width); } /** * Create the GUI and show it. For thread safety, * this method should be invoked from the * event-dispatching thread. */ private static void createAndShowGUI() { //Create and set up the window. JFrame frame = new JFrame("SimpleTableDemo"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Create and set up the content pane. SimpleTableDemo newContentPane = new SimpleTableDemo(); newContentPane.setOpaque(true); //content panes must be opaque frame.setContentPane(newContentPane); //Display the window. frame.pack(); frame.setVisible(true); } public static void main(String[] args) { //Schedule a job for the event-dispatching thread: //creating and showing this application's GUI. javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } } **Panel1.java** package com.swing.data; import java.awt.Font; import java.awt.Graphics; import java.awt.Rectangle; import javax.swing.JPanel; import javax.swing.JTable; class Panel1 extends JPanel { int x; int y; int width; int height; String str; JTable model; Font font; public Font getFont() { return font; } public void setFont(Font font) { this.font = font; } public void setModel(JTable model) { this.model = model; } public JTable getModel() { return model; } public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; } public void setWidth(int w) { this.width = w; } public void setHeight(int h) { this.height = h; } public void setStr(String s) { this.str = s; } public void paint(Graphics g) { super.paint(g); // int initX= 0; // for(int row=0;row < 5; ++row) // { // initX = x; // for (int col=0;col >>>>>>>>>>>>>>>>>>>>"); JTable table = getModel(); int columnCount = table.getModel().getColumnCount(); int rowCount = table.getModel().getRowCount(); int yLoc = 10; int rowHeight = 0 ; int columnWidth = 0 ; g.setFont(font); for(int r = 0 ; r < rowCount; r++) { int xLoc = 0 ; for(int c= 0 ; c< columnCount; c++) { Rectangle rect = table.getCellRect(r, c, true); columnWidth = rect.width; rowHeight = rect.height; g.drawRect(xLoc, yLoc, columnWidth, rowHeight); String displayString = table.getValueAt(r, c).toString(); System.out.println("displayString ::"+displayString); g.drawString(displayString, xLoc+5, yLoc+15); xLoc+= columnWidth; } yLoc+= rowHeight; } } } **BorderCellRenderer.java** package com.swing.data; import java.awt.*; import javax.swing.*; import javax.swing.table.*; import javax.swing.border.*; /** * @version 1.0 03/06/99 */ public class BorderCellRenderer extends JLabel implements TableCellRenderer { protected Border noFocusBorder; protected Border columnBorder; protected Font font; public Font getFont() { return font; } public void setFont(Font font) { this.font = font; } public BorderCellRenderer() { noFocusBorder = new EmptyBorder(1, 2, 1, 2); setOpaque(true); } public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setText((value == null) ? "" : value.toString()); setBorder(columnBorder); setFont(font); return this; } public void setColumnBorder(Border border) { columnBorder = border; } public Border getColumnBorder() { return columnBorder; } }

请建议重新绘制相应的JTable字体和边框。

有几个问题很明显:

图片

  1. 您似乎正在使用现有JTable的几何创建自己的表视图; 这些尺寸可能在pack()之后才有效。

  2. 循环遍历adjustColumns的列,但只有最后一列宽度在panel设置,然后变为表格中的常量宽度。

  3. 与使用flyweight渲染的 JTable本身相比,您的实现将扩展得很差,如图所示。

  4. 调整框架大小时, panel消失; 你应该显式调用repaint ,监听TableModel ,或者使用JTable本身。

  5. 从Java 5开始, autoboxing允许以下内容; 相比:

     {"John", "Doe", "Rowing", new Integer(3), new Boolean(true)} {"John", "Doe", "Rowing", 3, true} 
  6. 不要替换内容窗格; add()你的面板到它; 相比:

     frame.setContentPane(newContentPane); frame.add(newContentPane); 
  7. 你使用GridLayout(3,0)表明存在误解; 要在一列中获取任意数量的行,请使用GridLayout(0, 1)

  8. 在扩展JPanel ,请注意“Swing程序应该覆盖paintComponent()而不是覆盖paint() ;” 另见AWT和Swing中的绘画:绘画方法

另一种方法是将表呈现为JLabel HTML。

HTML表演示。

 import java.awt.*; import javax.swing.*; public class HTMLTableDemo { HTMLTableDemo() { StringBuilder sb = new StringBuilder(); sb.append("
"); sb.append(""); for ( String columnName : columnNames ) { sb.append(""); } sb.append(""); for (Object[] row : data) { sb.append(""); for (Object value : row) { sb.append(""); } sb.append(""); } sb.append("
"); sb.append(columnName); sb.append("
"); sb.append(value); sb.append("
"); JLabel html = new JLabel(sb.toString()); JOptionPane.showMessageDialog(null, html); } public static void main(String[] args) { Runnable r = new Runnable() { @Override public void run() { new HTMLTableDemo(); } }; SwingUtilities.invokeLater(r); } String[] columnNames = { "First Name", "Last Name", "Sport", "# of Years", "Vegetarian" }; Object[][] data = { {"Kathy", "Smith", "Snowboarding", new Integer(5), new Boolean(false)}, {"John", "Doe", "Rowing", new Integer(3), new Boolean(true)}, {"Sue", "Black", "Knitting", new Integer(2), new Boolean(false)}, {"Jane", "White", "Speed reading", new Integer(20), new Boolean(true)}, {"Joe", "Brown", "Pool", new Integer(10), new Boolean(false)} }; }

要将其呈现给Graphics实例,请参阅此答案的LabelRenderTest.java源代码。

我使用以下代码成功地绘制了一对一的绘图: –

Panel1.java

 package com.swing.data; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Rectangle; import java.awt.font.FontRenderContext; import javax.swing.JPanel; import javax.swing.JTable; class Panel1 extends JPanel { int x; int y; int width; int height; String str; JTable model; Font font; public Font getFont() { return font; } public void setFont(Font font) { this.font = font; } public void setModel(JTable model) { this.model = model; } public JTable getModel() { return model; } public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; } public void setWidth(int w) { this.width = w; } public void setHeight(int h) { this.height = h; } public void setStr(String s) { this.str = s; } public void paint(Graphics g) { super.paint(g); // int initX= 0; // for(int row=0;row < 5; ++row) // { // initX = x; // for (int col=0;col < 5;++col) // { // g.drawRect(x,y,width,height); // String str = model.getModel().getValueAt(row, col).toString(); // int xloc = (x+10); // int yloc = y +10; //// System.out.println("xloc : "+xloc); //// System.out.println("yloc : "+yloc); //// System.out.println("width : "+width); //// System.out.println("height : "+height); //// System.out.println("str : "+str); // // g.drawString(model.getModel().getValueAt(row,col).toString(),x + 10,y + 10); // x = x + width; // } // x = initX; // y = y + height; // // } System.out.println("Inside paint() >>>>>>>>>>>>>>>>>>>>>"); FontMetrics fm = g.getFontMetrics(font); JTable table = getModel(); int columnCount = table.getModel().getColumnCount(); int rowCount = table.getModel().getRowCount(); int yLoc =10; int rowHeight = 0 ; int columnWidth = 0 ; double w = 0; double h = 0; FontRenderContext frc = fm.getFontRenderContext(); g.setFont(font); for(int r = 0 ; r < rowCount; r++) { int xLoc = 0 ; int yPad = 0; for(int c= 0 ; c< columnCount; c++) { Rectangle rect = table.getCellRect(r, c, true); String displayString = table.getValueAt(r, c).toString(); columnWidth = rect.width; rowHeight = rect.height; w = (double)font.getStringBounds(displayString, frc).getWidth(); h = (double)font.getStringBounds(displayString, frc).getHeight(); //yPad = (int) Math.ceil((rowHeight - h)/2); yPad = Math.abs((int)(rowHeight - h)/2); System.out.println("displayString ::"+displayString + "rowHeight:" + rowHeight +"String height:" + h+"yPad:"+yPad +"xLoc:"+xLoc+"yLoc:"+yLoc); g.drawString(displayString, xLoc , yLoc + rowHeight - yPad); g.drawRect(xLoc, yLoc, columnWidth, rowHeight); xLoc+= columnWidth + table.getIntercellSpacing().width; } yLoc+= rowHeight + table.getIntercellSpacing().height; } } } 

谢谢