Jetez un œil sur Fenêtres Swing transparentes et personnalisées | Java.net. Peut-être que cela vous aidera.
// Ajouter Popup à une JWindow transparente pour créer et afficher.
PopupFactory.setSharedInstance(new TranslucentPopupFactory());
// Le popup doit être fermé uniquement lorsque l'utilisateur clique sur le bouton "Fermer".
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("Test de Popup");
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("Ce bouton n'a pas de fonction ;)"));
hintPanel.setOpaque(false);
JLabel closeBtn = new JLabel("Fermer");
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());
// Le popup doit être fermé uniquement lorsque l'utilisateur clique sur le bouton "Fermer".
Popup popup = PopupFactory.getSharedInstance().getPopup(button, hintPanel, x, y);
popup.show();
// Bouton de style "lien"
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);
// Peindre la couleur d'arrière-plan du parent, partout en dehors du clip
// de la bulle de texte.
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
Fenêtres Swing transparentes et personnalisées | 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);
// Créer une nouvelle fenêtre lourde
this.popupWindow = new JWindow();
// Marquer le popup avec une opacité partielle
// 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
// Déterminer l'emplacement du popup
popupWindow.setLocation(ownerX, ownerY);
// Ajouter le contenu au popup
popupWindow.getContentPane().add(contents);
contents.invalidate();
// JComponent parent = (JComponent) contents.getParent();
// Définir la bordure d'ombre
// parent.setBorder(new ShadowPopupBorder());
}
@Override public void show() {
System.out.println("Toujours lourde !");
this.popupWindow.setVisible(true);
this.popupWindow.pack();
// Marquer la fenêtre comme non opaque, afin que les
// pixels de la bordure d'ombre prennent en charge la translucidité par pixel.
// AWTUtilities.setWindowOpaque(this.popupWindow, false);
}
@Override public void hide() {
this.popupWindow.setVisible(false);
this.popupWindow.removeAll();
this.popupWindow.dispose();
}
}