ポップアップでTextBubbleBorderを使用します

Sergiy Medvynskyy:

彼のためのアンドリュー・トンプソンのすべての多くの感謝の最初のソリューション角丸のボーダーについて。

今、私の問題。私は、我々のアプリケーション機能(新しいコンポーネントを指して、小さな泡)に「新は何ですか」を追加してみてください。すべては、境界線の透過機能を除いて罰金を動作します。ここに私のMCVEがある(それはアンドリューによって書かれたコードが含まれているため、申し訳ありません、それは、少し長いです)。

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.font.TextAttribute;
import java.awt.geom.Area;
import java.awt.geom.RoundRectangle2D;
import java.util.Collections;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.Popup;
import javax.swing.PopupFactory;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.border.AbstractBorder;

/**
 * <code>PopupTryout</code>.
 */
public class PopupTryout {

    public static void main(String[] args) {
        JFrame frm = new JFrame("Popup test");
        JButton button = new JButton("Test");
        JPanel p = new JPanel();
        p.add(button);
        frm.add(p, BorderLayout.SOUTH);
        frm.add(new JScrollPane(new JTextArea()));
        JPanel hintPanel = new JPanel();
        hintPanel.add(new JLabel("This button has no function ;)"));
        hintPanel.setOpaque(false);
        JLabel closeBtn = new JLabel("Close");
        closeBtn.setForeground(Color.BLUE);
        closeBtn.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        hintPanel.add(closeBtn);
        hintPanel.setBorder(new TextBubbleBorder(Color.BLACK, 1, 6, 8, false));

        frm.setSize(600, 500);
        frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frm.setLocationRelativeTo(null);
        frm.setVisible(true);
        Point pt = button.getLocationOnScreen();
        Dimension panelSize = hintPanel.getPreferredSize();
        Dimension buttonSize = button.getSize();
        int x = pt.x + buttonSize.width - panelSize.width;
        int y = pt.y - panelSize.height - 10;
        // popup should only be closed when user clicks the "Close" button.
        Popup popup = PopupFactory.getSharedInstance().getPopup(button, hintPanel, x, y);
        popup.show();
        // "link style" button
        closeBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
                Font f = e.getComponent().getFont();
                e.getComponent().setFont(underlineOn(f));
            }

            @Override
            public void mouseExited(MouseEvent e) {
                e.getComponent().setFont(UIManager.getFont("Label.font"));
            }

            @Override
            public void mousePressed(MouseEvent e) {
                popup.hide();
            }
        });
    }

    /**
     * Gets the underline font for the given base font.
     * 
     * @param aBaseFont base font to paint it as underline.
     * @return underline font.
     */
    public static Font underlineOn(Font aBaseFont) {
        return aBaseFont.deriveFont(Collections.singletonMap(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON));
    }

    static class TextBubbleBorder extends AbstractBorder {

        private Color color;

        private int thickness = 4;

        private int radii = 8;

        private int pointerSize = 7;

        private Insets insets = null;

        private BasicStroke stroke = null;

        private int strokePad;

        private int pointerPad = 4;

        private boolean left = true;

        RenderingHints hints;

        TextBubbleBorder(Color color) {
            this(color, 4, 8, 7);
        }

        TextBubbleBorder(Color color, int thickness, int radii, int pointerSize) {
            this.thickness = thickness;
            this.radii = radii;
            this.pointerSize = pointerSize;
            this.color = color;

            stroke = new BasicStroke(thickness);
            strokePad = thickness / 2;

            hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            int pad = radii + strokePad;
            int bottomPad = pad + pointerSize + strokePad;
            insets = new Insets(pad, pad, bottomPad, pad);
        }

        TextBubbleBorder(Color color, int thickness, int radii, int pointerSize, boolean left) {
            this(color, thickness, radii, pointerSize);
            this.left = left;
        }

        @Override
        public Insets getBorderInsets(Component c) {
            return insets;
        }

        @Override
        public Insets getBorderInsets(Component c, Insets insets) {
            return getBorderInsets(c);
        }

        @Override
        public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {

            Graphics2D g2 = (Graphics2D) g;

            int bottomLineY = height - thickness - pointerSize;

            RoundRectangle2D.Double bubble =
                    new RoundRectangle2D.Double(0 + strokePad, 0 + strokePad, width - thickness, bottomLineY, radii, radii);

            Polygon pointer = new Polygon();

            if (left) {
                // left point
                pointer.addPoint(strokePad + radii + pointerPad, bottomLineY);
                // right point
                pointer.addPoint(strokePad + radii + pointerPad + pointerSize, bottomLineY);
                // bottom point
                pointer.addPoint(strokePad + radii + pointerPad + (pointerSize / 2), height - strokePad);
            } else {
                // left point
                pointer.addPoint(width - (strokePad + radii + pointerPad), bottomLineY);
                // right point
                pointer.addPoint(width - (strokePad + radii + pointerPad + pointerSize), bottomLineY);
                // bottom point
                pointer.addPoint(width - (strokePad + radii + pointerPad + (pointerSize / 2)), height - strokePad);
            }

            Area area = new Area(bubble);
            area.add(new Area(pointer));

            g2.setRenderingHints(hints);

            // Paint the BG color of the parent, everywhere outside the clip
            // of the text bubble.
            Component parent = c.getParent();
            if (parent != null) {
                Color bg = parent.getBackground();
                Rectangle rect = new Rectangle(0, 0, width, height);
                Area borderRegion = new Area(rect);
                borderRegion.subtract(area);
                g2.setClip(borderRegion);
                g2.setColor(bg);
                g2.fillRect(0, 0, width, height);
                g2.setClip(null);
            }

            g2.setColor(color);
            g2.setStroke(stroke);
            g2.draw(area);
        }
    }
}

