MessageFormat header/footerFormat how to change Font for JTable printing

前端 未结 1 2056
一整个雨季
一整个雨季 2020-12-06 13:54

in relation to this thread I have a question if someone to know if is possible to override/change larger font (Font Type, Size, Color) for MessageFormat headerFormat comings

相关标签:
1条回答
  • 2020-12-06 14:12

    As everybody already mentioned (while I was relaxing in vacation :-) - TablePrintable is tightly knitted for secrecy, no way to subclass, no way to configure the header/footer printing. The only option to hook is to wrap the table's default printable, let it do its work without header/footer and take over the header/footer printing oneself.

    The problem with the snippets shown so far is that they dont play nicely with multi-page - as known and mentioned by all authors, of course - because the default printable thinks there are no headers/footers and freely uses the space required by them. Not surprisingly :-)

    So the question is: is there a way to make to default not print into the region of the header/footer? And yeah, it is: double-wopper (ehh .. wrapper) is the answer - make the default printable believe it has less printable space by wrapping the given pageFormat into one that returns a adjusted getImageableHeight/Y. Something like:

    public class CustomPageFormat extends PageFormat {
    
        private PageFormat delegate;
        private double headerHeight;
        private double footerHeight;
    
        public CustomPageFormat(PageFormat format, double headerHeight, double footerHeight) {
            this.delegate = format;
            this.headerHeight = headerHeight;
            this.footerHeight = footerHeight;
        }
        /** 
         * @inherited <p>
         */
        @Override
        public double getImageableY() {
            return delegate.getImageableY() + headerHeight;
        }
    
        /** 
         * @inherited <p>
         */
        @Override
        public double getImageableHeight() {
            return delegate.getImageableHeight() - headerHeight - footerHeight;
        }
    
        // all other methods simply delegate
    

    Then use in the printable wrapper (footer has to be done similarly):

    public class CustomTablePrintable implements Printable {
    
        Printable tablePrintable;
        JTable table;
        MessageFormat header; 
        MessageFormat footer;
    
        public CustomTablePrintable(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 {
            // grab an untainted graphics
            Graphics2D g2d = (Graphics2D)graphics.create();
            // calculate the offsets and wrap the pageFormat
            double headerOffset = calculateHeaderHeight(g2d, pageIndex);
            CustomPageFormat wrappingPageFormat = new CustomPageFormat(pageFormat, headerOffset, 0);
            // feed the wrapped pageFormat into the default printable
            int exists = tablePrintable.print(graphics, wrappingPageFormat, pageIndex);
            if (exists != PAGE_EXISTS) {
                g2d.dispose();
                return exists;
            }
            // translate the graphics to the start of the original pageFormat and draw header
            g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
            printHeader(g2d, pageIndex, (int) pageFormat.getImageableWidth());
            g2d.dispose();
    
            return PAGE_EXISTS;        
        }
    
    
        protected double calculateHeaderHeight(Graphics2D g, int pageIndex) {
            if (header == null) return 0;
            Object[] pageNumber = new Object[]{new Integer(pageIndex + 1)};
            String text = header.format(pageNumber);
            Font headerFont = table.getFont().deriveFont(Font.BOLD, 18f);
            g.setFont(headerFont);
            Rectangle2D rect = g.getFontMetrics().getStringBounds(text, g);
            return rect.getHeight();
        }
    
        protected void printHeader(Graphics2D g, int pageIndex, int imgWidth) {
            Object[] pageNumber = new Object[]{new Integer(pageIndex + 1)};
            String text = header.format(pageNumber);
            Font headerFont = table.getFont().deriveFont(Font.BOLD, 18f);
            g.setFont(headerFont);
            Rectangle2D rect = g.getFontMetrics().getStringBounds(text, g);
            // following is c&p from TablePrintable printText
            int tx;
    
            // if the text is small enough to fit, center it
            if (rect.getWidth() < imgWidth) {
                tx = (int) ((imgWidth - rect.getWidth()) / 2);
    
                // otherwise, if the table is LTR, ensure the left side of
                // the text shows; the right can be clipped
            } else if (table.getComponentOrientation().isLeftToRight()) {
                tx = 0;
    
                // otherwise, ensure the right side of the text shows
            } else {
                tx = -(int) (Math.ceil(rect.getWidth()) - imgWidth);
            }
    
            int ty = (int) Math.ceil(Math.abs(rect.getY()));
            g.setColor(Color.BLACK);
            g.drawString(text, tx, ty);
    
        }
    }
    

    And at the end return that from table's getPrintable, like:

        final JTable table = new JTable(myModel){
    
            /** 
             * @inherited <p>
             */
            @Override
            public Printable getPrintable(PrintMode printMode,
                    MessageFormat headerFormat, MessageFormat footerFormat) {
                Printable printable = super.getPrintable(printMode, null, null);
                CustomTablePrintable custom = new CustomTablePrintable(headerFormat, footerFormat);
                custom.setTablePrintable(this, printable);
                return custom;
            }
    
        };
    

    printHeader/Footer can be implemented to do whatever is required.

    At the end of the day: the answer to the question "do I need to call g.drawString(...)" still is "Yes". But at least it's safely outside of the table itself :-)

    0 讨论(0)
提交回复
热议问题