问:
JTable multiple header with new lines
In java swing JTable, I want to print multiple header with new lines from MessageFormat.

```<code>MessageFormat header = new MessageFormat("Products Details" + '\n' + "xyz suppliers");
MessageFormat footer = new MessageFormat("Page{1,number,integer}");
tbl_country.print(JTable.PrintMode.FIT_WIDTH, header, footer);
</code>```

I had try lot of codes but new lines header does not work.

答:
Finally i found answer to print multiple header with new line of JTable data as below:-
My TablePrintable.java

```<code>import javax.swing.table.*;
import java.awt.*;
import java.awt.print.*;
import java.awt.geom.*;
import java.text.MessageFormat;
import javax.swing.JTable;

/**
 * An implementation of <code>Printable</code> for printing
 * <code>JTable</code>s.
 * <p>
 * This implementation spreads table rows naturally in sequence across multiple
 * pages, fitting as many rows as possible per page. The distribution of
 * columns, on the other hand, is controlled by a printing mode parameter passed
 * to the constructor. When <code>JTable.PrintMode.NORMAL</code> is used, the
 * implementation handles columns in a similar manner to how it handles rows,
 * spreading them across multiple pages (in an order consistent with the table's
 * <code>ComponentOrientation</code>). When
 * <code>JTable.PrintMode.FIT_WIDTH</code> is given, the implementation scales
 * the output smaller if necessary, to ensure that all columns fit on the page.
 * (Note that width and height are scaled equally, ensuring that the aspect
 * ratio remains the same).
 * <p>
 * The portion of table printed on each page is headed by the appropriate
 * section of the table's <code>JTableHeader</code>.
 * <p>
 * Header and footer text can be added to the output by providing
 * <code>MessageFormat</code> instances to the constructor. The printing code
 * requests Strings from the formats by calling their <code>format</code> method
 * with a single parameter: an <code>Object</code> array containing a single
 * element of type <code>Integer</code>, representing the current page number.
 * <p>
 * There are certain circumstances where this <code>Printable</code> cannot fit
 * items appropriately, resulting in clipped output. These are:
 * <ul>
 * <li>In any mode, when the header or footer text is too wide to fit completely
 * in the printable area. The implementation prints as much of the text as
 * possible starting from the beginning, as determined by the table's
 * <code>ComponentOrientation</code>.
 * <li>In any mode, when a row is too tall to fit in the printable area. The
 * upper most portion of the row is printed and no lower border is shown.
 * <li>In <code>JTable.PrintMode.NORMAL</code> when a column is too wide to fit
 * in the printable area. The center of the column is printed and no left and
 * right borders are shown.
 * </ul>
 * <p>
 * It is entirely valid for a developer to wrap this <code>Printable</code>
 * inside another in order to create complex reports and documents. They may
 * even request that different pages be rendered into different sized printable
 * areas. The implementation was designed to handle this by performing most of
 * its calculations on the fly. However, providing different sizes works best
 * when <code>JTable.PrintMode.FIT_WIDTH</code> is used, or when only the
 * printable width is changed between pages. This is because when it is printing
 * a set of rows in <code>JTable.PrintMode.NORMAL</code> and the implementation
 * determines a need to distribute columns across pages, it assumes that all of
 * those rows will fit on each subsequent page needed to fit the columns.
 * <p>
 * It is the responsibility of the developer to ensure that the table is not
 * modified in any way after this <code>Printable</code> is created (invalid
 * modifications include changes in: size, renderers, or underlying data). The
 * behavior of this <code>Printable</code> is undefined if the table is changed
 * at any time after creation.
 *
 * @author Shannon Hickey
 * @version 1.41 11/17/05
 */
class MyTablePrintable implements Printable {

    /**
     * The table to print.
     */
    private JTable table;

    /**
     * For quick reference to the table's header.
     */
    private JTableHeader header;

    /**
     * For quick reference to the table's column model.
     */
    private TableColumnModel colModel;

    /**
     * To save multiple calculations of total column width.
     */
    private int totalColWidth;

    /**
     * The printing mode of this printable.
     */
    private JTable.PrintMode printMode;

    /**
     * Provides the header text for the table.
     */
    private MessageFormat[] headerFormat;

    /**
     * Provides the footer text for the table.
     */
    private MessageFormat[] footerFormat;

    /**
     * The most recent page index asked to print.
     */
    private int last = -1;

    /**
     * The next row to print.
     */
    private int row = 0;

    /**
     * The next column to print.
     */
    private int col = 0;

    /**
     * Used to store an area of the table to be printed.
     */
    private final Rectangle clip = new Rectangle(0, 0, 0, 0);

    /**
     * Used to store an area of the table's header to be printed.
     */
    private final Rectangle hclip = new Rectangle(0, 0, 0, 0);

    /**
     * Saves the creation of multiple rectangles.
     */
    private final Rectangle tempRect = new Rectangle(0, 0, 0, 0);

    /**
     * Vertical space to leave between table and header/footer text.
     */
    private static final int H_F_SPACE = 8;

    /**
     * Font size for the header text.
     */
    private static final float HEADER_FONT_SIZE = 15.0f;

    /**
     * Font size for the footer text.
     */
    private static final float FOOTER_FONT_SIZE = 10.0f;

    /**
     * The font to use in rendering header text.
     */
    private Font headerFont;

    /**
     * The font to use in rendering footer text.
     */
    private Font footerFont;

    /**
     * Create a new <code>TablePrintable</code> for the given
     * <code>JTable</code>. Header and footer text can be specified using the
     * two <code>MessageFormat</code> parameters. When called upon to provide a
     * String, each format is given the current page number.
     *
     * @param table the table to print
     * @param printMode the printing mode for this printable
     * @param headerFormat a <code>MessageFormat</code> specifying the text to
     * be used in printing a header, or null for none
     * @param footerFormat a <code>MessageFormat</code> specifying the text to
     * be used in printing a footer, or null for none
     * @throws IllegalArgumentException if passed an invalid print mode
     */
    public MyTablePrintable(JTable table,
            JTable.PrintMode printMode,
            MessageFormat[] headerFormat,
            MessageFormat[] footerFormat) {

        this.table = table;

        header = table.getTableHeader();
        colModel = table.getColumnModel();
        totalColWidth = colModel.getTotalColumnWidth();

        if (header != null) {
            // the header clip height can be set once since it's unchanging
            hclip.height = header.getHeight();
        }

        this.printMode = printMode;

        this.headerFormat = headerFormat;
        this.footerFormat = footerFormat;

        // derive the header and footer font from the table's font
        headerFont = table.getFont().deriveFont(Font.BOLD,
                HEADER_FONT_SIZE);
        footerFont = table.getFont().deriveFont(Font.PLAIN,
                FOOTER_FONT_SIZE);
    }

    /**
     * Prints the specified page of the table into the given {@link Graphics}
     * context, in the specified format.
     *
     * @param graphics the context into which the page is drawn
     * @param pageFormat the size and orientation of the page being drawn
     * @param pageIndex the zero based index of the page to be drawn
     * @return PAGE_EXISTS if the page is rendered successfully, or NO_SUCH_PAGE
     * if a non-existent page index is specified
     * @throws PrinterException if an error causes printing to be aborted
     */
    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
            throws PrinterException {

        // for easy access to these values
        final int imgWidth = (int) pageFormat.getImageableWidth();
        final int imgHeight = (int) pageFormat.getImageableHeight();

        if (imgWidth <= 0) {
            throw new PrinterException("Width of printable area is too small.");
        }

        // to pass the page number when formatting the header and footer text
        Object[] pageNumber = new Object[]{new Integer(pageIndex + 1)};

        // fetch the formatted header text, if any
        String[] headerText = null;
        if (headerFormat != null) {
            headerText = new String[headerFormat.length];
            for (int i = 0; i < headerFormat.length; i++) {
                headerText[i] = headerFormat[i].format(pageNumber);
            }
        }

        // fetch the formatted footer text, if any
        String[] footerText = null;
        if (footerFormat != null) {
            footerText = new String[footerFormat.length];
            for (int i = 0; i < footerFormat.length; i++) {
                footerText[i] = footerFormat[i].format(pageNumber);
            }
        }

        // to store the bounds of the header and footer text
        Rectangle2D[] hRect = null;
        Rectangle2D[] fRect = null;

        // the amount of vertical space needed for the header and footer text
        int headerTextSpace = 15;
        int footerTextSpace = 0;

        // the amount of vertical space available for printing the table
        int availableSpace = imgHeight;

        // if there's header text, find out how much space is needed for it
        // and subtract that from the available space
        if (headerText != null) {
            graphics.setFont(headerFont);
            hRect = new Rectangle2D[headerText.length];
            for (int i = 0; i < headerText.length; i++) {
                hRect[i] = graphics.getFontMetrics().getStringBounds(headerText[i], graphics);
                headerTextSpace += (int) Math.ceil(hRect[i].getHeight());
            }
            availableSpace -= headerTextSpace + H_F_SPACE;
        }

        // if there's footer text, find out how much space is needed for it
        // and subtract that from the available space
        if (footerText != null) {
            graphics.setFont(footerFont);
            fRect = new Rectangle2D[footerText.length];
            for (int i = 0; i < footerText.length; i++) {
                fRect[i] = graphics.getFontMetrics().getStringBounds(footerText[i], graphics);
                footerTextSpace += (int) Math.ceil(fRect[i].getHeight());
            }
            availableSpace -= footerTextSpace + H_F_SPACE;
        }

        if (availableSpace <= 0) {
            throw new PrinterException("Height of printable area is too small.");
        }

        // depending on the print mode, we may need a scale factor to
        // fit the table's entire width on the page
        double sf = 1.0D;
        if (printMode == JTable.PrintMode.FIT_WIDTH
                && totalColWidth > imgWidth) {

            // if not, we would have thrown an acception previously
            assert imgWidth > 0;

            // it must be, according to the if-condition, since imgWidth > 0
            assert totalColWidth > 1;

            sf = (double) imgWidth / (double) totalColWidth;
        }

        // dictated by the previous two assertions
        assert sf > 0;

        // This is in a loop for two reasons:
        // First, it allows us to catch up in case we're called starting
        // with a non-zero pageIndex. Second, we know that we can be called
        // for the same page multiple times. The condition of this while
        // loop acts as a check, ensuring that we don't attempt to do the
        // calculations again when we are called subsequent times for the
        // same page.
        while (last < pageIndex) {
            // if we are finished all columns in all rows
            if (row >= table.getRowCount() && col == 0) {
                return NO_SUCH_PAGE;
            }

            // rather than multiplying every row and column by the scale factor
            // in findNextClip, just pass a width and height that have already
            // been divided by it
            int scaledWidth = (int) (imgWidth / sf);
            int scaledHeight = (int) ((availableSpace - hclip.height) / sf);

            // calculate the area of the table to be printed for this page
            findNextClip(scaledWidth, scaledHeight);

            last++;
        }

        // translate into the co-ordinate system of the pageFormat
        Graphics2D g2d = (Graphics2D) graphics;
        g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());

        // to save and store the transform
        AffineTransform oldTrans;

        // if there's footer text, print it at the bottom of the imageable area
        if (footerText != null) {
            oldTrans = g2d.getTransform();

            g2d.translate(0, imgHeight - footerTextSpace);
            for (int i = 0; i < footerText.length; i++) {
                printText(g2d, footerText[i], fRect[i], footerFont, i, imgWidth);
            }

            g2d.setTransform(oldTrans);
        }

        // if there's header text, print it at the top of the imageable area
        // and then translate downwards
        if (headerText != null) {
            for (int i = 0; i < headerText.length; i++) {
                printText(g2d, headerText[i], hRect[i], headerFont, i, imgWidth);
            }

            g2d.translate(0, headerTextSpace + H_F_SPACE);
        }

        // constrain the table output to the available space
        tempRect.x = 0;
        tempRect.y = 0;
        tempRect.width = imgWidth;
        tempRect.height = availableSpace;
        g2d.clip(tempRect);

        // if we have a scale factor, scale the graphics object to fit
        // the entire width
        if (sf != 1.0D) {
            g2d.scale(sf, sf);

            // otherwise, ensure that the current portion of the table is
            // centered horizontally
        } else {
            int diff = (imgWidth - clip.width) / 2;
            g2d.translate(diff, 0);
        }

        // store the old transform and clip for later restoration
        oldTrans = g2d.getTransform();
        Shape oldClip = g2d.getClip();

        // if there's a table header, print the current section and
        // then translate downwards
        if (header != null) {
            hclip.x = clip.x;
            hclip.width = clip.width;

            g2d.translate(-hclip.x, 0);
            g2d.clip(hclip);
            header.print(g2d);

            // restore the original transform and clip
            g2d.setTransform(oldTrans);
            g2d.setClip(oldClip);

            // translate downwards
            g2d.translate(0, hclip.height);
        }

        // print the current section of the table
        g2d.translate(-clip.x, -clip.y);
        g2d.clip(clip);
        table.print(g2d);

        // restore the original transform and clip
        g2d.setTransform(oldTrans);
        g2d.setClip(oldClip);

        // draw a box around the table
        g2d.setColor(Color.BLACK);
        g2d.drawRect(0, 0, clip.width, hclip.height + clip.height);

        return PAGE_EXISTS;
    }

    /**
     * A helper method that encapsulates common code for rendering the header
     * and footer text.
     *
     * @param g2d the graphics to draw into
     * @param text the text to draw, non null
     * @param rect the bounding rectangle for this text, as calculated at the
     * given font, non null
     * @param font the font to draw the text in, non null
     * @param imgWidth the width of the area to draw into
     */
    private void printText(Graphics2D g2d,
            String text,
            Rectangle2D rect,
            Font font,
            int textIndex,
            int imgWidth) {

        //int tx = -(int)(Math.ceil(rect.getWidth()) - imgWidth); // for right allign
        int tx = 0; // for left allign

        int ty = textIndex * (int) Math.ceil(Math.abs(rect.getY()));
        g2d.setColor(Color.BLACK);
        g2d.setFont(font);
        g2d.drawString(text, tx, ty);
    }

    /**
     * Calculate the area of the table to be printed for the next page. This
     * should only be called if there are rows and columns left to print.
     *
     * To avoid an infinite loop in printing, this will always put at least one
     * cell on each page.
     *
     * @param pw the width of the area to print in
     * @param ph the height of the area to print in
     */
    private void findNextClip(int pw, int ph) {
        final boolean ltr = table.getComponentOrientation().isLeftToRight();

        // if we're ready to start a new set of rows
        if (col == 0) {
            if (ltr) {
                // adjust clip to the left of the first column
                clip.x = 0;
            } else {
                // adjust clip to the right of the first column
                clip.x = totalColWidth;
            }

            // adjust clip to the top of the next set of rows
            clip.y += clip.height;

            // adjust clip width and height to be zero
            clip.width = 0;
            clip.height = 0;

            // fit as many rows as possible, and at least one
            int rowCount = table.getRowCount();
            int rowHeight = table.getRowHeight(row);
            do {
                clip.height += rowHeight;

                if (++row >= rowCount) {
                    break;
                }

                rowHeight = table.getRowHeight(row);
            } while (clip.height + rowHeight <= ph);
        }

        // we can short-circuit for JTable.PrintMode.FIT_WIDTH since
        // we'll always fit all columns on the page
        if (printMode == JTable.PrintMode.FIT_WIDTH) {
            clip.x = 0;
            clip.width = totalColWidth;
            return;
        }

        if (ltr) {
            // adjust clip to the left of the next set of columns
            clip.x += clip.width;
        }

        // adjust clip width to be zero
        clip.width = 0;

        // fit as many columns as possible, and at least one
        int colCount = table.getColumnCount();
        int colWidth = colModel.getColumn(col).getWidth();
        do {
            clip.width += colWidth;
            if (!ltr) {
                clip.x -= colWidth;
            }

            if (++col >= colCount) {
                // reset col to 0 to indicate we're finished all columns
                col = 0;

                break;
            }

            colWidth = colModel.getColumn(col).getWidth();
        } while (clip.width + colWidth <= pw);

    }

}
</code>```