ここで私が持っている結果です ここでは、画像の説明を入力します。

あなたが見ることができるように、ポップアップの下部には、透明ではありません。私はそれはとても(最初の溶液は、このような場合に適していない)理由を理解、それを修正するための解決策を見つけることができません。何か案は?

ATER:

見てください半透明さと形状スイングのWindowsを| Java.netそれは助けかもしれません。

// Add Popup to a transparent JWindow to create and display.
PopupFactory.setSharedInstance(new TranslucentPopupFactory());

// popup should only be closed when user clicks the "Close" button.
Popup popup = PopupFactory.getSharedInstance().getPopup(button, hintPanel, x, y);

PopupTryout2.java

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.font.TextAttribute;
import java.awt.geom.Area;
import java.awt.geom.RoundRectangle2D;
import java.util.Collections;
import javax.swing.*;
import javax.swing.border.AbstractBorder;

public class PopupTryout2 {
  public static void main(String[] args) {
    JFrame frm = new JFrame("Popup test");
    JButton button = new JButton("Test");
    JPanel p = new JPanel();
    p.add(button);
    frm.add(p, BorderLayout.SOUTH);
    frm.add(new JScrollPane(new JTextArea()));

    JPanel hintPanel = new JPanel();
    hintPanel.add(new JLabel("This button has no function ;)"));
    hintPanel.setOpaque(false);
    JLabel closeBtn = new JLabel("Close");
    closeBtn.setForeground(Color.BLUE);
    closeBtn.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
    hintPanel.add(closeBtn);
    hintPanel.setBorder(new TextBubbleBorder(Color.BLACK, 1, 6, 8, false));
    hintPanel.setOpaque(false);

    frm.setSize(600, 500);
    frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frm.setLocationRelativeTo(null);
    frm.setVisible(true);
    Point pt = button.getLocationOnScreen();
    Dimension panelSize = hintPanel.getPreferredSize();
    Dimension buttonSize = button.getSize();
    int x = pt.x + buttonSize.width - panelSize.width;
    int y = pt.y - panelSize.height - 10;

    PopupFactory.setSharedInstance(new TranslucentPopupFactory());

    // popup should only be closed when user clicks the "Close" button.
    Popup popup = PopupFactory.getSharedInstance().getPopup(button, hintPanel, x, y);

    popup.show();
    // "link style" button
    closeBtn.addMouseListener(new MouseAdapter() {
      @Override public void mouseEntered(MouseEvent e) {
        Font f = e.getComponent().getFont();
        e.getComponent().setFont(underlineOn(f));
      }

      @Override public void mouseExited(MouseEvent e) {
        e.getComponent().setFont(UIManager.getFont("Label.font"));
      }

      @Override public void mousePressed(MouseEvent e) {
        popup.hide();
      }
    });
  }

  public static Font underlineOn(Font aBaseFont) {
    return aBaseFont.deriveFont(Collections.singletonMap(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON));
  }

  static class TextBubbleBorder extends AbstractBorder {
    private Color color;
    private int thickness = 4;
    private int radii = 8;
    private int pointerSize = 7;
    private Insets insets = null;
    private BasicStroke stroke = null;
    private int strokePad;
    private int pointerPad = 4;
    private boolean left = true;
    RenderingHints hints;

    TextBubbleBorder(Color color) {
      this(color, 4, 8, 7);
    }

