开发者

How to add background image in JTable when printing?

开发者 https://www.devze.com 2023-03-27 13:56 出处:网络
I want to print a JTable with background image or water mark. My code is: 开发者_Python百科 public void actionPerformed(ActionEvent ae)

I want to print a JTable with background image or water mark. My code is:

开发者_Python百科
public void actionPerformed(ActionEvent ae)
{
    boolean status=false;

    MessageFormat header = null;
    header = new MessageFormat("Header");
    MessageFormat footer = null;
    footer = new MessageFormat("Page");

    boolean fitWidth = true;
    boolean showPrintDialog = true;
    boolean interactive = true;

    /* determine the print mode */
    JTable.PrintMode mode = fitWidth ? JTable.PrintMode.FIT_WIDTH
                                     : JTable.PrintMode.NORMAL;

    try
    {
        status = jt.print(mode, header, footer,showPrintDialog,null,interactive);

        if(status ==true)
        {
            frame.dispose();
        }
    }
    catch(Exception ee)
    {
        System.out.println(ee.getMessage());
    }
}

How can I pass or set the background image in this method?


there no easy way to set whatever for BackGround for whole JTable, but JViewPort from JScrollPane can do that easilly, then doesn't matter if is inside JScrollPane a JTable or another JComponents

for example

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

class ImageAsTableBackround {

    private JScrollPane sp;
    private JTable table;
    private String[] head = {"One", "Two", "Three", "Four", "Five", "Six"};
    private String[][] data = new String[25][6];

    public void buildGUI() {
        sp = new JScrollPane();

// uncomment these codes lines for panting an image from package, 
// but then block code table = new TableBackroundPaint0(data, head);
        //sp.setViewport(new ImageViewport());
        //table = new JTable(data, head);
        //table.setOpaque(false);

// code for painting from generated code    
        table = new TableBackroundPaint0(data, head);

        table.setBackground(new Color(0, 0, 0, 0));
        table.setFillsViewportHeight(true);
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        sp.setViewportView(table);
        JFrame frame = new JFrame();
        frame.getContentPane().add(sp);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    class ImageViewport extends JViewport {

        private static final long serialVersionUID = 1L;
        private Image img;

        public ImageViewport() {
            try {
                ImageIcon image = new ImageIcon(getClass().getResource("resources/PICT6090.jpg"));
                img = image.getImage();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (img != null) {
                g.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), this);
            } else {
                g.drawString("This space for rent", 50, 50);
            }
        }
    }

    class TableBackroundPaint0 extends JTable {

        private static final long serialVersionUID = 1L;

        TableBackroundPaint0(Object[][] data, Object[] head) {
            super(data, head);
            setOpaque(false);
            ((JComponent) getDefaultRenderer(Object.class)).setOpaque(false);
        }

        @Override
        public void paintComponent(Graphics g) {
            Color background = new Color(168, 210, 241);
            Color controlColor = new Color(230, 240, 230);
            int width = getWidth();
            int height = getHeight();
            Graphics2D g2 = (Graphics2D) g;
            Paint oldPaint = g2.getPaint();
            g2.setPaint(new GradientPaint(0, 0, background, width, 0, controlColor));
            g2.fillRect(0, 0, width, height);
            g2.setPaint(oldPaint);
            for (int row : getSelectedRows()) {
                Rectangle start = getCellRect(row, 0, true);
                Rectangle end = getCellRect(row, getColumnCount() - 1, true);
                g2.setPaint(new GradientPaint(start.x, 0, controlColor, (int) ((end.x + end.width - start.x) * 1.25), 0, Color.orange));
                g2.fillRect(start.x, start.y, end.x + end.width - start.x, start.height);
            }
            super.paintComponent(g);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ImageAsTableBackround().buildGUI();
            }
        });
    }
}


The problem has two parts

  • print an image an each page
  • be sure the image "shines-through" the table

the second is addressed by @mKorbel (though not really solved because there is no nice solution :-)

To solve the first, I would go for a custom Printable and subclass JTable to return it, something like

public class BackgroundPrintable implements Printable {

    Printable tablePrintable;
    JTable table;
    MessageFormat header; 
    MessageFormat footer;
    BufferedImage background;

    public BackgroundPrintable(MessageFormat header, MessageFormat footer) {
        this.header = header;
        this.footer = footer;
    }

    public void setTablePrintable(JTable table, Printable printable) {
        tablePrintable = printable;        
        this.table = table;
    }

    @Override
    public int print(Graphics graphics, PageFormat pageFormat, 
            int pageIndex) throws PrinterException {
        printImage(graphics, pageFormat, pageIndex);
        int exists = tablePrintable.print(graphics, pageFormat, pageIndex);
        if (exists != PAGE_EXISTS) {
            return exists;
        }
        return PAGE_EXISTS;        
    }

    private void printImage(Graphics graphics, PageFormat pageFormat,
            int pageIndex) {
        // grab an untainted graphics
        Graphics2D g2d = (Graphics2D)graphics.create();
        // do the image painting 
        ....
        // cleanup  
        g2d.dispose();
    }

}

// use in JTable subclass
@Override
public Printable getPrintable(PrintMode printMode,
        MessageFormat headerFormat, MessageFormat footerFormat) {
    Printable printable = super.getPrintable(printMode, null, null);
    BackgroundPrintable custom = new BackgroundPrintable(headerFormat, footerFormat);
    custom.setTablePrintable(this, printable);
    return custom;
}

To achieve the second, both the JTable and its renderers must be transparent. Tricky, because:

  • probably only if printing - otherwise they should have their usual opacity
  • all of the renderers must be transparent, and there is no completely safe way to get hold of them all

A custom JTable could try to achieve that by forcing the rendering component's opacity in its prepareRenderer:

  @Override
   public Component prepareRenderer(TableCellRenderer renderer,
            int row, int column) {
        JComponent comp = (JComponent) super.prepareRenderer(renderer, row, column);
        if (isPaintingForPrint()) {
            comp.setOpaque(false);
        } else {
            comp.setOpaque(true);
        }   
        return comp;
   }

Actually, that's not entirely valid: the code in the else block might be the wrong-thing-to-do for naturally transparent components. No really reliable solution available, I'm afraid.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号