To print while print buttom clicked

```<code>String name = lblCompanyName.getText();
        String address = lblAddress.getText();

        try {
            PrinterJob job = PrinterJob.getPrinterJob();

            MessageFormat[] header = new MessageFormat[3];

            header[0] = new MessageFormat("line 1");
            header[1] = new MessageFormat("                    " + name);
            header[2] = new MessageFormat("                  " + address);

            MessageFormat[] footer = new MessageFormat[2];
            footer[0] = new MessageFormat("");
            footer[1] = new MessageFormat("-{1}-");
            job.setPrintable(new MyTablePrintable(table, JTable.PrintMode.FIT_WIDTH, header, footer));
            job.printDialog();
            job.print();

        } catch (Exception ex) {
        }
</code>```

result

Title: JTable multiple header with new lines

Body:
In java swing JTable, I want to print multiple header with new lines from MessageFormat.

MessageFormat header = new MessageFormat("Products Details" + '\n' + "xyz suppliers");
MessageFormat footer = new MessageFormat("Page{1,number,integer}");
tbl_country.print(JTable.PrintMode.FIT_WIDTH, header, footer);

I had try lot of codes but new lines header does not work.

Body:
Finally i found answer to print multiple header with new line of JTable data as below:-
My TablePrintable.java

import javax.swing.table.*;
import java.awt.*;
import java.awt.print.*;
import java.awt.geom.*;
import java.text.MessageFormat;
import javax.swing.JTable;

/**
 * An implementation of <code>Printable</code> for printing
 * <code>JTable</code>s.
 * <p>
 * This implementation spreads table rows naturally in sequence across multiple
 * pages, fitting as many rows as possible per page. The distribution of
 * columns, on the other hand, is controlled by a printing mode parameter passed
 * to the constructor. When <code>JTable.PrintMode.NORMAL</code> is used, the
 * implementation handles columns in a similar manner to how it handles rows,
 * spreading them across multiple pages (in an order consistent with the table's
 * <code>ComponentOrientation</code>). When
 * <code>JTable.PrintMode.FIT_WIDTH</code> is given, the implementation scales
 * the output smaller if necessary, to ensure that all columns fit on the page.
 * (Note that width and height are scaled equally, ensuring that the aspect
 * ratio remains the same).
 * <p>
 * The portion of table printed on each page is headed by the appropriate
 * section of the table's <code>JTableHeader</code>.
 * <p>
 * Header and footer text can be added to the output by providing
 * <code>MessageFormat</code> instances to the constructor. The printing code
 * requests Strings from the formats by calling their <code>format</code> method
 * with a single parameter: an <code>Object</code> array containing a single
 * element of type <code>Integer</code>, representing the current page number.
 * <p>
 * There are certain circumstances where this <code>Printable</code> cannot fit
 * items appropriately, resulting in clipped output. These are:
 * <ul>
 * <li>In any mode, when the header or footer text is too wide to fit completely
 * in the printable area. The implementation prints as much of the text as
 * possible starting from the beginning, as determined by the table's
 * <code>ComponentOrientation</code>.
 * <li>In any mode, when a row is too tall to fit in the printable area. The
 * upper most portion of the row is printed and no lower border is shown.
 * <li>In <code>JTable.PrintMode.NORMAL</code> when a column is too wide to fit
 * in the printable area. The center of the column is printed and no left and
 * right borders are shown.
 * </ul>
 * <p>
 * It is entirely valid for a developer to wrap this <code>Printable</code>
 * inside another in order to create complex reports and documents. They may
 * even request that different pages be rendered into different sized printable
 * areas. The implementation was designed to handle this by performing most of
 * its calculations on the fly. However, providing different sizes works best
 * when <code>JTable.PrintMode.FIT_WIDTH</code> is used, or when only the
 * printable width is changed between pages. This is because when it is printing
 * a set of rows in <code>JTable.PrintMode.NORMAL</code> and the implementation
 * determines a need to distribute columns across pages, it assumes that all of
 * those rows will fit on each subsequent page needed to fit the columns.
 * <p>
 * It is the responsibility of the developer to ensure that the table is not
 * modified in any way after this <code>Printable</code> is created (invalid
 * modifications include changes in: size, renderers, or underlying data). The
 * behavior of this <code>Printable</code> is undefined if the table is changed
 * at any time after creation.
 *
 * @author Shannon Hickey
 * @version 1.41 11/17/05
 */
class MyTablePrintable implements Printable {

    /**
     * The table to print.
     */
    private JTable table;

    /**
     * For quick reference to the table's header.
     */
    private JTableHeader header;

    /**
     * For quick reference to the table's column model.
     */
    private TableColumnModel colModel;

    /**
     * To save multiple calculations of total column width.
     */
    private int totalColWidth;

    /**
     * The printing mode of this printable.
     */
    private JTable.PrintMode printMode;

    /**
     * Provides the header text for the table.
     */
    private MessageFormat[] headerFormat;

    /**
     * Provides the footer text for the table.
     */
    private MessageFormat[] footerFormat;

    /**
     * The most recent page index asked to print.
     */
    private int last = -1;

    /**
     * The next row to print.
     */
    private int row = 0;

    /**
     * The next column to print.
     */
    private int col = 0;

    /**
     * Used to store an area of the table to be printed.
     */
    private final Rectangle clip = new Rectangle(0, 0, 0, 0);

