Domanda

Folks,

I have read several threads on stackoverflow and googled some(http://docs.oracle.com/javase/tutorial/uiswing/components/border.html) and asked around all Swing experts at work before deciding to post a question. I have basic understanding of Swing and this complicates things terribly.

http://i58.tinypic.com/f1fo1w.jpg

I have attached a picture of a button...this is a button with nearly 3 borders (as much my eyes can tell). The rectangle on the right is the Digital Colormeter application on a Mac. The mouse is sitting between the black border and the grayish border that you see on the button image.

Based on what we see on the pixelated image of the border, it appears the border has a tail or a shadow that covers many pixels. Take the Blac for instance, it has atleast 3 pixels(internal border). The external border is grayish - and it spans nearly 6 pixels.

Here is what I have done: I experiemented with several versions of Strokes and with BasicStroke(3.0F), I could produce 2 pixels of information for both the intenal and external border.

Here is my question: 1. Is such a "high touch" rendering possible using Swing in Java 7? 2. If so, can you please point me in the right direction?

thank you

È stato utile?

Soluzione

You can always create compound borders and stack them

class GUI extends JFrame {

    public static void main(String[] args) {

        new GUI();
    }

    GUI() {

        Border[] borders = new Border[]{
                   BorderFactory.createLineBorder(Color.GREEN, 3, true),
                   BorderFactory.createLineBorder(Color.BLACK, 3, true),
                   BorderFactory.createLineBorder(Color.GRAY, 6, true)};
        Border border = BorderFactory.createCompoundBorder(borders[2], 
                        BorderFactory.createCompoundBorder(borders[1], borders[0]));
        JButton button = new JButton("Button");
        button.setBorder(border);

        add(button);
        pack();
        setVisible(true);
    }
}

Edit1 - Stacking LineBorders

Here are many examples of creating gradients by stacking line borders. The code is long because of the amount of examples, you can just copy the private methods. There are over 3000 single Border components in the final view and I don't notice any performance issues.

class GUI extends JFrame {

    public static void main(String[] args) {

        new GUI();
    }

    public GUI() {

        JTabbedPane tabs = new JTabbedPane();
        JButton button;
        Border b1, b2, b3, b4, b5, b6;

        button = new JButton("Button");
        button.setBorder(compoundBorder(interpolateColors(Color.BLACK, Color.GREEN, 5)));
        tabs.addTab("Black-Green 5", button);

        button = new JButton("Button");
        button.setBorder(compoundBorder(interpolateColors(Color.BLACK, Color.GREEN, 100)));
        tabs.addTab("Black-Green 100", button);

        button = new JButton("Button");
        button.setBorder(compoundBorder(interpolateColors(Color.BLACK, Color.GREEN, 200)));
        tabs.addTab("Black-Green 200", button);

        button = new JButton("Button");
        button.setBorder(compoundBorder(interpolateColors(Color.GREEN, Color.BLACK, 5)));
        tabs.addTab("Green-Black 5", button);

        button = new JButton("Button");
        button.setBorder(compoundBorder(interpolateColors(Color.GREEN, Color.BLACK, 100)));
        tabs.addTab("Green-Black 100", button);

        button = new JButton("Button");
        button.setBorder(compoundBorder(interpolateColors(Color.GREEN, Color.BLACK, 200)));
        tabs.addTab("Green-Black 200", button);

        button = new JButton("Button");
        b1 = compoundBorder(interpolateColors(Color.GREEN, Color.BLACK, 5));
        b2 = compoundBorder(interpolateColors(Color.BLACK, Color.GRAY, 5));
        button.setBorder(BorderFactory.createCompoundBorder(b2, b1));
        tabs.add("Green-Black-Gray 5", button);

        button = new JButton("Button");
        b1 = compoundBorder(interpolateColors(Color.GREEN, Color.BLACK, 50));
        b2 = compoundBorder(interpolateColors(Color.BLACK, Color.GRAY, 50));
        button.setBorder(BorderFactory.createCompoundBorder(b2, b1));
        tabs.add("Green-Black-Gray 50", button);

        button = new JButton("Button");
        b1 = compoundBorder(interpolateColors(Color.GREEN, Color.BLACK, 100));
        b2 = compoundBorder(interpolateColors(Color.BLACK, Color.GRAY, 100));
        button.setBorder(BorderFactory.createCompoundBorder(b2, b1));
        tabs.add("Green-Black-Gray 100", button);

        button = new JButton("Button");
        b1 = compoundBorder(interpolateColors(Color.GREEN, Color.BLUE, 50));
        b2 = compoundBorder(interpolateColors(Color.BLUE, Color.RED, 50));
        b3 = compoundBorder(interpolateColors(Color.RED, Color.GREEN, 50));
        button.setBorder(compoundBorder(new Border[] {b1, b2, b3}));
        tabs.add("Green-Blue-Red-Green 50", button);

        button = new JButton("Button");
        b1 = compoundBorder(interpolateColors(Color.GREEN, Color.BLUE, 50));
        b2 = compoundBorder(interpolateColors(Color.BLUE, Color.RED, 50));
        b3 = compoundBorder(interpolateColors(Color.RED, Color.GREEN, 50));
        button.setBorder(compoundBorder(new Border[] {b3, b2, b1}));
        tabs.add("{Green, Blue, Red} 50", button);

        button = new JButton("Button");
        b1 = compoundBorder(interpolateColors(Color.MAGENTA, Color.BLUE, 2));
        b2 = compoundBorder(interpolateColors(Color.BLUE, Color.CYAN, 2));
        b3 = compoundBorder(interpolateColors(Color.CYAN, Color.GREEN, 2));
        b4 = compoundBorder(interpolateColors(Color.GREEN, Color.YELLOW, 2));
        b5 = compoundBorder(interpolateColors(Color.YELLOW, Color.ORANGE, 2));
        b6 = compoundBorder(interpolateColors(Color.ORANGE, Color.RED, 2));
        button.setBorder(compoundBorder(new Border[] {b1, b2, b3, b4, b5, b6}));
        tabs.add("Rainbow 2", button);

        button = new JButton("Button");
        b1 = compoundBorder(interpolateColors(Color.MAGENTA, Color.BLUE, 20));
        b2 = compoundBorder(interpolateColors(Color.BLUE, Color.CYAN, 20));
        b3 = compoundBorder(interpolateColors(Color.CYAN, Color.GREEN, 20));
        b4 = compoundBorder(interpolateColors(Color.GREEN, Color.YELLOW, 20));
        b5 = compoundBorder(interpolateColors(Color.YELLOW, Color.ORANGE, 20));
        b6 = compoundBorder(interpolateColors(Color.ORANGE, Color.RED, 20));
        button.setBorder(compoundBorder(new Border[] {b1, b2, b3, b4, b5, b6}));
        tabs.add("Rainbow 20", button);

        button = new JButton("Button");
        b1 = compoundBorder(interpolateColors(Color.MAGENTA, Color.BLUE, 40));
        b2 = compoundBorder(interpolateColors(Color.BLUE, Color.CYAN, 30));
        b3 = compoundBorder(interpolateColors(Color.CYAN, Color.GREEN, 15));
        b4 = compoundBorder(interpolateColors(Color.GREEN, Color.YELLOW, 15));
        b5 = compoundBorder(interpolateColors(Color.YELLOW, Color.ORANGE, 30));
        b6 = compoundBorder(interpolateColors(Color.ORANGE, Color.RED, 40));
        button.setBorder(compoundBorder(new Border[] {b1, b2, b3, b4, b5, b6}));
        tabs.add("Rainbow assymetric", button);

        add(tabs);
        pack();
        setSize(new Dimension(1000, 600));
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    private static Color[] interpolateColors(Color c1, Color c2, int width) {

        Color[] colors = new Color[width];
        for (int i = 0; i < width; i++) {
            colors[i] = new Color( (c2.getRed() - c1.getRed()) / width * i + c1.getRed(),
                                  (c2.getGreen() - c1.getGreen()) / width * i + c1.getGreen(),
                                  (c2.getBlue() - c1.getBlue()) / width * i + c1.getBlue() );
        }
        return colors;
    }

    private static Border compoundBorder(Color[] colors) {

        Border b = BorderFactory.createLineBorder(colors[0], 1, true);
        for (int i = 1; i < colors.length; i++)
            b = BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(colors[i], 1, true), b);
        return b;
    }

    private static Border compoundBorder(Border[] borders) {

        Border b = borders[0];
        for (int i = 1; i < borders.length; i++)
            b = BorderFactory.createCompoundBorder(borders[i], b);
        return b;
    }
}

Edit2 - Single StrokeBorder

Since the gradients can be radial or linear, you can't get a rectangular-symmetric border, but you can still get some nice results. To make good use of these you have to read RadialGradientPaint and LinearGradientPaint.

While you need only one border for this, there is a lot of setup to be done beforehand. Also, since the border is a graphics object and not a Swing object, it won't resize with the components is surrounds. The only way I can think of for really having a symmetrical border is to paint a rectangle (with Java2D) and tie it to the component's bounds such that it surrounds it through resizing. In any case, this can surely be useful in the right hands, but here are some examples.

class GUI extends JFrame {

    public static void main(String[] args) {

        new GUI();
    }

    public GUI() {

        JTabbedPane mainTabs = new JTabbedPane();
        JTabbedPane linTabs = new JTabbedPane();
        JTabbedPane radTabs = new JTabbedPane();
        JButton button;
        Point2D start, end;
        float[] dist;
        Color[] colors;
        BasicStroke stroke;

        start = new Point2D.Float(0, 0);
        end = new Point2D.Float(500, 500);
        dist = new float[] {0.0f, 0.2f, 1.0f};
        colors = new Color[] {Color.RED, Color.WHITE, Color.BLUE};
        LinearGradientPaint lgp;
        stroke = new BasicStroke(5);
/// Linear ///
        button = new JButton("Button");
        lgp = new LinearGradientPaint(start, end, dist, colors);
        button.setBorder(BorderFactory.createStrokeBorder(stroke, lgp));
        linTabs.addTab("Red-White-Blue 5", button);

        button = new JButton("Button");
        end = new Point2D.Float(200, 200);
        lgp = new LinearGradientPaint(start, end, dist, colors, CycleMethod.REFLECT);
        button.setBorder(BorderFactory.createStrokeBorder(stroke, lgp));
        linTabs.addTab("Red-White-Blue Reflect 5", button);

        button = new JButton("Button");
        end = new Point2D.Float(500, 500);
        lgp = new LinearGradientPaint(start, end, dist, colors, CycleMethod.REPEAT);
        button.setBorder(BorderFactory.createStrokeBorder(stroke, lgp));
        linTabs.addTab("Red-White-Blue Repeat 5", button);

        stroke = new BasicStroke(20);
        button = new JButton("Button");
        button.setBorder(BorderFactory.createStrokeBorder(stroke, lgp));
        linTabs.addTab("Red-White-Blue 20", button);

        button = new JButton("Button");
        end = new Point2D.Float(200, 200);
        lgp = new LinearGradientPaint(start, end, dist, colors, CycleMethod.REFLECT);
        button.setBorder(BorderFactory.createStrokeBorder(stroke, lgp));
        linTabs.addTab("Red-White-Blue Reflect 20", button);

        button = new JButton("Button");
        end = new Point2D.Float(500, 500);
        lgp = new LinearGradientPaint(start, end, dist, colors, CycleMethod.REPEAT);
        button.setBorder(BorderFactory.createStrokeBorder(stroke, lgp));
        linTabs.addTab("Red-White-Blue Repeat 20", button);

        dist = new float[] {0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1f};
        colors = new Color[] {Color.RED, Color.ORANGE, Color.YELLOW, Color.LIGHT_GRAY,
                                Color.BLACK, Color.RED};
        stroke = new BasicStroke(5);

        button = new JButton("Button");
        lgp = new LinearGradientPaint(start, end, dist, colors);
        button.setBorder(BorderFactory.createStrokeBorder(stroke, lgp));
        linTabs.addTab("Dark 5", button);

        button = new JButton("Button");
        end = new Point2D.Float(200, 200);
        lgp = new LinearGradientPaint(start, end, dist, colors, CycleMethod.REFLECT);
        button.setBorder(BorderFactory.createStrokeBorder(stroke, lgp));
        linTabs.addTab("Dark Reflect 5", button);

        button = new JButton("Button");
        end = new Point2D.Float(500, 500);
        lgp = new LinearGradientPaint(start, end, dist, colors, CycleMethod.REPEAT);
        button.setBorder(BorderFactory.createStrokeBorder(stroke, lgp));
        linTabs.addTab("Dark Repeat 5", button);

        stroke = new BasicStroke(20);
        button = new JButton("Button");
        button.setBorder(BorderFactory.createStrokeBorder(stroke, lgp));
        linTabs.addTab("Dark 20", button);

        button = new JButton("Button");
        end = new Point2D.Float(200, 200);
        lgp = new LinearGradientPaint(start, end, dist, colors, CycleMethod.REFLECT);
        button.setBorder(BorderFactory.createStrokeBorder(stroke, lgp));
        linTabs.addTab("Dark Reflect 20", button);

        button = new JButton("Button");
        end = new Point2D.Float(500, 500);
        lgp = new LinearGradientPaint(start, end, dist, colors, CycleMethod.REPEAT);
        button.setBorder(BorderFactory.createStrokeBorder(stroke, lgp));
        linTabs.addTab("Dark Repeat 20", button);
/// Radial ///
        Point2D center = new Point2D.Float(20, 20);
        float radius = 1;
        dist = new float[] {0.0f, 0.2f, 1.0f};
        colors = new Color[] {Color.RED, Color.WHITE, Color.BLUE};
        RadialGradientPaint  rgp;
        stroke = new BasicStroke(40);

        button = new JButton("Button");
        rgp = new RadialGradientPaint(center, radius, dist, colors, CycleMethod.REPEAT);
        button.setBorder(BorderFactory.createStrokeBorder(stroke, rgp));
        radTabs.addTab("{Red, Blue White} assymetric 40", button);

        button = new JButton("Button");
        radius = 300;
        stroke = new BasicStroke(10);
        center = new Point2D.Float(500, 250);
        rgp = new RadialGradientPaint(center, radius, dist, colors, CycleMethod.REPEAT);
        button.setBorder(BorderFactory.createStrokeBorder(stroke, rgp));
        radTabs.addTab("{Red, Blue White} REPEAT 40", button);

        button = new JButton("Button");
        radius = 150;
        rgp = new RadialGradientPaint(center, radius, dist, colors, CycleMethod.REFLECT);
        button.setBorder(BorderFactory.createStrokeBorder(stroke, rgp));
        radTabs.addTab("{Red, Blue White} Reflect 40", button);

        colors = new Color[] {Color.PINK, Color.MAGENTA, Color.BLUE, Color.CYAN, Color.GREEN, Color.PINK};
        dist = new float[] {0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1f};

        button = new JButton("Button");
        radius = 70;
        Point2D focus = new Point2D.Float(40, 90);
        rgp = new RadialGradientPaint(center, radius, focus, dist, colors, CycleMethod.REFLECT);
        button.setBorder(BorderFactory.createStrokeBorder(stroke, rgp));
        radTabs.addTab("Light Reflect assymetric", button);

        button = new JButton("Button");
        rgp = new RadialGradientPaint(center, radius, focus, dist, colors, CycleMethod.REPEAT);
        button.setBorder(BorderFactory.createStrokeBorder(stroke, rgp));
        radTabs.addTab("Light Repeat assymetric", button);

        button = new JButton("Button");
        radius = 70;
        stroke = new BasicStroke(10);
        center = new Point2D.Float(500, 250);
        rgp = new RadialGradientPaint(center, radius, dist, colors, CycleMethod.REFLECT);
        button.setBorder(BorderFactory.createStrokeBorder(stroke, rgp));
        radTabs.addTab("Light Reflect 10", button);

        button = new JButton("Button");
        stroke = new BasicStroke(10);
        center = new Point2D.Float(500, 250);
        rgp = new RadialGradientPaint(center, radius, dist, colors, CycleMethod.REPEAT);
        button.setBorder(BorderFactory.createStrokeBorder(stroke, rgp));
        radTabs.addTab("Light Repeat 10", button);

        mainTabs.addTab("Linear", linTabs);
        mainTabs.addTab("Radial", radTabs);
        add(mainTabs);
        pack();
        setSize(new Dimension(1000, 600));
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }
}

Comments and ideas are welcome.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top