    TextBubbleBorder(Color color, int thickness, int radii, int pointerSize) {
      this.thickness = thickness;
      this.radii = radii;
      this.pointerSize = pointerSize;
      this.color = color;

      stroke = new BasicStroke(thickness);
      strokePad = thickness / 2;

      hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

      int pad = radii + strokePad;
      int bottomPad = pad + pointerSize + strokePad;
      insets = new Insets(pad, pad, bottomPad, pad);
    }

    TextBubbleBorder(Color color, int thickness, int radii, int pointerSize, boolean left) {
      this(color, thickness, radii, pointerSize);
      this.left = left;
    }

    @Override public Insets getBorderInsets(Component c) {
      return insets;
    }

    @Override public Insets getBorderInsets(Component c, Insets insets) {
      return getBorderInsets(c);
    }

    @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
      Graphics2D g2 = (Graphics2D) g;
      int bottomLineY = height - thickness - pointerSize;
      RoundRectangle2D.Double bubble =
        new RoundRectangle2D.Double(0 + strokePad, 0 + strokePad, width - thickness, bottomLineY, radii, radii);

      Polygon pointer = new Polygon();

      if (left) {
        pointer.addPoint(strokePad + radii + pointerPad, bottomLineY);
        pointer.addPoint(strokePad + radii + pointerPad + pointerSize, bottomLineY);
        pointer.addPoint(strokePad + radii + pointerPad + (pointerSize / 2), height - strokePad);
      } else {
        pointer.addPoint(width - (strokePad + radii + pointerPad), bottomLineY);
        pointer.addPoint(width - (strokePad + radii + pointerPad + pointerSize), bottomLineY);
        pointer.addPoint(width - (strokePad + radii + pointerPad + (pointerSize / 2)), height - strokePad);
      }

      Area area = new Area(bubble);
      area.add(new Area(pointer));

      g2.setRenderingHints(hints);

      // Paint the BG color of the parent, everywhere outside the clip
      // of the text bubble.
      Component parent = c.getParent();
      if (parent != null) {
        Color bg = parent.getBackground();
        // Rectangle rect = new Rectangle(0, 0, width, height);
        // Area borderRegion = new Area(rect);
        // borderRegion.subtract(area);
        // g2.setClip(borderRegion);
        // g2.setColor(bg);
        // g2.fillRect(0, 0, width, height);
        // g2.setClip(null);
        g2.setPaint(bg);
        g2.fill(area);
      }
      g2.setColor(color);
      g2.setStroke(stroke);
      g2.draw(area);
    }
  }
}

/*
@see http://today.java.net/pub/a/today/2008/03/18/translucent-and-shaped-swing-windows.html
https://web.archive.org/web/20150515015137/http://today.java.net/pub/a/today/2008/03/18/translucent-and-shaped-swing-windows.html
Translucent and Shaped Swing Windows | Java.net
*/
class TranslucentPopupFactory extends PopupFactory {
  @Override public Popup getPopup(Component owner, Component contents, int x, int y) {
    return new TranslucentPopup(owner, contents, x, y);
  }
}

class TranslucentPopup extends Popup {
  private final JWindow popupWindow;

  protected TranslucentPopup(Component owner, Component contents, int ownerX, int ownerY) {
    super(owner, contents, ownerX, ownerY);
    // create a new heavyweight window
    this.popupWindow = new JWindow();
    // mark the popup with partial opacity
    // AWTUtilities.setWindowOpacity(popupWindow, (contents instanceof JToolTip) ? .8f : .95f);
    // popupWindow.setOpacity(.5f);
    // AWTUtilities.setWindowOpaque(popupWindow, false); // Java 1.6.0_10
    popupWindow.setBackground(new Color(0x0, true)); // Java 1.7.0
    // determine the popup location
    popupWindow.setLocation(ownerX, ownerY);
    // add the contents to the popup
    popupWindow.getContentPane().add(contents);
    contents.invalidate();
    // JComponent parent = (JComponent) contents.getParent();
    // set the shadow border
    // parent.setBorder(new ShadowPopupBorder());
  }

  @Override public void show() {
    System.out.println("Always Heavy weight!");
    this.popupWindow.setVisible(true);
    this.popupWindow.pack();
    // mark the window as non-opaque, so that the
    // shadow border pixels take on the per-pixel
    // translucency
    // AWTUtilities.setWindowOpaque(this.popupWindow, false);
  }

  @Override public void hide() {
    this.popupWindow.setVisible(false);
    this.popupWindow.removeAll();
    this.popupWindow.dispose();
  }
}

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=281846&siteId=1