    /**
     * Used to store an area of the table's header to be printed.
     */
    private final Rectangle hclip = new Rectangle(0, 0, 0, 0);

    /**
     * Saves the creation of multiple rectangles.
     */
    private final Rectangle tempRect = new Rectangle(0, 0, 0, 0);

    /**
     * Vertical space to leave between table and header/footer text.
     */
    private static final int H_F_SPACE = 8;

    /**
     * Font size for the header text.
     */
    private static final float HEADER_FONT_SIZE = 15.0f;

    /**
     * Font size for the footer text.
     */
    private static final float FOOTER_FONT_SIZE = 10.0f;

    /**
     * The font to use in rendering header text.
     */
    private Font headerFont;

    /**
     * The font to use in rendering footer text.
     */
    private Font footerFont;

    /**
     * Create a new <code>TablePrintable</code> for the given
     * <code>JTable</code>. Header and footer text can be specified using the
     * two <code>MessageFormat</code> parameters. When called upon to provide a
     * String, each format is given the current page number.
     *
     * @param table the table to print
     * @param printMode the printing mode for this printable
     * @param headerFormat a <code>MessageFormat</code> specifying the text to
     * be used in printing a header, or null for none
     * @param footerFormat a <code>MessageFormat</code> specifying the text to
     * be used in printing a footer, or null for none
     * @throws IllegalArgumentException if passed an invalid print mode
     */
    public MyTablePrintable(JTable table,
            JTable.PrintMode printMode,
            MessageFormat[] headerFormat,
            MessageFormat[] footerFormat) {

        this.table = table;

        header = table.getTableHeader();
        colModel = table.getColumnModel();
        totalColWidth = colModel.getTotalColumnWidth();

        if (header != null) {
            // the header clip height can be set once since it's unchanging
            hclip.height = header.getHeight();
        }

        this.printMode = printMode;

        this.headerFormat = headerFormat;
        this.footerFormat = footerFormat;

        // derive the header and footer font from the table's font
        headerFont = table.getFont().deriveFont(Font.BOLD,
                HEADER_FONT_SIZE);
        footerFont = table.getFont().deriveFont(Font.PLAIN,
                FOOTER_FONT_SIZE);
    }

    /**
     * Prints the specified page of the table into the given {@link Graphics}
     * context, in the specified format.
     *
     * @param graphics the context into which the page is drawn
     * @param pageFormat the size and orientation of the page being drawn
     * @param pageIndex the zero based index of the page to be drawn
     * @return PAGE_EXISTS if the page is rendered successfully, or NO_SUCH_PAGE
     * if a non-existent page index is specified
     * @throws PrinterException if an error causes printing to be aborted
     */
    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
            throws PrinterException {

        // for easy access to these values
        final int imgWidth = (int) pageFormat.getImageableWidth();
        final int imgHeight = (int) pageFormat.getImageableHeight();

        if (imgWidth <= 0) {
            throw new PrinterException("Width of printable area is too small.");
        }

        // to pass the page number when formatting the header and footer text
        Object[] pageNumber = new Object[]{new Integer(pageIndex + 1)};

        // fetch the formatted header text, if any
        String[] headerText = null;
        if (headerFormat != null) {
            headerText = new String[headerFormat.length];
            for (int i = 0; i < headerFormat.length; i++) {
                headerText[i] = headerFormat[i].format(pageNumber);
            }
        }

        // fetch the formatted footer text, if any
        String[] footerText = null;
        if (footerFormat != null) {
            footerText = new String[footerFormat.length];
            for (int i = 0; i < footerFormat.length; i++) {
                footerText[i] = footerFormat[i].format(pageNumber);
            }
        }

        // to store the bounds of the header and footer text
        Rectangle2D[] hRect = null;
        Rectangle2D[] fRect = null;

        // the amount of vertical space needed for the header and footer text
        int headerTextSpace = 15;
        int footerTextSpace = 0;

        // the amount of vertical space available for printing the table
        int availableSpace = imgHeight;

        // if there's header text, find out how much space is needed for it
        // and subtract that from the available space
        if (headerText != null) {
            graphics.setFont(headerFont);
            hRect = new Rectangle2D[headerText.length];
            for (int i = 0; i < headerText.length; i++) {
                hRect[i] = graphics.getFontMetrics().getStringBounds(headerText[i], graphics);
                headerTextSpace += (int) Math.ceil(hRect[i].getHeight());
            }
            availableSpace -= headerTextSpace + H_F_SPACE;
        }

        // if there's footer text, find out how much space is needed for it
        // and subtract that from the available space
        if (footerText != null) {
            graphics.setFont(footerFont);
            fRect = new Rectangle2D[footerText.length];
            for (int i = 0; i < footerText.length; i++) {
                fRect[i] = graphics.getFontMetrics().getStringBounds(footerText[i], graphics);
                footerTextSpace += (int) Math.ceil(fRect[i].getHeight());
            }
            availableSpace -= footerTextSpace + H_F_SPACE;
        }

        if (availableSpace <= 0) {
            throw new PrinterException("Height of printable area is too small.");
        }

        // depending on the print mode, we may need a scale factor to
        // fit the table's entire width on the page
        double sf = 1.0D;
        if (printMode == JTable.PrintMode.FIT_WIDTH
                && totalColWidth > imgWidth) {

            // if not, we would have thrown an acception previously
            assert imgWidth > 0;

            // it must be, according to the if-condition, since imgWidth > 0
            assert totalColWidth > 1;

            sf = (double) imgWidth / (double) totalColWidth;
        }

        // dictated by the previous two assertions
        assert sf > 0;

        // This is in a loop for two reasons:
        // First, it allows us to catch up in case we're called starting
        // with a non-zero pageIndex. Second, we know that we can be called
        // for the same page multiple times. The condition of this while
        // loop acts as a check, ensuring that we don't attempt to do the
        // calculations again when we are called subsequent times for the
        // same page.
        while (last < pageIndex) {
            // if we are finished all columns in all rows
            if (row >= table.getRowCount() && col == 0) {
                return NO_SUCH_PAGE;
            }

            // rather than multiplying every row and column by the scale factor
            // in findNextClip, just pass a width and height that have already
            // been divided by it
            int scaledWidth = (int) (imgWidth / sf);
            int scaledHeight = (int) ((availableSpace - hclip.height) / sf);

            // calculate the area of the table to be printed for this page
            findNextClip(scaledWidth, scaledHeight);

            last++;
        }

        // translate into the co-ordinate system of the pageFormat
        Graphics2D g2d = (Graphics2D) graphics;
        g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());

        // to save and store the transform
        AffineTransform oldTrans;

        // if there's footer text, print it at the bottom of the imageable area
        if (footerText != null) {
            oldTrans = g2d.getTransform();

            g2d.translate(0, imgHeight - footerTextSpace);
            for (int i = 0; i < footerText.length; i++) {
                printText(g2d, footerText[i], fRect[i], footerFont, i, imgWidth);
            }

            g2d.setTransform(oldTrans);
        }

        // if there's header text, print it at the top of the imageable area
        // and then translate downwards
        if (headerText != null) {
            for (int i = 0; i < headerText.length; i++) {
                printText(g2d, headerText[i], hRect[i], headerFont, i, imgWidth);
            }

            g2d.translate(0, headerTextSpace + H_F_SPACE);
        }

        // constrain the table output to the available space
        tempRect.x = 0;
        tempRect.y = 0;
        tempRect.width = imgWidth;
        tempRect.height = availableSpace;
        g2d.clip(tempRect);

        // if we have a scale factor, scale the graphics object to fit
        // the entire width
        if (sf != 1.0D) {
            g2d.scale(sf, sf);

            // otherwise, ensure that the current portion of the table is
            // centered horizontally
        } else {
            int diff = (imgWidth - clip.width) / 2;
            g2d.translate(diff, 0);
        }

        // store the old transform and clip for later restoration
        oldTrans = g2d.getTransform();
        Shape oldClip = g2d.getClip();

        // if there's a table header, print the current section and
        // then translate downwards
        if (header != null) {
            hclip.x = clip.x;
            hclip.width = clip.width;

            g2d.translate(-hclip.x, 0);
            g2d.clip(hclip);
            header.print(g2d);

            // restore the original transform and clip
            g2d.setTransform(oldTrans);
            g2d.setClip(oldClip);

            // translate downwards
            g2d.translate(0, hclip.height);
        }

        // print the current section of the table
        g2d.translate(-clip.x, -clip.y);
        g2d.clip(clip);
        table.print(g2d);

        // restore the original transform and clip
        g2d.setTransform(oldTrans);
        g2d.setClip(oldClip);

        // draw a box around the table
        g2d.setColor(Color.BLACK);
        g2d.drawRect(0, 0, clip.width, hclip.height + clip.height);

        return PAGE_EXISTS;
    }

    /**
     * A helper method that encapsulates common code for rendering the header
     * and footer text.
     *
     * @param g2d the graphics to draw into
     * @param text the text to draw, non null
     * @param rect the bounding rectangle for this text, as calculated at the
     * given font, non null
     * @param font the font to draw the text in, non null
     * @param imgWidth the width of the area to draw into
     */
    private void printText(Graphics2D g2d,
            String text,
            Rectangle2D rect,
            Font font,
            int textIndex,
            int imgWidth) {

        //int tx = -(int)(Math.ceil(rect.getWidth()) - imgWidth); // for right allign
        int tx = 0; // for left allign

        int ty = textIndex * (int) Math.ceil(Math.abs(rect.getY()));
        g2d.setColor(Color.BLACK);
        g2d.setFont(font);
        g2d.drawString(text, tx, ty);
    }

    /**
     * Calculate the area of the table to be printed for the next page. This
     * should only be called if there are rows and columns left to print.
     *
     * To avoid an infinite loop in printing, this will always put at least one
     * cell on each page.
     *
     * @param pw the width of the area to print in
     * @param ph the height of the area to print in
     */
    private void findNextClip(int pw, int ph) {
        final boolean ltr = table.getComponentOrientation().isLeftToRight();

        // if we're ready to start a new set of rows
        if (col == 0) {
            if (ltr) {
                // adjust clip to the left of the first column
                clip.x = 0;
            } else {
                // adjust clip to the right of the first column
                clip.x = totalColWidth;
            }

            // adjust clip to the top of the next set of rows
            clip.y += clip.height;

            // adjust clip width and height to be zero
            clip.width = 0;
            clip.height = 0;

            // fit as many rows as possible, and at least one
            int rowCount = table.getRowCount();
            int rowHeight = table.getRowHeight(row);
            do {
                clip.height += rowHeight;

                if (++row >= rowCount) {
                    break;
                }

                rowHeight = table.getRowHeight(row);
            } while (clip.height + rowHeight <= ph);
        }

        // we can short-circuit for JTable.PrintMode.FIT_WIDTH since
        // we'll always fit all columns on the page
        if (printMode == JTable.PrintMode.FIT_WIDTH) {
            clip.x = 0;
            clip.width = totalColWidth;
            return;
        }

        if (ltr) {
            // adjust clip to the left of the next set of columns
            clip.x += clip.width;
        }

        // adjust clip width to be zero
        clip.width = 0;

        // fit as many columns as possible, and at least one
        int colCount = table.getColumnCount();
        int colWidth = colModel.getColumn(col).getWidth();
        do {
            clip.width += colWidth;
            if (!ltr) {
                clip.x -= colWidth;
            }

            if (++col >= colCount) {
                // reset col to 0 to indicate we're finished all columns
                col = 0;

                break;
            }

            colWidth = colModel.getColumn(col).getWidth();
        } while (clip.width + colWidth <= pw);

    }

}

