// -*- mode:java; encoding:utf-8 -*- // vim:set fileencoding=utf-8: // @homepage@ package example; import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.awt.image.BufferedImageOp; import java.awt.image.ByteLookupTable; import java.awt.image.LookupOp; import java.io.IOException; import java.net.URL; import java.util.Objects; import java.util.Optional; import java.util.stream.IntStream; import java.util.stream.Stream; import javax.imageio.ImageIO; import javax.swing.*; import javax.swing.border.Border; public final class MainPanel extends JPanel { public static final Paint TEXTURE = ImageUtil.makeCheckerTexture(); private MainPanel() { super(new BorderLayout()); JPanel p = new JPanel() { @Override protected void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g.create(); g2.setPaint(TEXTURE); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .6f)); g2.fillRect(0, 0, getWidth(), getHeight()); g2.dispose(); } }; p.add(new JButton("button")); JInternalFrame frame = new JInternalFrame("InternalFrame", true, true, true, true); frame.setContentPane(p); frame.setSize(160, 80); frame.setLocation(10, 10); frame.setOpaque(false); frame.setVisible(true); // @Override protected void paintComponent(Graphics g) { // super.paintComponent(g); // Graphics2D g2 = (Graphics2D) g.create(); // g2.setPaint(new Color(100, 100, 100, 100)); // g2.fillRect(0, 0, getWidth(), getHeight()); // g2.dispose(); // } JDesktopPane desktop = new JDesktopPane() { @Override public void updateUI() { super.updateUI(); setOpaque(false); } // @Override protected void paintComponent(Graphics g) { // super.paintComponent(g); // Graphics2D g2 = (Graphics2D) g.create(); // g2.setPaint(new Color(100, 100, 100, 100)); // g2.fillRect(0, 0, getWidth(), getHeight()); // g2.dispose(); // } }; desktop.add(frame); add(desktop); setOpaque(false); setPreferredSize(new Dimension(320, 240)); } public static void main(String[] args) { EventQueue.invokeLater(MainPanel::createAndShowGui); } private static void createAndShowGui() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); Toolkit.getDefaultToolkit().beep(); } PopupFactory.setSharedInstance(new TranslucentPopupFactory()); JFrame frame = new JFrame("@title@") { @Override protected JRootPane createRootPane() { return new JRootPane() { // private final Paint texture = makeCheckerTexture(); @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g.create(); g2.setPaint(TEXTURE); g2.fillRect(0, 0, getWidth(), getHeight()); g2.dispose(); } @Override public void updateUI() { super.updateUI(); URL url = MainPanel.class.getResource("test.jpg"); BufferedImage bi = ImageUtil.getFilteredImage(url); setBorder(new CentredBackgroundBorder(bi)); setOpaque(false); } }; } }; // frame.getRootPane().setBackground(Color.BLUE); // frame.getLayeredPane().setBackground(Color.GREEN); // frame.getContentPane().setBackground(Color.RED); Container contentPane = frame.getContentPane(); if (contentPane instanceof JComponent) { ((JComponent) contentPane).setOpaque(false); } frame.setJMenuBar(ImageUtil.createMenuBar()); frame.getContentPane().add(new MainPanel()); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } } final class ImageUtil { private ImageUtil() { /* Singleton */ } public static JMenuBar createMenuBar() { UIManager.put("Menu.background", new Color(200, 0, 0, 0)); UIManager.put("Menu.selectionBackground", new Color(100, 100, 255, 100)); UIManager.put("Menu.selectionForeground", new Color(200, 200, 200)); UIManager.put("Menu.useMenuBarBackgroundForTopLevel", Boolean.TRUE); JMenuBar mb = new JMenuBar() { @Override protected void paintComponent(Graphics g) { // super.paintComponent(g); Graphics2D g2 = (Graphics2D) g.create(); g2.setPaint(new Color(100, 100, 100, 100)); g2.fillRect(0, 0, getWidth(), getHeight()); g2.dispose(); } }; mb.setOpaque(false); Stream.of("File", "Edit", "Help").map(ImageUtil::createMenu).forEach(mb::add); return mb; } private static JMenu createMenu(String key) { JMenu menu = new TransparentMenu(key); menu.setForeground(new Color(200, 200, 200)); menu.setOpaque(false); // Motif lnf JMenu sub = new TransparentMenu("Submenu"); sub.add("JMenuItem"); sub.add("Looooooooooooooooooooong"); menu.add(sub); menu.add("dummy1"); menu.add("dummy2"); return menu; } public static BufferedImage getFilteredImage(URL url) { BufferedImage image = Optional.ofNullable(url) .map(u -> { try { return ImageIO.read(u); } catch (IOException ex) { return makeMissingImage(); } }).orElseGet(ImageUtil::makeMissingImage); BufferedImage dest = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB); byte[] b = new byte[256]; IntStream.range(0, b.length).forEach(i -> b[i] = (byte) (i * .5)); BufferedImageOp op = new LookupOp(new ByteLookupTable(0, b), null); op.filter(image, dest); return dest; } private static BufferedImage makeMissingImage() { Icon missingIcon = UIManager.getIcon("OptionPane.errorIcon"); int w = missingIcon.getIconWidth(); int h = missingIcon.getIconHeight(); BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics2D g2 = bi.createGraphics(); missingIcon.paintIcon(null, g2, 0, 0); g2.dispose(); return bi; } public static TexturePaint makeCheckerTexture() { int cs = 6; int sz = cs * cs; BufferedImage img = new BufferedImage(sz, sz, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); g2.setPaint(new Color(120, 120, 120)); g2.fillRect(0, 0, sz, sz); g2.setPaint(new Color(200, 200, 200, 20)); for (int i = 0; i * cs < sz; i++) { for (int j = 0; j * cs < sz; j++) { if ((i + j) % 2 == 0) { g2.fillRect(i * cs, j * cs, cs, cs); } } } g2.dispose(); return new TexturePaint(img, new Rectangle(sz, sz)); } } // https://community.oracle.com/thread/1395763 How can I use TextArea with Background Picture ? // https://ateraimemo.com/Swing/CentredBackgroundBorder.html class CentredBackgroundBorder implements Border { private final BufferedImage image; protected CentredBackgroundBorder(BufferedImage image) { this.image = image; } @Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { int cx = (width - image.getWidth()) / 2; int cy = (height - image.getHeight()) / 2; Graphics2D g2 = (Graphics2D) g.create(); g2.translate(x, y); g2.drawRenderedImage(image, AffineTransform.getTranslateInstance(cx, cy)); g2.dispose(); } @Override public Insets getBorderInsets(Component c) { return new Insets(0, 0, 0, 0); } @Override public boolean isBorderOpaque() { return true; } } // https://ateraimemo.com/Swing/TranslucentPopupMenu.html class TranslucentPopupMenu extends JPopupMenu { private static final Paint POPUP_BACK = new Color(250, 250, 250, 100); private static final Paint POPUP_LEFT = new Color(230, 230, 230, 100); private static final int LEFT_WIDTH = 24; @Override public boolean isOpaque() { return false; } @Override public Component add(Component c) { if (c instanceof JComponent) { ((JComponent) c).setOpaque(false); } return c; } @Override public JMenuItem add(JMenuItem menuItem) { menuItem.setOpaque(false); return super.add(menuItem); } // private static final Color ALPHA_ZERO = new Color(0x0, true); // @Override public void show(Component c, int x, int y) { // EventQueue.invokeLater(() -> { // Container p = getTopLevelAncestor(); // if (p instanceof JWindow) { // System.out.println("Heavy weight"); // p.setBackground(ALPHA_ZERO); // } else { // System.out.println("Light weight"); // } // }); // super.show(c, x, y); // } @Override protected void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g.create(); g2.setPaint(POPUP_LEFT); g2.fillRect(0, 0, LEFT_WIDTH, getHeight()); g2.setPaint(POPUP_BACK); g2.fillRect(LEFT_WIDTH, 0, getWidth(), getHeight()); g2.dispose(); } } class TransparentMenu extends JMenu { private JPopupMenu popupMenu; protected TransparentMenu(String title) { super(title); } // [JDK-4688783] JPopupMenu hardcoded i JMenu - Java Bug System // https://bugs.openjdk.java.net/browse/JDK-4688783 private void ensurePopupMenuCreated2() { if (Objects.isNull(popupMenu)) { this.popupMenu = new TranslucentPopupMenu(); popupMenu.setInvoker(this); popupListener = createWinListener(popupMenu); } } @Override public JPopupMenu getPopupMenu() { ensurePopupMenuCreated2(); return popupMenu; } @Override public JMenuItem add(JMenuItem menuItem) { ensurePopupMenuCreated2(); menuItem.setOpaque(false); return popupMenu.add(menuItem); } @Override public Component add(Component c) { ensurePopupMenuCreated2(); if (c instanceof JComponent) { ((JComponent) c).setOpaque(false); } popupMenu.add(c); return c; } @Override public void addSeparator() { ensurePopupMenuCreated2(); popupMenu.addSeparator(); } @Override public void insert(String s, int pos) { if (pos < 0) { throw new IllegalArgumentException("index less than zero."); } ensurePopupMenuCreated2(); popupMenu.insert(new JMenuItem(s), pos); } @Override public JMenuItem insert(JMenuItem mi, int pos) { if (pos < 0) { throw new IllegalArgumentException("index less than zero."); } ensurePopupMenuCreated2(); popupMenu.insert(mi, pos); return mi; } @Override public void insertSeparator(int index) { if (index < 0) { throw new IllegalArgumentException("Separator index less than zero."); } ensurePopupMenuCreated2(); popupMenu.insert(new JPopupMenu.Separator(), index); } @Override public boolean isPopupMenuVisible() { ensurePopupMenuCreated2(); return popupMenu.isVisible(); } } /* <a href="http://today.java.net/pub/a/today/2008/03/18/translucent-and-shaped-swing-windows.html"> Translucent and Shaped Swing Windows | Java.net </a> */ class TranslucentPopupFactory extends PopupFactory { @Override public Popup getPopup(Component owner, Component contents, int x, int y) { // throws IllegalArgumentException { 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(); } }