JTable 1点边界不会出现在网格线上

时间:2012-10-16 16:48:38

标签: java swing graphics jtable itext

我正在使用

iText版本5.3.3。 Java jdk 1.6.0

我正在开发一个报告软件,用户希望自定义具有1点黑色边框的JTable单元格,如下所示: -

JTable output

Pdf输出:

Pdf output

在两个输出上,单个边界单元格的单元格之间存在一些间隙。我们发现线条不在网格线上。 无论如何可能这些边界线作为1点线出现在网格上。 以下是使用JTable和pdfs测试上述问题的示例代码。

TableImage.java

import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.border.LineBorder;
import javax.swing.table.JTableHeader;
import com.lowagie.text.Document;
import com.lowagie.text.PageSize;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfTemplate;
import com.lowagie.text.pdf.PdfWriter;

class TableImage {

    public static void main(String[] args) throws Exception {
        Object[][] data = {
            {"Hari", new Integer(23), new Double(78.23), (true)},
            {"James", new Integer(23), new Double(47.64), (false)},
            {"Sally", new Integer(22), new Double(84.81), (true)}
        };
        String[] columns = {"Name", "Age", "GPA", "Pass"};
        JTable table = new JTable(data, columns);
        JScrollPane scroll = new JScrollPane(table);
        JPanel p = new JPanel(new BorderLayout());
        p.add(scroll, BorderLayout.CENTER);
        JOptionPane.showMessageDialog(null, p);
        JTableHeader h = table.getTableHeader();
        int x = table.getWidth();
        int y = table.getHeight();
        table.setDefaultRenderer(Object.class,
                new ColumnAlignmentRenderer(
                table.getDefaultRenderer(Object.class)));
        BufferedImage bi = new BufferedImage(x, y, BufferedImage.TYPE_INT_RGB);
        Graphics g = bi.createGraphics();
        Graphics2D g2 = (Graphics2D) g;
        table.paint(g2);
        JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
        print(table);
    }

    private static void print(JTable table) {
        Document document = new Document(PageSize.A4.rotate());
        try {
            PdfWriter writer = PdfWriter.getInstance(document,
                    new FileOutputStream("F://jTable.pdf"));
            document.open();
            PdfContentByte cb = writer.getDirectContent();
            cb.saveState();
            PdfTemplate pdfTemplate = cb.createTemplate(
                    table.getWidth(), table.getHeight());
            Graphics2D g2 = pdfTemplate.createGraphics(
                    table.getWidth(), table.getHeight());
            table.print(g2);
            cb.addTemplate(pdfTemplate, 20, 100);
            g2.dispose();
            cb.restoreState();
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
        document.close();
    }

    private TableImage() {
    }
}

ColumnAlignmentRenderer.java

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.util.HashMap;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.border.Border;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;

public class ColumnAlignmentRenderer extends DefaultTableCellRenderer {

    private TableCellRenderer mWrappedRenderer;
    private HashMap objFormatCellMap;

    public ColumnAlignmentRenderer(TableCellRenderer pWrappedRenderer) {
        mWrappedRenderer = pWrappedRenderer;
    }

    public Component getTableCellRendererComponent(JTable pTable,
            Object pValue, boolean pIsSelected,
            boolean pHasFocus, int pRow, int pColumn) {
        int hAlignment = SwingConstants.LEFT;
        int vAlignment = SwingConstants.CENTER;
        String pattern = "##000.0";
        Font font = pTable.getFont();
        Border cellBorder = pTable.getBorder();
        // Border cellBorder = BorderFactory.createCompoundBorder();
        Color backgroundColor = Color.WHITE;
        Color foregroundColor = Color.BLACK;
        // Use the wrapped renderer 
        Component renderedComponent =
                mWrappedRenderer.getTableCellRendererComponent(
                pTable, pValue, pIsSelected, pHasFocus, pRow, pColumn);
        int iLeft = 1;
        int iRight = 1;
        int iTop = 1;
        int iBottom = 1;
        Map fontAttributes = font.getAttributes();
        cellBorder = BorderFactory.createCompoundBorder(cellBorder, 
                new ZoneBorder(iTop, iLeft, iBottom, iRight, Color.BLACK));
        ((JLabel) renderedComponent).setBorder(cellBorder);
        if (pIsSelected) {
            renderedComponent.setBackground(pTable.getSelectionBackground());
        }
        return renderedComponent;
    }