To print while print buttom clicked

String name = lblCompanyName.getText();
        String address = lblAddress.getText();

        try {
            PrinterJob job = PrinterJob.getPrinterJob();

            MessageFormat[] header = new MessageFormat[3];

            header[0] = new MessageFormat("line 1");
            header[1] = new MessageFormat("                    " + name);
            header[2] = new MessageFormat("                  " + address);

            MessageFormat[] footer = new MessageFormat[2];
            footer[0] = new MessageFormat("");
            footer[1] = new MessageFormat("-{1}-");
            job.setPrintable(new MyTablePrintable(table, JTable.PrintMode.FIT_WIDTH, header, footer));
            job.printDialog();
            job.print();

        } catch (Exception ex) {
        }

result


来源: stackexchange

问:
Get Guideline percent size in pixels programmatically
I have a GuideLine, 15% off the left of the page.

I can get a percentage of it in this code:

```<code>float percent = ((ConstraintLayout.LayoutParams) guideline.getLayoutParams()).guidePercent;
</code>```

Output: 0.15

How can I get pixel or dpi values?

答:
Assuming ConstraintLayout has already been laid out, then you can get top or left distance in pixels using guideline.getTop() for horizontal guideline and guideline.getLeft() for vertical guideline.

If ConstraintLayout has not been laid out yet (say you are in onCreate() of activity), then you have to wait until it is laid out:

```
<code>
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ConstraintLayout constraintLayout = (ConstraintLayout) findViewById(R.id.constraint);
        constraintLayout.post(new Runnable() {
            @Override
            public void run() {
                Guideline guideline = findViewById(R.id.guideline);
                Log.i(TAG, guideline.getLeft() + "");
            }
        });
    }
</code>
```

Note, that getLeft()/getTop() will return size in pixel. This size would point out the distance between the Guideline and its parent - ConstraintLayout. This means that value is not absolute, it's relative to its parent.

If you want to get an absolute value (say your ConstraintLayout is deeply nested inside view hierarchy, and you want to understand how far is the Guideline from the left of the screen), then you have to utilize View#getLocationOnScreen(int[]) API:

```
<code>
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ConstraintLayout constraintLayout = (ConstraintLayout) findViewById(R.id.constraint);
        constraintLayout.post(new Runnable() {
            @Override
            public void run() {
                Guideline guideline = findViewById(R.id.guideline);
                int[] location = new int[2];
                guideline.getLocationOnScreen(location);
                Log.i(TAG, location[0] + " " + location[1]);
            }
        });
    }
</code>
```

ContentLicense: CC BY-SA 3.0

Body:
I have a GuideLine, 15% off the left of the page.

I can get a percentage of it in this code:

float percent = ((ConstraintLayout.LayoutParams) guideline.getLayoutParams()).guidePercent;

Output: 0.15

How can I get pixel or dpi values?

Body:
Assuming ConstraintLayout has already been laid out, then you can get top or left distance in pixels using guideline.getTop() for horizontal guideline and guideline.getLeft() for vertical guideline.

If ConstraintLayout has not been laid out yet (say you are in onCreate() of activity), then you have to wait until it is laid out:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ConstraintLayout constraintLayout = (ConstraintLayout) findViewById(R.id.constraint);
        constraintLayout.post(new Runnable() {
            @Override
            public void run() {
                Guideline guideline = findViewById(R.id.guideline);
                Log.i(TAG, guideline.getLeft() + "");
            }
        });
    }

Note, that getLeft()/getTop() will return size in pixel. This size would point out the distance between the Guideline and its parent - ConstraintLayout. This means that value is not absolute, it's relative to its parent.

If you want to get an absolute value (say your ConstraintLayout is deeply nested inside view hierarchy, and you want to understand how far is the Guideline from the left of the screen), then you have to utilize View#getLocationOnScreen(int[]) API:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ConstraintLayout constraintLayout = (ConstraintLayout) findViewById(R.id.constraint);
        constraintLayout.post(new Runnable() {
            @Override
            public void run() {
                Guideline guideline = findViewById(R.id.guideline);
                int[] location = new int[2];
                guideline.getLocationOnScreen(location);
                Log.i(TAG, location[0] + " " + location[1]);
            }
        });
    }


问:
Why won't my function return largest even if numbers are negative
I need to create a function that returns the largest even number in a list. I created this but it doesn't work for negative numbers and I'm not sure why.</p>

```<code>def largest_even(list_int):
large = False
print(list_int)
for i in list_int:
    if i % 2 == 0:
        i = large
for i in list_int:
    if i % 2 == 0:
        if i > large:
            large = i
return large
</code>```

答:
According to the comments above you can solve the problem with:

```<code>max(x for x in list_int if x % 2 == 0)
</code>```

Your code must be modified as follows so it can get the largest even number in the passed list:

