概要

Synthを使ったLookAndFeelで、JInternalFrameを半透明にします。

サンプルコード

try {
  for (UIManager.LookAndFeelInfo laf: UIManager.getInstalledLookAndFeels())
    if ("Nimbus".equals(laf.getName())) {
      UIManager.setLookAndFeel(laf.getClassName());
      SynthLookAndFeel.setStyleFactory(
        new MySynthStyleFactory(SynthLookAndFeel.getStyleFactory()));
      break;
    }
  }
} catch (Exception e) {
  e.printStackTrace();
}
view all
class MySynthStyleFactory extends SynthStyleFactory {
  private SynthStyleFactory wrappedFactory;
  public MySynthStyleFactory(SynthStyleFactory factory) {
    this.wrappedFactory = factory;
  }
  @Override public SynthStyle getStyle(JComponent c, Region id) {
    SynthStyle s = wrappedFactory.getStyle(c, id);
    //if (id == Region.INTERNAL_FRAME_TITLE_PANE||id == Region.INTERNAL_FRAME) {
    if (id == Region.INTERNAL_FRAME) {
      s = new TranslucentSynthStyle(s);
    }
    return s;
  }
}
class TranslucentSynthStyle extends SynthStyle {
  private final SynthStyle style;
  public TranslucentSynthStyle(SynthStyle s) {
    style = s;
  }
  @Override public SynthPainter getPainter(final SynthContext context) {
    return new SynthPainter() {
      @Override public void paintInternalFrameBackground(SynthContext context,
                           Graphics g, int x, int y, int w, int h) {
        g.setColor(new Color(100, 200, 100, 100));
        g.fillRoundRect(x, y, w - 1, h - 1, 15, 15);
      }
    };
  }
  @Override public boolean isOpaque(SynthContext context) {
    if (context.getRegion() == Region.INTERNAL_FRAME) {
      return false;
    } else {
      return style.isOpaque(context);
    }
  }
  @Override public Color getColorForState(SynthContext context, ColorType type) {
    return null; //Color.RED;
  }
  @Override public Font getFontForState(SynthContext context) {
    return null; //new Font(Font.MONOSPACED, Font.ITALIC, 24);
  }
  //...

解説

上記のサンプルでは、SynthStyle#paintInternalFrameBackgroundSynthStyle#isOpaqueなどのメソッドをオーバーライドしてJInternalFrameを半透明にします。


  • Synthを使ったLookAndFeel
    • JDK 1.6.0_10で追加されたNimbusLookAndFeelや、GTKLookAndFeelなど
TranslucentFrame1.png

JDK 1.7.0以上でNimbusLookAndFeelを使用する場合、以下のようにUIDefaults#put(...)javax.swing.Painterを設定する方法もあります。

import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.synth.*;
//import com.sun.java.swing.Painter; // 1.6
import javax.swing.Painter;

public class BackgroundPainterTest {
  private final JDesktopPane desktop = new JDesktopPane();
  public JComponent makeUI() {
    JPanel p1 = new JPanel();
    p1.setOpaque(false);
    JPanel p2 = new JPanel() {
      @Override protected void paintComponent(Graphics g) {
        g.setColor(new Color(100, 50, 50, 100));
        g.fillRect(0, 0, getWidth(), getHeight());
      }
    };
    p2.setOpaque(false);
    UIDefaults d = new UIDefaults();
    d.put("InternalFrame[Enabled].backgroundPainter", new Painter<JComponent>() {
      @Override public void paint(Graphics2D g, JComponent c, int w, int h) {
        g.setColor(new Color(100, 200, 100, 100));
        g.fillRoundRect(0, 0, w - 1, h - 1, 15, 15);
      }
    });
    d.put("InternalFrame[Enabled+WindowFocused].backgroundPainter", new Painter<JComponent>() {
      @Override public void paint(Graphics2D g, JComponent c, int w, int h) {
        g.setColor(new Color(100, 250, 120, 100));
        g.fillRoundRect(0, 0, w - 1, h - 1, 15, 15);
      }
    });
    createFrame(p1, d, 0);
    createFrame(p2, d, 1);
    JPanel p = new JPanel(new BorderLayout());
    p.add(desktop);
    p.setPreferredSize(new Dimension(320, 240));
    return p;
  }
  protected JInternalFrame createFrame(JPanel panel, UIDefaults d, int idx) {
    MyInternalFrame frame = new MyInternalFrame();
    frame.putClientProperty("Nimbus.Overrides", d);
    //frame.putClientProperty("Nimbus.Overrides.InheritDefaults", false);
    frame.setOpaque(false);
    if (panel != null) {
      frame.setContentPane(panel);
      panel.add(new JLabel("label"));
      panel.add(new JButton("button"));
      frame.getRootPane().setOpaque(false);
    }
    desktop.add(frame);
    frame.setVisible(true);
    frame.setLocation(10 + 60 * idx, 10 + 40 * idx);
    desktop.getDesktopManager().activateFrame(frame);
    return frame;
  }
  static class MyInternalFrame extends JInternalFrame {
    public MyInternalFrame() {
      super("title", true, true, true, true);
      setSize(160, 100);
    }
  }
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    try {
      for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
        if ("Nimbus".equals(laf.getName())) {
          UIManager.setLookAndFeel(laf.getClassName());
          break;
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.getContentPane().add(new BackgroundPainterTest().makeUI());
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}

参考リンク

コメント