    public void setHashFormatCellData(HashMap hashFormatCellData) {
        this.objFormatCellMap = hashFormatCellData;
    }
}

ZoneBorder.java

import java.awt.*;
import javax.swing.border.*;

public class ZoneBorder implements Border {

    private static final int WIDTH = 1;
    private Color color;
    private int iTop = 0, iRight = 0, iBottom = 0, iLeft = 0;

    public ZoneBorder(int T, int R, int B, int L, Color color) {
        this.iTop = T;
        this.iRight = R;
        this.iBottom = B;
        this.iLeft = L;
        this.color = color;
    }

    public boolean isBorderOpaque() {
        return false;
    }

    public Insets getBorderInsets(Component c) {
        return new Insets(iTop, iRight, iBottom, iLeft);
    }

    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
        Color oldColor = g.getColor();
        g.setColor(color);
        for (int i = 0; i < iTop; i++) {
            g.drawLine(x, y + i, x + width - 1, y + i);
        }
        //g.setColor(southColor);
        for (int i = 0; i < iBottom; i++) {
            g.drawLine(x, y + height - i - 1, x + width - 1, y + height - i - 1);
        }
        //g.setColor(eastColor);
        for (int i = 0; i < iLeft; i++) {
            g.drawLine(x + i, y, x + i, y + height - 1);
        }
        //g.setColor(westColor);
        for (int i = 0; i < iRight; i++) {
            g.drawLine(x + width - i - 1, y, x + width - i - 1, y + height - 1);
        }
        g.setColor(oldColor);
    }
}
  • 更新1

我改变了代码,用

将表格单元格的单元间距减少到0
    table.setIntercellSpacing(new Dimension(0,0));

以及将行边距更改为0

    table.setRowMargin(0);

但是当行更多时,它会在某些地方的行之间显示空白行,如下所示: -

row spacing image

为此,我使用以下代码将数据增加到9行: -

 Object[][] data = {
        {"Hari", new Integer(23), new Double(78.23), (true)},
        {"James", new Integer(23), new Double(47.64), (false)},
        {"Sally", new Integer(22), new Double(84.81), (true)},
        {"Sally", new Integer(22), new Double(84.81), (true)},
        {"Sally", new Integer(22), new Double(84.81), (true)},
        {"Hari", new Integer(23), new Double(78.23), (true)},
        {"James", new Integer(23), new Double(47.64), (false)},
        {"Hari", new Integer(23), new Double(78.23), (true)},
        {"James", new Integer(23), new Double(47.64), (false)}
    };

请就此提出建议。

**

  • 更新2

**

我观察到,如果我们看到75%zoomin JTable中的pdf看起来很准确。但是当这个JTable被看作是100%时,它显示出细胞外边界和颜色的差异。 我们有什么东西可以通过它来缩放JTable打印,即table.print(g)从75%到25%,然后再打印到pdf,即100%。如果有任何JTable扩展想法会有很大的帮助! 谢谢!

1 个答案:

答案 0 :(得分:2)

我建议使用

table.setGridColor(Color.black);

否则,如果要使用自定义渲染器

table.setIntercellSpacing(new Dimension(0,0));

(并确保渲染器正确设置边框)。

修改

就个人而言,您的更新闻起来像一个新问题(看到您的新更新代码会非常好 - 但它可能对原始问题/答案有害)。

我怀疑你的问题可能在某处(这似乎有点可疑):

Border cellBorder = pTable.getBorder();
...
cellBorder = BorderFactory.createCompoundBorder(cellBorder, 
            new ZoneBorder(iTop, iLeft, iBottom, iRight, Color.BLACK));
((JLabel) renderedComponent).setBorder(cellBorder);

你能解释为什么你抓住桌子的边框,将它与另一个边框混合,然后将结果添加到每个单元格中吗?

补充工具栏:如果您想要额外的帮助标记评论中的人,他们的回答使他们更有可能提供帮助,而不是接受他们的回答......