1- You need to fix the indentation in your code (I would guess it's due to copy and paste)

2- You can find the largest as:

```<code>large = None
for x in list_int:
     if x % 2 == 0:
         if large is None:
             large = x
         if x > large:
             large = x
</code>```

Body:
I need to create a function that returns the largest even number in a list. I created this but it doesn't work for negative numbers and I'm not sure why.

def largest_even(list_int):
large = False
print(list_int)
for i in list_int:
    if i % 2 == 0:
        i = large
for i in list_int:
    if i % 2 == 0:
        if i > large:
            large = i
return large

Body:
According to the comments above you can solve the problem with:

max(x for x in list_int if x % 2 == 0)

Your code must be modified as follows so it can get the largest even number in the passed list:

1- You need to fix the indentation in your code (I would guess it's due to copy and paste)

2- You can find the largest as:

large = None
for x in list_int:
     if x % 2 == 0:
         if large is None:
             large = x
         if x > large:
             large = x


问:
Disable Chrome strict MIME type checking
Is there any way to disable strict MIME type checking in Chrome.

Actually I'm making a JSONP request on cross domain. Its working fine on Firefox but, while using chrome its giving some error in console.

Refused to execute script from 'https://example.com' because its MIME type ('text/plain') is not executable, and strict MIME type checking is enabled.

Its working perfectly in Mozilla.. Issue is arising in chrome only

Here are the response Headers of the request..

```<code>Cache-Control:no-cache, no-store
Connection:Keep-Alive
Content-Length:29303
Content-Type:text/plain;charset=ISO-8859-1
Date: xxxx
Expires:-1
Keep-Alive:timeout=5
max-age:Thu, 01 Jan 1970 00:00:00 GMT
pragma:no-cache
Set-Cookie:xxxx
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options:nosniff
X-Frame-Options:SAMEORIGIN
</code>```

Workaround what i think :
Externally setting content-type to application/javascript

答:
In my case, I turned off X-Content-Type-Options on nginx then works fine. But make sure this declines your security level a little. Would be a temporally fix.

```<code># Not work
add_header X-Content-Type-Options nosniff;
# OK (comment out)
#add_header X-Content-Type-Options nosniff;
</code>```

It'll be the same for apache.

```<code><IfModule mod_headers.c>
  #Header set X-Content-Type-Options nosniff
</IfModule>
</code>```

Body:
Is there any way to disable strict MIME type checking in Chrome.

Actually I'm making a JSONP request on cross domain. Its working fine on Firefox but, while using chrome its giving some error in console.

Refused to execute script from 'https://example.com' because its MIME type ('text/plain') is not executable, and strict MIME type checking is enabled.

Its working perfectly in Mozilla.. Issue is arising in chrome only

Here are the response Headers of the request..

Cache-Control:no-cache, no-store
Connection:Keep-Alive
Content-Length:29303
Content-Type:text/plain;charset=ISO-8859-1
Date: xxxx
Expires:-1
Keep-Alive:timeout=5
max-age:Thu, 01 Jan 1970 00:00:00 GMT
pragma:no-cache
Set-Cookie:xxxx
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options:nosniff
X-Frame-Options:SAMEORIGIN

Workaround what i think :
Externally setting content-type to application/javascript

Body:
In my case, I turned off X-Content-Type-Options on nginx then works fine. But make sure this declines your security level a little. Would be a temporally fix.

# Not work
add_header X-Content-Type-Options nosniff;
# OK (comment out)
#add_header X-Content-Type-Options nosniff;

It'll be the same for apache.

<IfModule mod_headers.c>
  #Header set X-Content-Type-Options nosniff
</IfModule>

ContentLicense: CC BY-SA 4.0


问:
Configuring Kamailio for RTP Proxying
Would I need to install RTPProxy and RTPEngine for multiple users to send audio to one another? I'm not sure if RTPProxy and RTPEngine are two different modules that does the samething.</p>

答:
RTPProxy/RTPEngine are just the same thing. They are used to proxy media mainly for relaying purposes, however RTPEngine is an updated RTPProxy and you can do much more than just relaying media streams like crypto, capturing pcaps and also recording mp3/wav files.

RTPProxy http://www.kamailio.org/docs/modules/5.0.x/modules/rtpproxy.html

RTPEngine
http://www.kamailio.org/docs/modules/5.0.x/modules/rtpengine.html

The better approach as I suggest, is to use RTPEngine.

Title: Configuring Kamailio for RTP Proxying


问:
How to remove django crispy form field validation error?
I would like to override the errors in crispy forms to hide the default crispy form  field(username) validation error because I am using clean method for validation already.

Image

```<code>class AddEmployeeForm(ModelForm):
    password = forms.CharField(widget=forms.PasswordInput)

    def __init__(self, *args, **kwargs):
        super(AddEmployeeForm, self).__init__(*args, **kwargs)

        for fieldname in ['username', ]:
            self.fields[fieldname].help_text = None

        for key in self.fields:
            self.fields[key].required = True

        self.helper = FormHelper(self)
        self.helper.form_method = 'POST'
        self.helper.form_action = '/add_employee/'
        self.helper.form_class = 'form-horizontal'
        self.helper.form_show_errors = True
        self.helper.error_text_inline = False
        # NEW:
        self.helper.label_class = 'col-sm-4'
        self.helper.field_class = 'col-sm-5'

        self.helper.layout = Layout(
            Field('first_name', css_class='input-sm'),
            Field('last_name', css_class='input-sm'),
            Field('username', css_class='input-sm'),
            Field('email', css_class='input-sm'),
            Field('password', css_class='input-sm'),
            # NEW:
            ButtonHolder(
                Submit('submit', 'Submit', css_class='btn btn-primary')
            )
        )

    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'username', 'email', 'password']

    def clean(self):
        cleaned_data = super(AddEmployeeForm, self).clean()
        email = cleaned_data.get("email")
        username = cleaned_data.get("username")
        if User.objects.filter(email=email):
            raise forms.ValidationError('Email already exists.')
        if User.objects.filter(username=username):
            raise forms.ValidationError('Username already exists.')
        return self.cleaned_data
</code>```

In template I have used this only.:

```<code>{% load crispy_forms_tags %}

{% crispy form %}
</code>```

答:
Please change the form_show_errors parameter being passwed to helper to  False

i.e. replace the line

self.helper.form_show_errors = True

to

self.helper.form_show_errors = False

Your new AddEmployeeForm class will look as follows

```<code>class AddEmployeeForm(ModelForm):
    password = forms.CharField(widget=forms.PasswordInput)

    def __init__(self, *args, **kwargs):
        super(AddEmployeeForm, self).__init__(*args, **kwargs)

        for fieldname in ['username', ]:
            self.fields[fieldname].help_text = None

        for key in self.fields:
            self.fields[key].required = True

        self.helper = FormHelper(self)
        self.helper.form_method = 'POST'
        self.helper.form_action = '/add_employee/'
        self.helper.form_class = 'form-horizontal'
        self.helper.form_show_errors = False
        self.helper.error_text_inline = False
        # NEW:
        self.helper.label_class = 'col-sm-4'
        self.helper.field_class = 'col-sm-5'

        self.helper.layout = Layout(
            Field('first_name', css_class='input-sm'),
            Field('last_name', css_class='input-sm'),
            Field('username', css_class='input-sm'),
            Field('email', css_class='input-sm'),
            Field('password', css_class='input-sm'),
            # NEW:
            ButtonHolder(
                Submit('submit', 'Submit', css_class='btn btn-primary')
            )
        )

    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'username', 'email', 'password']

    def clean(self):
        cleaned_data = super(AddEmployeeForm, self).clean()
        email = cleaned_data.get("email")
        username = cleaned_data.get("username")
        if User.objects.filter(email=email):
            raise forms.ValidationError('Email already exists.')
        if User.objects.filter(username=username):
            raise forms.ValidationError('Username already exists.')
        return self.cleaned_data
</code>```

Body:
I would like to override the errors in crispy forms to hide the default crispy form  field(username) validation error because I am using clean method for validation already.

Image

class AddEmployeeForm(ModelForm):
    password = forms.CharField(widget=forms.PasswordInput)

    def __init__(self, *args, **kwargs):
        super(AddEmployeeForm, self).__init__(*args, **kwargs)

        for fieldname in ['username', ]:
            self.fields[fieldname].help_text = None

        for key in self.fields:
            self.fields[key].required = True

        self.helper = FormHelper(self)
        self.helper.form_method = 'POST'
        self.helper.form_action = '/add_employee/'
        self.helper.form_class = 'form-horizontal'
        self.helper.form_show_errors = True
        self.helper.error_text_inline = False
        # NEW:
        self.helper.label_class = 'col-sm-4'
        self.helper.field_class = 'col-sm-5'

        self.helper.layout = Layout(
            Field('first_name', css_class='input-sm'),
            Field('last_name', css_class='input-sm'),
            Field('username', css_class='input-sm'),
            Field('email', css_class='input-sm'),
            Field('password', css_class='input-sm'),
            # NEW:
            ButtonHolder(
                Submit('submit', 'Submit', css_class='btn btn-primary')
            )
        )

    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'username', 'email', 'password']

    def clean(self):
        cleaned_data = super(AddEmployeeForm, self).clean()
        email = cleaned_data.get("email")
        username = cleaned_data.get("username")
        if User.objects.filter(email=email):
            raise forms.ValidationError('Email already exists.')
        if User.objects.filter(username=username):
            raise forms.ValidationError('Username already exists.')
        return self.cleaned_data

In template I have used this only.:

{% load crispy_forms_tags %}

{% crispy form %}

Body:
Please change the form_show_errors parameter being passwed to helper to  False

i.e. replace the line

self.helper.form_show_errors = True

to

self.helper.form_show_errors = False

Your new AddEmployeeForm class will look as follows

class AddEmployeeForm(ModelForm):
    password = forms.CharField(widget=forms.PasswordInput)

    def __init__(self, *args, **kwargs):
        super(AddEmployeeForm, self).__init__(*args, **kwargs)

        for fieldname in ['username', ]:
            self.fields[fieldname].help_text = None

        for key in self.fields:
            self.fields[key].required = True

        self.helper = FormHelper(self)
        self.helper.form_method = 'POST'
        self.helper.form_action = '/add_employee/'
        self.helper.form_class = 'form-horizontal'
        self.helper.form_show_errors = False
        self.helper.error_text_inline = False
        # NEW:
        self.helper.label_class = 'col-sm-4'
        self.helper.field_class = 'col-sm-5'

        self.helper.layout = Layout(
            Field('first_name', css_class='input-sm'),
            Field('last_name', css_class='input-sm'),
            Field('username', css_class='input-sm'),
            Field('email', css_class='input-sm'),
            Field('password', css_class='input-sm'),
            # NEW:
            ButtonHolder(
                Submit('submit', 'Submit', css_class='btn btn-primary')
            )
        )

    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'username', 'email', 'password']

    def clean(self):
        cleaned_data = super(AddEmployeeForm, self).clean()
        email = cleaned_data.get("email")
        username = cleaned_data.get("username")
        if User.objects.filter(email=email):
            raise forms.ValidationError('Email already exists.')
        if User.objects.filter(username=username):
            raise forms.ValidationError('Username already exists.')
        return self.cleaned_data


问:
How to intercept all read and write access to objects at runtime?
I am working on an aging Java "Swing" application that, unfortunately, uses a non Thread-safe data model. As the number of clients with multi-threading and multi-core PCs grows, so does the number of spurious random errors due to non synchronized access to the data. We have a huge code-base, something like 6000 Java files, most of which are quite large and complicated.

I would like to create a global static ReentrantReadWriteLock to control access to the model. My plan would be to create a dummy ReadWriteLock implementation, which always succeeds and does not do anything, and use it on the productive system, while using the ReentrantReadWriteLock on the test systems, so that the transition can be gradual.

What I need is a way to "intercept" all accesses to the model in the test systems and log an error if the access is not within the scoop of an appropriate lock/unlock block. ReentrantReadWriteLock can tell you if you own a write lock. I am assuming I could track the read lock state myself by using a ThreadLocal or something.

So now comes the real question: How could I, in Java, write code that would intercept at runtime any access to any public method in a well-defined set of classes, and check if the access is within a lock/unlock block, by querying the global lock? Can this be done with AspectJ? Or anything else? And how?

答:
I don't know how applicable this is to your situation but the best way to intercept method calls is by using dynamic proxies. For this you have to create interfaces for your classes though, which you might have done anyway.

Here's an example of how dynamic proxies work:

```<code> interface Foo {
    void setBar( String bar );
    String getBar();
 }

 class FooImpl implements Foo {
    private String bar;
    // getter and setter
 }
</code>```

This is your normal code. Now what you can do is instead of new FooImpl() you can use a proxy. For the proxy you need an [InvocationHandler][1] first.

```<code> class LockHandler implements InvocationHandler {

    private FooImpl originalOb;

    public LockHandler( FooImpl originalOb ) {
      this.originalOb = originalOb;
    }

    @Override
    public Object invoke( Object proxy, Method method, Object [] args ) {
      try {
        if( method.getName().startsWith( "set" ) {
           // do locking stuff
        }
        return method.invoke( originalOb, args ); //invoke underlying method
      } finally {
        if( method.getName().startsWith( "set" ) {
           // do post-call locking stuff
        }
      }
    }
 }
</code>```

And then you finally create your Proxy object:

```<code> Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
                                      new Class[] { Foo.class },
                                      new LockHandler( new FooImpl() ) );
</code>```

Now every call to your foo object will be channeled into your invocation handler. Of course you don't have to create a new invocation handler instance for every object, you don't even need a separate one for every interface, originalOb could (and in real life should) be declared as Object type.

Another option is to use an aspect implementation, like AspectJ, which is probably simpler to use but it may be too late to introduce it, depending on how far you're into the development of the software.

ContentLicense: CC BY-SA 2.5

Body:
I don't know how applicable this is to your situation but the best way to intercept method calls is by using dynamic proxies. For this you have to create interfaces for your classes though, which you might have done anyway.

Here's an example of how dynamic proxies work:

 interface Foo {
    void setBar( String bar );
    String getBar();
 }

 class FooImpl implements Foo {
    private String bar;
    // getter and setter
 }

