在 JScrollPane 中转换为 JTable 的图像
Convert to image of a JTable within a JScrollPane
我在 JScrollPane
里面有一个 JTable
,在 JPanel
下面。我需要将 table 导出为图像。如果 table 足够小,可以在 JScrollPane
中完全查看而没有滚动条,则它工作正常。但如果 table 太大,需要滚动条左右或上下移动,则导出的图像中只有部分 table 可见。
我正在使用以下代码
public BufferedImage componentToImage( Component component, boolean visible)
{
if (visible)
{
BufferedImage img = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TRANSLUCENT);
Graphics2D g2d = (Graphics2D) img.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
component.paintAll(g2d);
try
{
File outputfile = new File("C:\Users\SciOme Admin\Desktop\a.png");
ImageIO.write(img, "png", outputfile);
}
catch (IOException e)
{
e.printStackTrace();
}
return img;
}
}
我将 JScrollPane
作为组件传递的地方。
我正在附加带有滚动条的部分图像。但是我需要完整的JTable
。
我无法将 JTable
作为组件传递,因为我在 JScrollPane
中使用了两个重叠的 table。一个 table 用于仅显示行 headers 并使它们始终可见,即使在向右滚动时也是如此。
根据您的图片,我建议您使用 JScrollPane
的 rowHeader
支持。渲染 JTable
在最好的情况下也不是一件容易的事,通常你只需要使用 table 的内置打印支持,但这并没有考虑 JScrollPane
s rowHeader
,足够大的 table 可能想要打印到多个页面,这只会变得混乱。
在你的情况下,你将不得不反汇编 JScrollPane
并自己渲染 rowHeader
、columnHeader
和主要 view
。
在"very"基本级别,这将调用计算渲染所有组件所需的整体大小,计算每个组件的偏移位置并绘制它们,就像这样...
Component columnHeader = scrollPane.getColumnHeader().getView();
Component rowHeader = scrollPane.getRowHeader().getView();
Component view = scrollPane.getViewport().getView();
int width = rowHeader.getPreferredSize().width + view.getPreferredSize().width;
int height = columnHeader.getPreferredSize().height + view.getPreferredSize().height;
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, width, height);
int xOffset = rowHeader.getPreferredSize().width;
int yOffset = columnHeader.getPreferredSize().height;
Graphics2D rowHeaderG = (Graphics2D) g2d.create();
rowHeaderG.translate(0, yOffset);
rowHeader.printAll(rowHeaderG);
rowHeaderG.dispose();
Graphics2D colHeaderG = (Graphics2D) g2d.create();
colHeaderG.translate(xOffset, 0);
columnHeader.printAll(colHeaderG);
colHeaderG.dispose();
Graphics2D viewG = (Graphics2D) g2d.create();
viewG.translate(xOffset, yOffset);
view.printAll(viewG);
viewG.dispose();
g2d.dispose();
我借用了一些旧示例的代码,并将基本思想作为示例实现。由于我没有你的代码,你将不得不尝试自己解决任何其他问题(很难通过 crystal 球进行调试),但这应该可以帮助你开始
来自 window...
到图片...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableColumnModelEvent;
import javax.swing.event.TableColumnModelListener;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class TableRowHeaderTest {
public static void main(String[] args) {
new TableRowHeaderTest();
}
public TableRowHeaderTest() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Object rowData1[][]
= {
{"", "", "", ""},
{"", "", "", ""},
{"", "", "", ""},
{"", "", "", ""}
};
Object columnNames1[] = {"HEADER 1", "HEADER 2", "HEADER 3", "HEADER 4"};
JTable table1 = new TableWithRowHeader(rowData1, columnNames1);
table1.getColumnModel().getColumn(0).setPreferredWidth(120);
JScrollPane scrollPane1 = new JScrollPane(table1);
// scrollPane1.setColumnHeaderView(null);
JButton print = new JButton("Save");
print.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
print(scrollPane1);
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(scrollPane1);
frame.add(print, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected void print(JScrollPane scrollPane) {
Component columnHeader = scrollPane.getColumnHeader().getView();
Component rowHeader = scrollPane.getRowHeader().getView();
Component view = scrollPane.getViewport().getView();
int width = rowHeader.getPreferredSize().width + view.getPreferredSize().width;
int height = columnHeader.getPreferredSize().height + view.getPreferredSize().height;
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, width, height);
int xOffset = rowHeader.getPreferredSize().width;
int yOffset = columnHeader.getPreferredSize().height;
Graphics2D rowHeaderG = (Graphics2D) g2d.create();
rowHeaderG.translate(0, yOffset);
rowHeader.printAll(rowHeaderG);
rowHeaderG.dispose();
Graphics2D colHeaderG = (Graphics2D) g2d.create();
colHeaderG.translate(xOffset, 0);
columnHeader.printAll(colHeaderG);
colHeaderG.dispose();
Graphics2D viewG = (Graphics2D) g2d.create();
viewG.translate(xOffset, yOffset);
view.printAll(viewG);
viewG.dispose();
g2d.dispose();
try {
ImageIO.write(img, "png", new File("Test.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
public class TableWithRowHeader extends JTable {
private TableRowHeader rowHeader;
public TableWithRowHeader(final Object[][] rowData, final Object[] columnNames) {
super(rowData, columnNames);
rowHeader = new TableRowHeader(this);
setGridColor(Color.LIGHT_GRAY);
}
@Override
protected void configureEnclosingScrollPane() {
// This is required as it calls a private method...
super.configureEnclosingScrollPane();
Container parent = SwingUtilities.getUnwrappedParent(this);
if (parent instanceof JViewport) {
JViewport port = (JViewport) parent;
Container gp = port.getParent();
if (gp instanceof JScrollPane) {
JScrollPane scrollPane = (JScrollPane) gp;
JViewport viewport = scrollPane.getViewport();
if (viewport == null || SwingUtilities.getUnwrappedView(viewport) != this) {
return;
}
// scrollPane.setColumnHeaderView(null);
scrollPane.setRowHeaderView(rowHeader);
}
}
}
}
public class TableRowHeader extends JTableHeader {
private JTable table;
public TableRowHeader(JTable table) {
super(table.getColumnModel());
this.table = table;
table.getColumnModel().addColumnModelListener(new TableColumnModelListener() {
@Override
public void columnAdded(TableColumnModelEvent e) {
repaint();
}
@Override
public void columnRemoved(TableColumnModelEvent e) {
repaint();
}
@Override
public void columnMoved(TableColumnModelEvent e) {
repaint();
}
@Override
public void columnMarginChanged(ChangeEvent e) {
repaint();
}
@Override
public void columnSelectionChanged(ListSelectionEvent e) {
// Don't care about this, want to highlight the row...
}
});
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
repaint();
}
});
}
public JTable getTable() {
return table;
}
@Override
public Dimension getPreferredSize() {
Dimension size = new Dimension();
JTable table = getTable();
if (table != null) {
TableColumnModel model = table.getColumnModel();
if (model != null) {
for (int index = 0; index < model.getColumnCount(); index++) {
TableColumn column = model.getColumn(index);
TableCellRenderer renderer = column.getHeaderRenderer();
if (renderer == null) {
renderer = getDefaultRenderer();
}
Component comp = renderer.getTableCellRendererComponent(table, column.getHeaderValue(), false, false, -1, index);
size.width = Math.max(comp.getPreferredSize().width, size.width);
size.height += table.getRowHeight(index);
}
}
}
return size;
}
/**
* Overridden to avoid propagating a invalidate up the tree when the
* cell renderer child is configured.
*/
@Override
public void invalidate() {
}
/**
* If the specified component is already a child of this then we don't
* bother doing anything - stacking order doesn't matter for cell
* renderer components (CellRendererPane doesn't paint anyway).
*/
@Override
protected void addImpl(Component x, Object constraints, int index) {
if (x.getParent() == this) {
return;
} else {
super.addImpl(x, constraints, index);
}
}
@Override
protected void paintComponent(Graphics g) {
// super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(getBackground());
g2d.fillRect(0, 0, getWidth(), getHeight());
JTable table = getTable();
if (table != null) {
int width = getWidth();
TableColumnModel model = table.getColumnModel();
if (model != null) {
for (int index = 0; index < model.getColumnCount(); index++) {
TableColumn column = model.getColumn(index);
TableCellRenderer renderer = column.getHeaderRenderer();
if (renderer == null) {
renderer = getDefaultRenderer();
}
boolean selected = table.getSelectedRow() == index;
Component comp = renderer.getTableCellRendererComponent(table, column.getHeaderValue(), selected, false, 0, index);
add(comp);
comp.validate();
int height = table.getRowHeight(index) - 1;
comp.setBounds(0, 0, width, height);
comp.paint(g2d);
comp.setBounds(-width, -height, 0, 0);
g2d.setColor(table.getGridColor());
g2d.drawLine(0, height, width, height);
g2d.translate(0, height + 1);
}
}
}
g2d.dispose();
removeAll();
}
}
}
我在 JScrollPane
里面有一个 JTable
,在 JPanel
下面。我需要将 table 导出为图像。如果 table 足够小,可以在 JScrollPane
中完全查看而没有滚动条,则它工作正常。但如果 table 太大,需要滚动条左右或上下移动,则导出的图像中只有部分 table 可见。
我正在使用以下代码
public BufferedImage componentToImage( Component component, boolean visible)
{
if (visible)
{
BufferedImage img = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TRANSLUCENT);
Graphics2D g2d = (Graphics2D) img.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
component.paintAll(g2d);
try
{
File outputfile = new File("C:\Users\SciOme Admin\Desktop\a.png");
ImageIO.write(img, "png", outputfile);
}
catch (IOException e)
{
e.printStackTrace();
}
return img;
}
}
我将 JScrollPane
作为组件传递的地方。
我正在附加带有滚动条的部分图像。但是我需要完整的JTable
。
我无法将 JTable
作为组件传递,因为我在 JScrollPane
中使用了两个重叠的 table。一个 table 用于仅显示行 headers 并使它们始终可见,即使在向右滚动时也是如此。
根据您的图片,我建议您使用 JScrollPane
的 rowHeader
支持。渲染 JTable
在最好的情况下也不是一件容易的事,通常你只需要使用 table 的内置打印支持,但这并没有考虑 JScrollPane
s rowHeader
,足够大的 table 可能想要打印到多个页面,这只会变得混乱。
在你的情况下,你将不得不反汇编 JScrollPane
并自己渲染 rowHeader
、columnHeader
和主要 view
。
在"very"基本级别,这将调用计算渲染所有组件所需的整体大小,计算每个组件的偏移位置并绘制它们,就像这样...
Component columnHeader = scrollPane.getColumnHeader().getView();
Component rowHeader = scrollPane.getRowHeader().getView();
Component view = scrollPane.getViewport().getView();
int width = rowHeader.getPreferredSize().width + view.getPreferredSize().width;
int height = columnHeader.getPreferredSize().height + view.getPreferredSize().height;
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, width, height);
int xOffset = rowHeader.getPreferredSize().width;
int yOffset = columnHeader.getPreferredSize().height;
Graphics2D rowHeaderG = (Graphics2D) g2d.create();
rowHeaderG.translate(0, yOffset);
rowHeader.printAll(rowHeaderG);
rowHeaderG.dispose();
Graphics2D colHeaderG = (Graphics2D) g2d.create();
colHeaderG.translate(xOffset, 0);
columnHeader.printAll(colHeaderG);
colHeaderG.dispose();
Graphics2D viewG = (Graphics2D) g2d.create();
viewG.translate(xOffset, yOffset);
view.printAll(viewG);
viewG.dispose();
g2d.dispose();
我借用了一些旧示例的代码,并将基本思想作为示例实现。由于我没有你的代码,你将不得不尝试自己解决任何其他问题(很难通过 crystal 球进行调试),但这应该可以帮助你开始
来自 window...
到图片...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableColumnModelEvent;
import javax.swing.event.TableColumnModelListener;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class TableRowHeaderTest {
public static void main(String[] args) {
new TableRowHeaderTest();
}
public TableRowHeaderTest() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Object rowData1[][]
= {
{"", "", "", ""},
{"", "", "", ""},
{"", "", "", ""},
{"", "", "", ""}
};
Object columnNames1[] = {"HEADER 1", "HEADER 2", "HEADER 3", "HEADER 4"};
JTable table1 = new TableWithRowHeader(rowData1, columnNames1);
table1.getColumnModel().getColumn(0).setPreferredWidth(120);
JScrollPane scrollPane1 = new JScrollPane(table1);
// scrollPane1.setColumnHeaderView(null);
JButton print = new JButton("Save");
print.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
print(scrollPane1);
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(scrollPane1);
frame.add(print, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected void print(JScrollPane scrollPane) {
Component columnHeader = scrollPane.getColumnHeader().getView();
Component rowHeader = scrollPane.getRowHeader().getView();
Component view = scrollPane.getViewport().getView();
int width = rowHeader.getPreferredSize().width + view.getPreferredSize().width;
int height = columnHeader.getPreferredSize().height + view.getPreferredSize().height;
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, width, height);
int xOffset = rowHeader.getPreferredSize().width;
int yOffset = columnHeader.getPreferredSize().height;
Graphics2D rowHeaderG = (Graphics2D) g2d.create();
rowHeaderG.translate(0, yOffset);
rowHeader.printAll(rowHeaderG);
rowHeaderG.dispose();
Graphics2D colHeaderG = (Graphics2D) g2d.create();
colHeaderG.translate(xOffset, 0);
columnHeader.printAll(colHeaderG);
colHeaderG.dispose();
Graphics2D viewG = (Graphics2D) g2d.create();
viewG.translate(xOffset, yOffset);
view.printAll(viewG);
viewG.dispose();
g2d.dispose();
try {
ImageIO.write(img, "png", new File("Test.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
public class TableWithRowHeader extends JTable {
private TableRowHeader rowHeader;
public TableWithRowHeader(final Object[][] rowData, final Object[] columnNames) {
super(rowData, columnNames);
rowHeader = new TableRowHeader(this);
setGridColor(Color.LIGHT_GRAY);
}
@Override
protected void configureEnclosingScrollPane() {
// This is required as it calls a private method...
super.configureEnclosingScrollPane();
Container parent = SwingUtilities.getUnwrappedParent(this);
if (parent instanceof JViewport) {
JViewport port = (JViewport) parent;
Container gp = port.getParent();
if (gp instanceof JScrollPane) {
JScrollPane scrollPane = (JScrollPane) gp;
JViewport viewport = scrollPane.getViewport();
if (viewport == null || SwingUtilities.getUnwrappedView(viewport) != this) {
return;
}
// scrollPane.setColumnHeaderView(null);
scrollPane.setRowHeaderView(rowHeader);
}
}
}
}
public class TableRowHeader extends JTableHeader {
private JTable table;
public TableRowHeader(JTable table) {
super(table.getColumnModel());
this.table = table;
table.getColumnModel().addColumnModelListener(new TableColumnModelListener() {
@Override
public void columnAdded(TableColumnModelEvent e) {
repaint();
}
@Override
public void columnRemoved(TableColumnModelEvent e) {
repaint();
}
@Override
public void columnMoved(TableColumnModelEvent e) {
repaint();
}
@Override
public void columnMarginChanged(ChangeEvent e) {
repaint();
}
@Override
public void columnSelectionChanged(ListSelectionEvent e) {
// Don't care about this, want to highlight the row...
}
});
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
repaint();
}
});
}
public JTable getTable() {
return table;
}
@Override
public Dimension getPreferredSize() {
Dimension size = new Dimension();
JTable table = getTable();
if (table != null) {
TableColumnModel model = table.getColumnModel();
if (model != null) {
for (int index = 0; index < model.getColumnCount(); index++) {
TableColumn column = model.getColumn(index);
TableCellRenderer renderer = column.getHeaderRenderer();
if (renderer == null) {
renderer = getDefaultRenderer();
}
Component comp = renderer.getTableCellRendererComponent(table, column.getHeaderValue(), false, false, -1, index);
size.width = Math.max(comp.getPreferredSize().width, size.width);
size.height += table.getRowHeight(index);
}
}
}
return size;
}
/**
* Overridden to avoid propagating a invalidate up the tree when the
* cell renderer child is configured.
*/
@Override
public void invalidate() {
}
/**
* If the specified component is already a child of this then we don't
* bother doing anything - stacking order doesn't matter for cell
* renderer components (CellRendererPane doesn't paint anyway).
*/
@Override
protected void addImpl(Component x, Object constraints, int index) {
if (x.getParent() == this) {
return;
} else {
super.addImpl(x, constraints, index);
}
}
@Override
protected void paintComponent(Graphics g) {
// super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(getBackground());
g2d.fillRect(0, 0, getWidth(), getHeight());
JTable table = getTable();
if (table != null) {
int width = getWidth();
TableColumnModel model = table.getColumnModel();
if (model != null) {
for (int index = 0; index < model.getColumnCount(); index++) {
TableColumn column = model.getColumn(index);
TableCellRenderer renderer = column.getHeaderRenderer();
if (renderer == null) {
renderer = getDefaultRenderer();
}
boolean selected = table.getSelectedRow() == index;
Component comp = renderer.getTableCellRendererComponent(table, column.getHeaderValue(), selected, false, 0, index);
add(comp);
comp.validate();
int height = table.getRowHeight(index) - 1;
comp.setBounds(0, 0, width, height);
comp.paint(g2d);
comp.setBounds(-width, -height, 0, 0);
g2d.setColor(table.getGridColor());
g2d.drawLine(0, height, width, height);
g2d.translate(0, height + 1);
}
}
}
g2d.dispose();
removeAll();
}
}
}