This is your normal code. Now what you can do is instead of new FooImpl() you can use a proxy. For the proxy you need an [InvocationHandler][1] first.

 class LockHandler implements InvocationHandler {

    private FooImpl originalOb;

    public LockHandler( FooImpl originalOb ) {
      this.originalOb = originalOb;
    }

    @Override
    public Object invoke( Object proxy, Method method, Object [] args ) {
      try {
        if( method.getName().startsWith( "set" ) {
           // do locking stuff
        }
        return method.invoke( originalOb, args ); //invoke underlying method
      } finally {
        if( method.getName().startsWith( "set" ) {
           // do post-call locking stuff
        }
      }
    }
 }

And then you finally create your Proxy object:

 Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
                                      new Class[] { Foo.class },
                                      new LockHandler( new FooImpl() ) );

Now every call to your foo object will be channeled into your invocation handler. Of course you don't have to create a new invocation handler instance for every object, you don't even need a separate one for every interface, originalOb could (and in real life should) be declared as Object type.

Another option is to use an aspect implementation, like AspectJ, which is probably simpler to use but it may be too late to introduce it, depending on how far you're into the development of the software.


问:
Objective c: iBeacon ranging doesn't fire didEnterRegion
I´ve implemented a beacon region monitoring in my AppDelegate.

I test my code in foreground.
The didRangeBeacons event is thrown successfully and regularly. (I see the amount of beacons and also the count change in the didRangeBeacons if i turn off my beacon.)
My didEnterRegion event was not fired.

AppDelegate.m

```<code>- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //....
    self->beaconLocationManager = [[CLLocationManager alloc] init];
    self->beaconLocationManager.delegate = self;//(AppDelegate *)[[UIApplication sharedApplication] delegate];
    NSUUID *uuid=[[NSUUID alloc]initWithUUIDString:@"200F0B26-2215-1518-442B-5F0616412530"];
    clBeconRegion=[[CLBeaconRegion alloc]initWithProximityUUID:uuid identifier:@"BluetoothExample"];
    clBeconRegion.notifyOnEntry=YES;
    [self->beaconLocationManager requestAlwaysAuthorization];
    [self->beaconLocationManager startMonitoringForRegion:clBeconRegion];
    [self->beaconLocationManager startRangingBeaconsInRegion:clBeconRegion];
    return YES;
}

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
    NSLog(@"ENTER REGION");//not fired
}
-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region{
    NSLog(@"beacons list %@ ",beacons);//successfully fired regularly
}
</code>```

I also enabled Background App Refresh in general settings.

Info.plist entry:
<key>NSLocationAlwaysUsageDescription</key><string>bla bla bla</string>
<key>NSLocationWhenInUseUsageDescription</key><string>bla bla bla</string>

The monitoringDidFailForRegion writes the following error:
CLBeaconRegion (identifier:'BluetoothExample', uuid:200F0B26-2215-1518-442B-5F0616412530, major:(null), minor:(null)) The operation couldn’t be completed. (kCLErrorDomain error 4.)

答:
You need to enable BLE background permission as well.
Go to Project Target >> Background Modes >> Capabilities  check Uses Bluetooth LE Accessories. Look on this Image

Body:
I´ve implemented a beacon region monitoring in my AppDelegate.

I test my code in foreground.
The didRangeBeacons event is thrown successfully and regularly. (I see the amount of beacons and also the count change in the didRangeBeacons if i turn off my beacon.)
My didEnterRegion event was not fired.

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //....
    self->beaconLocationManager = [[CLLocationManager alloc] init];
    self->beaconLocationManager.delegate = self;//(AppDelegate *)[[UIApplication sharedApplication] delegate];
    NSUUID *uuid=[[NSUUID alloc]initWithUUIDString:@"200F0B26-2215-1518-442B-5F0616412530"];
    clBeconRegion=[[CLBeaconRegion alloc]initWithProximityUUID:uuid identifier:@"BluetoothExample"];
    clBeconRegion.notifyOnEntry=YES;
    [self->beaconLocationManager requestAlwaysAuthorization];
    [self->beaconLocationManager startMonitoringForRegion:clBeconRegion];
    [self->beaconLocationManager startRangingBeaconsInRegion:clBeconRegion];
    return YES;
}

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
    NSLog(@"ENTER REGION");//not fired
}
-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region{
    NSLog(@"beacons list %@ ",beacons);//successfully fired regularly
}

I also enabled Background App Refresh in general settings.

Info.plist entry:
<key>NSLocationAlwaysUsageDescription</key><string>bla bla bla</string>
<key>NSLocationWhenInUseUsageDescription</key><string>bla bla bla</string>

The monitoringDidFailForRegion writes the following error:
CLBeaconRegion (identifier:'BluetoothExample', uuid:200F0B26-2215-1518-442B-5F0616412530, major:(null), minor:(null)) The operation couldn’t be completed. (kCLErrorDomain error 4.)


问:
Ruby on Rails webfont not displaying locally
I'm using Rails 3.2.22 and have installed a new font using .woff and .woff2 files.  But the font seems to fail to display locally only.  The font shows up fine when I deploy to our staging environment after the assets have been precompiled and bundled up.  I can also follow the url that my local compiled CSS is using to try and display the font, and that link downloads the correct files.

The font files are contained in the "app/assets/fonts" folder, I have this in my application.rb

```<code>config.assets.paths << Rails.root.join("app", "assets", "fonts")
</code>```

and I am pulling the fonts into Sass like so:

```<code>// Custom Font Faces
@font-face {
  font-family: 'Museo Sans Rounded';
  src: font-url('MuseoSansRounded-500-webfont.woff2') format('woff2'),
       font-url('MuseoSansRounded-500-webfont.woff') format('woff');
  font-weight: 500;
  font-style: normal;
}

@font-face {
  font-family: 'Museo Sans Rounded';
  src: font-url('MuseoSansRounded-700-webfont.woff2') format('woff2'),
       font-url('MuseoSansRounded-700-webfont.woff') format('woff');
  font-weight: 700;
  font-style: normal;
}
</code>```

Any clue why this doesn't display locally?

答:
Try this way, this is a working example of 'Glyphicons Halflings'

```<code>@font-face {
font-family: 'Glyphicons Halflings';
src: url('/assets/glyphicons-halflings-regular.eot');
src: url('/assets/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('/assets/glyphicons-halflings-regular.woff2') format('woff2'), url('/assets/glyphicons-halflings-regular.woff') format('woff'), url('assets/glyphicons-halflings-regular.ttf') format('truetype'), url('/assets/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')
</code>```

}

Body:
I'm using Rails 3.2.22 and have installed a new font using .woff and .woff2 files.  But the font seems to fail to display locally only.  The font shows up fine when I deploy to our staging environment after the assets have been precompiled and bundled up.  I can also follow the url that my local compiled CSS is using to try and display the font, and that link downloads the correct files.

The font files are contained in the "app/assets/fonts" folder, I have this in my application.rb

config.assets.paths << Rails.root.join("app", "assets", "fonts")

and I am pulling the fonts into Sass like so:

// Custom Font Faces
@font-face {
  font-family: 'Museo Sans Rounded';
  src: font-url('MuseoSansRounded-500-webfont.woff2') format('woff2'),
       font-url('MuseoSansRounded-500-webfont.woff') format('woff');
  font-weight: 500;
  font-style: normal;
}

@font-face {
  font-family: 'Museo Sans Rounded';
  src: font-url('MuseoSansRounded-700-webfont.woff2') format('woff2'),
       font-url('MuseoSansRounded-700-webfont.woff') format('woff');
  font-weight: 700;
  font-style: normal;
}

Any clue why this doesn't display locally?

Body:
Try this way, this is a working example of 'Glyphicons Halflings'

@font-face {
font-family: 'Glyphicons Halflings';
src: url('/assets/glyphicons-halflings-regular.eot');
src: url('/assets/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('/assets/glyphicons-halflings-regular.woff2') format('woff2'), url('/assets/glyphicons-halflings-regular.woff') format('woff'), url('assets/glyphicons-halflings-regular.ttf') format('truetype'), url('/assets/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')

}


问:
How Do I Set The Value Of A String In Android?
I have a string and a button as follows:

```<code>String message = "Hello World"

button.OnClickListener(......){

   message = "123456789";
}
</code>```

So here is what I want,

When the app starts the string is "Hello World" but when the user clicks the button it changes to "123456789" and I want the string to change permanently for lifetime.

So when the user restarts the application or reinstall it the string is still
"123456789".I think this comes under Shared Preferences.

Please Help,I really need this

答: There is a chance data from SharedPreferences is gone when you reinstall especially if you uninstall the app first, same case as local database using SQLite. You can try using database from your local server.

Body:
I have a string and a button as follows:

String message = "Hello World"

button.OnClickListener(......){

   message = "123456789";
}

So here is what I want,

When the app starts the string is "Hello World" but when the user clicks the button it changes to "123456789" and I want the string to change permanently for lifetime.

So when the user restarts the application or reinstall it the string is still
"123456789".I think this comes under Shared Preferences.

Please Help,I really need this


问:
How to compare rows in a single column?
I have data like the below in an Oracle database

```<code>Name   Session     CATEGORY   HT     WT     BMI
John   SESSION 1   OW         1.5    64.6   28.71
John   SESSION 3   OW         1.5    64.6   28.71
Eric   SESSION 1   OW         1.48   55.7   25.43
Eric   SESSION 3   OW         1.52   55.4   23.98
</code>```

I have converted the above data like this using pivot

```<code>Name  session_1_Category  Session_1_height  session_1_weight  session_1_BMI  session_3_Category  Session_3_height  session_3_weight  session_3_BMI
John  OW                  1.5               64.6              28.71          OW                  1.5               64.6              28.71
Eric  OW                  1.48              55.7              25.43          OW                  1.52              55.4              23.98
</code>```

I want to compare session 1 height with session 3 height, and session 1 weight with session 3 weight.

For e.g.

```<code>if SESSION_1_HEIGHT =SESSION_3_HEIGHT then height_status=true else height_status=false
if SESSION_1_WEIGHT =SESSION_3_WEIGHT then weight_status=true else weight_status=false
if SESSION_1_BMI =SESSION_3_BMI then bmi_status=true else bmi_status=false
</code>```

Please look here at SQLFiddle

答:
I'm not super familiar with Oracle and PIVOT, but you can use CASE to do your comparisons.

I had to remove the SELECT * and replace it with the list of fields, I'm not sure why that was necessary sorry.

```<code>SELECT name, category,
session_1_height, session_1_weight, session_1_bmi,
session_3_height, session_3_weight, session_3_bmi,
CASE WHEN session_1_height = session_3_height THEN 'true' ELSE 'false' END AS height_status,
CASE WHEN session_1_weight = session_3_weight THEN 'true' ELSE 'false' END AS weight_status,
CASE WHEN session_1_bmi = session_3_bmi THEN 'true' ELSE 'false' END AS bmi_status
FROM   table_name
PIVOT(
    MAX( HT ) AS height,
    MAX( WT ) AS weight,
    MAX( BMI ) AS BMI
    FOR "Session" IN (
        'SESSION 1' AS Session_1,
        'SESSION 3' AS Session_3
    )
);
</code>```

Title: How to compare rows in a single column?

Body:
I have data like the below in an Oracle database

Name   Session     CATEGORY   HT     WT     BMI
John   SESSION 1   OW         1.5    64.6   28.71
John   SESSION 3   OW         1.5    64.6   28.71
Eric   SESSION 1   OW         1.48   55.7   25.43
Eric   SESSION 3   OW         1.52   55.4   23.98

I have converted the above data like this using pivot

Name  session_1_Category  Session_1_height  session_1_weight  session_1_BMI  session_3_Category  Session_3_height  session_3_weight  session_3_BMI
John  OW                  1.5               64.6              28.71          OW                  1.5               64.6              28.71
Eric  OW                  1.48              55.7              25.43          OW                  1.52              55.4              23.98

I want to compare session 1 height with session 3 height, and session 1 weight with session 3 weight.

For e.g.

if SESSION_1_HEIGHT =SESSION_3_HEIGHT then height_status=true else height_status=false
if SESSION_1_WEIGHT =SESSION_3_WEIGHT then weight_status=true else weight_status=false
if SESSION_1_BMI =SESSION_3_BMI then bmi_status=true else bmi_status=false

Please look here at SQLFiddle

Body:
I'm not super familiar with Oracle and PIVOT, but you can use CASE to do your comparisons.

I had to remove the SELECT * and replace it with the list of fields, I'm not sure why that was necessary sorry.

SELECT name, category,
session_1_height, session_1_weight, session_1_bmi,
session_3_height, session_3_weight, session_3_bmi,
CASE WHEN session_1_height = session_3_height THEN 'true' ELSE 'false' END AS height_status,
CASE WHEN session_1_weight = session_3_weight THEN 'true' ELSE 'false' END AS weight_status,
CASE WHEN session_1_bmi = session_3_bmi THEN 'true' ELSE 'false' END AS bmi_status
FROM   table_name
PIVOT(
    MAX( HT ) AS height,
    MAX( WT ) AS weight,
    MAX( BMI ) AS BMI
    FOR "Session" IN (
        'SESSION 1' AS Session_1,
        'SESSION 3' AS Session_3
    )
);


问:
How to print leading spaces before char array in C?
```<code>#include <stdio.h>
int main() {

char a[30];
char b[30];
scanf("%[^\n]s",a);
scanf(" %[^\n]s",b);
printf("%s \n",a);
printf("%s",b);
return 0;
}
</code>```

Input :

```<code>    hai
        hello
</code>```

Output :

```<code>    hai
hello
</code>```

But I am expecting

```<code>    hai
        hello
</code>```

How to print leading spaces before hello?

答:
Note that %[…] (a scan set) is a complete conversion specification.  The s after it in your code never matches anything, but you can't spot that.  The newline is left in the input.  You'd have to arrange to read that before using the second scan set — and a space (or newline) in the format string is not the answer to that.  Replacing the s with %*c would do the job.  But you're probably best off not using scanf() at this point; use fgets() instead.

Using scanf()

```<code>#include <stdio.h>

int main(void)
{
    char a[30];
    char b[30];
    if (scanf("%29[^\n]%*c", a) == 1 &&
        scanf("%29[^\n]%*c", b) == 1)
    {
        printf("[%s]\n", a);
        printf("[%s]\n", b);
    }
    return 0;
}
</code>```

Input:

```<code>    hai
        hello
</code>```

Output:

```<code>[    hai]
[        hello]
</code>```

Using fgets()

```<code>#include <stdio.h>
#include <string.h>

int main(void)
{
    char a[30];
    char b[30];
    if (fgets(a, sizeof(a), stdin) != 0 &&
        fgets(b, sizeof(b), stdin) != 0)
    {
        a[strcspn(a, "\n")] = '\0';
        b[strcspn(b, "\n")] = '\0';
        printf("[%s]\n", a);
        printf("[%s]\n", b);
    }
    return 0;
}
</code>```

For the same input, this produces the same output.

Body:
#include <stdio.h>
int main() {

char a[30];
char b[30];
scanf("%[^\n]s",a);
scanf(" %[^\n]s",b);
printf("%s \n",a);
printf("%s",b);
return 0;
}

Input :

    hai
        hello

Output :

    hai
hello

But I am expecting

    hai
        hello

How to print leading spaces before hello?

Body:
Note that %[…] (a scan set) is a complete conversion specification.  The s after it in your code never matches anything, but you can't spot that.  The newline is left in the input.  You'd have to arrange to read that before using the second scan set — and a space (or newline) in the format string is not the answer to that.  Replacing the s with %*c would do the job.  But you're probably best off not using scanf() at this point; use fgets() instead.

Using scanf()

#include <stdio.h>

int main(void)
{
    char a[30];
    char b[30];
    if (scanf("%29[^\n]%*c", a) == 1 &&
        scanf("%29[^\n]%*c", b) == 1)
    {
        printf("[%s]\n", a);
        printf("[%s]\n", b);
    }
    return 0;
}

Input:

    hai
        hello

Output:

[    hai]
[        hello]

Using fgets()

#include <stdio.h>
#include <string.h>

int main(void)
{
    char a[30];
    char b[30];
    if (fgets(a, sizeof(a), stdin) != 0 &&
        fgets(b, sizeof(b), stdin) != 0)
    {
        a[strcspn(a, "\n")] = '\0';
        b[strcspn(b, "\n")] = '\0';
        printf("[%s]\n", a);
        printf("[%s]\n", b);
    }
    return 0;
}

For the same input, this produces the same output.


问:
What is <?= in C++?

Possible Duplicate:

  C extension: <? and >? operators

Take a look at the top answer (by sclo) to problem D of this Google Code Jam. It's C++ code, it must have compiled, and it contains statements such as this one:

```<code>double& ret = F[mask][cur][b];
if(j==cur) {
  ret<?=f(tmp,j,b||bad[i])+M[cur][i];   // WTF is <?=   ???
}
</code>```

This doesn't compile in my Visual Studio 2008. What does the <?= mean?

答:
It doesn't compile also with GCC, and I've never heard of an operator <?=.

Anyway I would hazard a guess that a<?=b could have a semantics like: a = (a<b) ? b : a, but again, this is just a guess.

Title: What is <?= in C++?

Body:
Possible Duplicate:

  C extension: <? and >? operators

Take a look at the top answer (by sclo) to problem D of this Google Code Jam. It's C++ code, it must have compiled, and it contains statements such as this one:

double& ret = F[mask][cur][b];
if(j==cur) {
  ret<?=f(tmp,j,b||bad[i])+M[cur][i];   // WTF is <?=   ???
}

This doesn't compile in my Visual Studio 2008. What does the <?= mean?


问:
Yellow warning triangle in Xcode 9's Create Bot.. window
I'm trying to set up continuous integration (CI) in Xcode 9 with it's new built-in Xcode Server functionality. (MacBook Pro, macOS High Sierra)

I've been following various tutorials, such as Tutorial: Continuous Integration with Xcode 9 and FastLane, Xcode Server and Continuous Integration Guide: Configure Bots to Perform Continuous Integration, and a few others.

Everything seems to work fine, till I get to the Product -> Create Bot... step. The window opens with a yellow triangle/exclamation mark warning symbol to the right of the Server dropdown:

The Previous and Next buttons are disabled. Nothing happens if I click on the warning triangle, and there are no other related messages I can see in Xcode or the macOS console.

I performed the same setup on another MacBook Pro running High Sierra and the same version of Xcode 9. There was no triangle on that one, and I was able to select Next and continue the process.

Update: The triangle is present for any project I create. And, I've tried closing/restarting both Xcode and the MacBook Pro.

I've searched repeatedly for things like create bot yellow triangle, create bot warning symbol, xcode 9 continuous integration warning symbol, etc, but found nothing relevant.

Has anybody seen this, and what does it mean/how do I fix it???

答:
Your Server & Bots option in Xcode Preferences is still not enabled even though you did it earlier.
Re-enable it and this should fix the issue.
As shown here

Also make sure permissions are set correctly, As shown here


问:
Error while upgrading laravel from 5.0 to 5.1
Today I decided to upgrade my app from Laravel 5.0 to 5.1. But while upgrading, I am facing the following issue:

```<code>Catchable fatal error: Argument 1 passed to Illuminate\Config\Repository::__construct() must be of the type array, integer given, called in /home/vagrant/Code/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php on line 32 and defined in /home/vagrant/Code/vendor/laravel/framework/src/Illuminate/Config/Repository.php on line 23
</code>```

Please help me. I need to get my app up and running once again. Thank You.

答: del storage/bootstrap/cache/[files], this resovle my problem</p>

Body:
Today I decided to upgrade my app from Laravel 5.0 to 5.1. But while upgrading, I am facing the following issue:

Catchable fatal error: Argument 1 passed to Illuminate\Config\Repository::__construct() must be of the type array, integer given, called in /home/vagrant/Code/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php on line 32 and defined in /home/vagrant/Code/vendor/laravel/framework/src/Illuminate/Config/Repository.php on line 23

Please help me. I need to get my app up and running once again. Thank You.


问:
Yii2: a proper way to resolve ambiguity of controller and module names
As far as I know, currently Yii 2 doesn't have an out of the box method to resolve ambiguity of controller and module names. An example of module hierarchy to describe what exactly I mean:

app\modules\v1\controllers\UserController // resolves the /v1/users and /v1/users/{id} actions
app\modules\v1\modules\user\Module.php // nested module, resolves the /v1/user/... controllers and their actions, e.g. /v1/user/something/{id}

In this case, the UserController conflicts with the user Module. The main reason of the ambiguity is the singular-plural magic of Yii 2 framework. I didn't find an appropriate solution to resolve this ambiguity. Further my ideas how to resolve it.

Rename the module.

Rename the UserController to the UsersController.

Create an additional submodule, and place there the UserController. E.g. app\modules\v1\modules\root\controllers\UserController

I'm not sure that at least one of these options is a quite elegant one and a proper solution in view of the Yii 2 philosophy.

Coming back to the main question, what is a more appropriate approach to resolve this issue by the Yii 2 philosophy? Controller and Module is two different types of objects, which is differently pluralized or not, thus should be right way to separate them in the routing for the described case.

答:
I am not sure I can fully understand the question, but probably you're asking about classname aliases?</p>

```<code>use My\Full\Classname as Another;
</code>```

Body:
I am not sure I can fully understand the question, but probably you're asking about classname aliases?

use My\Full\Classname as Another;


问:
How to architecture a json object model in swift with Codable protocol
I’m coding a REST Web app client and I use JSON which looks like this:

JSON1

```<code>{
  "device" : "iPhone"
  "manufacturer" : "Apple"
  "id" : 42

  "owner" : "Steve"
}
</code>```

But the API could give me this kind of JSON also

JSON2

```<code>{
  "device" : "iPhone"
  "manufacturer" : "Apple"
  "id" : 42

  "latitude" : 3.1415926535
  "longitude" : 2.7182818284
}
</code>```

So now in my app I create a struct who conforms to the Codable protocol

```<code>struct MyStruct : Codable {
  var name: String
  var manufacturer: String

  var owner: String?

  // I prefer to use a property of type Location rather than 2 variables
  var location: Location? {
    guard let latitude = latitude, let longitude = longitude else {
      return nil
    }

    return Location(latitude: latitude, longitude: longitude)
  }

  // Used to conform to the Codable protocol
  private var latitude: Double?
  private var longitude: Double?
}

struct Location {
  var latitude: Double = 0.0
  var longitude: Double = 0.0
}
</code>```

This architecture works but it seems to me not the best one or elegant. Would you know if a better approach
exists? Should I use 2 differents json model instead like:

```<code>struct MyStruct1 : Codable {
  var name: String
  var manufacturer: String
  var owner: String
}

struct MyStruct2 : Codable {
  var name: String
  var manufacturer: String

  private var latitude: Double
  private var longitude: Double
}
</code>```

I'm new to REST API client and this kind of JSON doesn't seems to use a good architecture.

答:
Make the owner, latitude & longitude properties  optional.
And use decodeIfPresent for decoding properties only when they exists.

You can create a struct as-

```<code>struct UserData: Codable {//Confroms to Codable protocol
    var id: Int
    var device: String
    var manufacturer: String
    var owner: String? = nil//Making property optional
    var latitude: Double? = nil//Making property optional
    var longitude: Double? = nil//Making property optional
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        id = try values.decode(Int.self, forKey: .id)
        device = try values.decode(String.self, forKey: .device)
        manufacturer = try values.decode(String.self, forKey: .manufacturer)
        owner = try values.decodeIfPresent(String.self, forKey: .owner)
        latitude = try values.decodeIfPresent(Double.self, forKey: .latitude)
        longitude = try values.decodeIfPresent(Double.self, forKey: .longitude)
    }
}
</code>```

Example Json:

```<code>    let jsonExample = """
 {
  "device" : "iPhone",
  "manufacturer" : "Apple",
  "id" : 42,
  "owner" : "Steve"
}
""".data(using: .utf8)!
    let jsonExample2 = """
 {
  "device" : "iPhone",
  "manufacturer" : "Apple",
  "id" : 42,
  "latitude" : 3.1415926535,
  "longitude" : 2.7182818284
}
""".data(using: .utf8)!.
</code>```

Usage:

```<code>    //Decode struct using JSONDecoder
     let jsonDecoder = JSONDecoder()
            do {
                let modelResult = try jsonDecoder.decode(UserData.self,from: jsonExample2)
                print("owner is \(String(describing: modelResult.owner)) - latitude is \(String(describing: modelResult.latitude)) - longitude is \(String(describing: (modelResult.longitude)))")
            } catch {
                print(error)
            }
</code>```

Body:
I’m coding a REST Web app client and I use JSON which looks like this:

JSON1

{
  "device" : "iPhone"
  "manufacturer" : "Apple"
  "id" : 42

  "owner" : "Steve"
}

But the API could give me this kind of JSON also

JSON2

{
  "device" : "iPhone"
  "manufacturer" : "Apple"
  "id" : 42

  "latitude" : 3.1415926535
  "longitude" : 2.7182818284
}

So now in my app I create a struct who conforms to the Codable protocol

struct MyStruct : Codable {
  var name: String
  var manufacturer: String

  var owner: String?

  // I prefer to use a property of type Location rather than 2 variables
  var location: Location? {
    guard let latitude = latitude, let longitude = longitude else {
      return nil
    }

    return Location(latitude: latitude, longitude: longitude)
  }

  // Used to conform to the Codable protocol
  private var latitude: Double?
  private var longitude: Double?
}

struct Location {
  var latitude: Double = 0.0
  var longitude: Double = 0.0
}

This architecture works but it seems to me not the best one or elegant. Would you know if a better approach
exists? Should I use 2 differents json model instead like:

struct MyStruct1 : Codable {
  var name: String
  var manufacturer: String
  var owner: String
}

struct MyStruct2 : Codable {
  var name: String
  var manufacturer: String

  private var latitude: Double
  private var longitude: Double
}

I'm new to REST API client and this kind of JSON doesn't seems to use a good architecture.

Body:
Make the owner, latitude & longitude properties  optional.
And use decodeIfPresent for decoding properties only when they exists.

You can create a struct as-

struct UserData: Codable {//Confroms to Codable protocol
    var id: Int
    var device: String
    var manufacturer: String
    var owner: String? = nil//Making property optional
    var latitude: Double? = nil//Making property optional
    var longitude: Double? = nil//Making property optional
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        id = try values.decode(Int.self, forKey: .id)
        device = try values.decode(String.self, forKey: .device)
        manufacturer = try values.decode(String.self, forKey: .manufacturer)
        owner = try values.decodeIfPresent(String.self, forKey: .owner)
        latitude = try values.decodeIfPresent(Double.self, forKey: .latitude)
        longitude = try values.decodeIfPresent(Double.self, forKey: .longitude)
    }
}

Example Json:

    let jsonExample = """
 {
  "device" : "iPhone",
  "manufacturer" : "Apple",
  "id" : 42,
  "owner" : "Steve"
}
""".data(using: .utf8)!
    let jsonExample2 = """
 {
  "device" : "iPhone",
  "manufacturer" : "Apple",
  "id" : 42,
  "latitude" : 3.1415926535,
  "longitude" : 2.7182818284
}
""".data(using: .utf8)!.

Usage:

    //Decode struct using JSONDecoder
     let jsonDecoder = JSONDecoder()
            do {
                let modelResult = try jsonDecoder.decode(UserData.self,from: jsonExample2)
                print("owner is \(String(describing: modelResult.owner)) - latitude is \(String(describing: modelResult.latitude)) - longitude is \(String(describing: (modelResult.longitude)))")
            } catch {
                print(error)
            }


问:
PHP - While writing a fixed length file, PHP is not processing `\t` as Tab after the first one. Why?
I am writing a fixed length file using PHP. Each character will have a predefined length. If characters are less than the length then it will insert that number of blank spaces. Each field is separated by TAB.

```<code>$str1 = str_pad('ten',10)."\t";
$str2 = str_pad('seven',7)."\t";
$str3 = str_pad('fifteen',15)."\t";

$str = $str1.$str2.$str3;

file_put_contents("newfile.txt",$str);
</code>```

But TAB is not working as expected.

I can see TAB only after first word (ten). After that there are no more TABs in the output file.

答:
Your text is rendered correctly.

A tab does not mean a fixed number of spaces or a printable character. It means "forward the cursor to the next tab stop".

A tab stop in computers is typically set to every 4 or 8 characters. It's a display issue that will behave differently across various systems and user configurations.

If you copy your output to your preferred text editor and manually select it, you can see spaces as dots and tabs as lines, as in the examples below:

Note: your output is the first line ("ten seven fifteen"). I added the second and third lines to illustrate the configured tab length in the text editor.

If we set tab length to 4:

The first string contains 10 chars ("t", "e", "n" plus 7 dots), and the next tab stop is at the 12th char. So it's only 2 chars away, that's why your tab character (grey line) is only 2 chars long. The second string has 7 chars, and the next stop is only 1 char away so the tab will have only 1 char. It's the same logic for the third string.

If we set tab length to 8:

It follows the same logic, but in this example, the first tab is now bigger because the nearest stop is at position 16, so the tab has 6 chars. The second and third tabs have coincidentally only one char.

If we set tab length to an odd number like 3:

This is not common, but it's something possible. In this example, we can see all tabs as multiple spaces. It follows the same logic as explained above, but we can visually see that your code is producing the expected output.

Notice that I did not change your output in any way. I just played with the editor's configuration.

If you want a fixed length spacer between your chars, you should use "\s" instead. You can repeat the character like this: "\s\s\s\s", or using str_repeat("\s", 4); or "\s" * 4 if you were using Python.

Body:
I am writing a fixed length file using PHP. Each character will have a predefined length. If characters are less than the length then it will insert that number of blank spaces. Each field is separated by TAB.

$str1 = str_pad('ten',10)."\t";
$str2 = str_pad('seven',7)."\t";
$str3 = str_pad('fifteen',15)."\t";

$str = $str1.$str2.$str3;

file_put_contents("newfile.txt",$str);

But TAB is not working as expected.

I can see TAB only after first word (ten). After that there are no more TABs in the output file.


问:
Why Xcode 9 change my outlet unsafe_unretained by default
When I control-drag outlet from xib, I got unsafe_unretained property by default. I'm using Xcode 9.1. The following code is what it looks like.</p>

```<code>@property (unsafe_unretained, nonatomic) IBOutlet UILabel *shIndexLabel;
</code>```

答:
__unsafe_unretained specifies a reference that does not keep the referenced object alive and is not set to nil when there are no strong
  references to the object. If the object it references is deallocated,
  the pointer is left dangling.

Above excerpt from Apple docs. So answering your question WHY?

It is not possible for the Swift compiler to know if these references
  are really intended to be strong (+1) or unretained (+0)

This change involved with respect to the swift compiler. They made __unsafe_unretained by default.

Body:
When I control-drag outlet from xib, I got unsafe_unretained property by default. I'm using Xcode 9.1. The following code is what it looks like.

@property (unsafe_unretained, nonatomic) IBOutlet UILabel *shIndexLabel;


问:
Why does python __file__ variable returns errorneous path when used in DJango?

I was trying to retrieve the file path using python __file__ variable under django though i am getting correct path. It's behavior is little weird. Here is my attached sample code please let me know why is the behavior so.

```<code>from django.shortcuts import render_to_response
import datetime

class WebServer():

    def __init__(self):
        pass

    def display_first_page(self, request):

        print "File Path: ", __file__
        return render_to_response('Hello')
</code>```

I have stored this code at the given location : C:\Django_example\MySample. Ideally it should have returned something like C:\Django_example\MySample\webserver.py, but instead i am getting C:\Django_example\MySample\..\MySample\webserver.py . Can someone please point me to the right direction.

Thanks in advance,

Rupesh

答:
To get a current directory path you can do something like this.

```<code>    import os
    os.path.abspath(os.path.dirname(__file__))
</code>```

This will return a normalized absolutized version of the pathname(absolute path) as well as it will normalizes the path. For example, on Unix and Mac OS X systems the path /var/www/project  will work fine, but on Windows systems that is not a good path. Normalizing the path will convert forward slashes to backward slashes. Normalization also collapses redundant separators, for example the path A/foo/../B will be normalized to A/B.

Rupesh

Body:
I was trying to retrieve the file path using python __file__ variable under django though i am getting correct path. It's behavior is little weird. Here is my attached sample code please let me know why is the behavior so.

from django.shortcuts import render_to_response
import datetime

class WebServer():

    def __init__(self):
        pass

    def display_first_page(self, request):

        print "File Path: ", __file__
        return render_to_response('Hello')

I have stored this code at the given location : C:\Django_example\MySample. Ideally it should have returned something like C:\Django_example\MySample\webserver.py, but instead i am getting C:\Django_example\MySample\..\MySample\webserver.py . Can someone please point me to the right direction.

Thanks in advance,

Rupesh

Body:
To get a current directory path you can do something like this.

    import os
    os.path.abspath(os.path.dirname(__file__))

This will return a normalized absolutized version of the pathname(absolute path) as well as it will normalizes the path. For example, on Unix and Mac OS X systems the path /var/www/project  will work fine, but on Windows systems that is not a good path. Normalizing the path will convert forward slashes to backward slashes. Normalization also collapses redundant separators, for example the path A/foo/../B will be normalized to A/B.

Rupesh