Swing/RoundImageButton のバックアップの現在との差分(No.4)
- バックアップ一覧
- 差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- バックアップ を表示
- Swing/RoundImageButton へ行く。
- 1 (2008-07-21 (月) 16:27:56)
- 2 (2008-07-22 (火) 15:56:11)
- 3 (2008-07-22 (火) 19:26:22)
- 4 (2008-10-01 (水) 17:22:22)
- 5 (2009-01-05 (月) 16:55:06)
- 6 (2009-01-07 (水) 20:04:04)
- 7 (2009-01-09 (金) 15:26:36)
- 8 (2009-06-22 (月) 12:28:26)
- 9 (2009-12-16 (水) 21:23:55)
- 10 (2010-11-15 (月) 15:06:41)
- 11 (2010-12-14 (火) 14:55:56)
- 12 (2013-01-19 (土) 20:19:44)
- 13 (2013-10-23 (水) 20:28:37)
- 14 (2014-11-01 (土) 00:46:09)
- 15 (2014-11-21 (金) 18:27:40)
- 16 (2014-11-22 (土) 03:59:58)
- 17 (2015-01-25 (日) 18:32:54)
- 18 (2016-04-24 (日) 21:08:11)
- 19 (2016-11-17 (木) 18:21:21)
- 20 (2017-04-19 (水) 20:30:08)
- 21 (2017-11-02 (木) 15:34:40)
- 22 (2018-02-24 (土) 19:51:30)
- 23 (2018-04-10 (火) 17:07:36)
- 24 (2018-12-14 (金) 19:51:34)
- 25 (2020-11-13 (金) 12:12:17)
- 26 (2022-08-20 (土) 22:15:25)
- 27 (2022-11-16 (水) 16:42:20)
- 追加された行はこの色です。
- 削除された行はこの色です。
TITLE:ImageIconの形でJButtonを作成 #navi(../) *ImageIconの形でJButtonを作成 [#lb2a57b5] Posted by [[terai]] at 2008-07-21 --- category: swing folder: RoundImageButton title: ImageIconの形でJButtonを作成 tags: [JButton, Shape, ImageIcon] author: aterai pubdate: 2008-07-21T16:27:56+09:00 description: 任意のShapeとその形に透過色を設定した画像を使ってJButtonを作成します。 image: https://lh6.googleusercontent.com/_9Z4BYR88imo/TQTSO4fquKI/AAAAAAAAAic/UdMAZSREN1U/s800/RoundImageButton.png hreflang: href: https://java-swing-tips.blogspot.com/2008/07/create-round-image-jbutton.html lang: en --- * 概要 [#summary] 任意の`Shape`とその形に透過色を設定した画像を使って`JButton`を作成します。 #contents #download(https://lh6.googleusercontent.com/_9Z4BYR88imo/TQTSO4fquKI/AAAAAAAAAic/UdMAZSREN1U/s800/RoundImageButton.png) **概要 [#h91eef1a] 任意のShapeとその形に透過色を設定した画像を使ってJButtonを作成します。 -&jnlp; -&jar; -&zip; #screenshot **サンプルコード [#ka72aa46] #code{{ * サンプルコード [#sourcecode] #code(link){{ class RoundButton extends JButton { protected Shape base; protected Shape shape public RoundButton() { this(null, null); } public RoundButton(Icon icon) { this(null, icon); } public RoundButton(String text) { this(text, null); } public RoundButton(Action a) { this(); setAction(a); } public RoundButton(String text, Icon icon) { setModel(new DefaultButtonModel()); init(text, icon); if(icon==null) { if (icon == null) { return; } int iw = Math.max(icon.getIconWidth(), icon.getIconHeight()); int sw = 1; setBorder(BorderFactory.createEmptyBorder(sw,sw,sw,sw)); Dimension dim = new Dimension(iw+sw+sw, iw+sw+sw); setPreferredSize(dim); setMaximumSize(dim); setMinimumSize(dim); setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); setBackground(Color.BLACK); setContentAreaFilled(false); setFocusPainted(false); //setVerticalAlignment(SwingConstants.TOP); // setVerticalAlignment(SwingConstants.TOP); setAlignmentY(Component.TOP_ALIGNMENT); initShape(); } protected Shape shape, base; protected void initShape() { if(!getBounds().equals(base)) { if (!getBounds().equals(base)) { Dimension s = getPreferredSize(); base = getBounds(); shape = new Ellipse2D.Float(0, 0, s.width-1, s.height-1); shape = new Ellipse2D.Float(0, 0, s.width - 1, s.height - 1); } } @Override protected void paintBorder(Graphics g) { @Override public Dimension getPreferredSize() { Icon icon = getIcon(); Insets i = getInsets(); int iw = Math.max(icon.getIconWidth(), icon.getIconHeight()); return new Dimension(iw + i.right + i.left, iw + i.top + i.bottom); } @Override protected void paintBorder(Graphics g) { initShape(); Graphics2D g2 = (Graphics2D)g; Graphics2D g2 = (Graphics2D) g.create(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setColor(getBackground()); //g2.setStroke(new BasicStroke(1.0f)); // g2.setStroke(new BasicStroke(1f)); g2.draw(shape); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); g2.dispose(); } @Override public boolean contains(int x, int y) { @Override public boolean contains(int x, int y) { initShape(); return shape.contains(x, y); // 以下、透過色が0でクリック不可にする場合の例 // or return super.contains(x, y) && ((image.getRGB(x, y) >> 24) & 0xff) > 0; } } }} **解説 [#x2ead355] 上記のサンプルでは、JButtonに円形の画像を貼り付けてボタンを作成しています。 - 円形、同サイズのPNG画像(円の外側が透過色)を三種類用意してJButtonに設定 -- setIcon -- setPressedIcon -- setRolloverIcon - setContentAreaFilled(false)などを設定して、ボタン自体の描画はしない - 推奨、最小、最大サイズを画像のサイズに合わせる -- ただし、縁の線を描画するため、画像サイズより上下左右1pt大きくなるようEmptyBorderを設定している - containsをオーバーライドして、円の外側をクリックしてもボタンが反応しないようにする -- 画像の透過色から、円を生成している訳ではなく、画像のサイズから円図形を別途作成している - paintBorderをオーバーライドして、元の縁は描画せずにその幅の線で独自に円を描画する -- containsで使用した図形を利用 * 解説 [#explanation] 上記のサンプルでは、`JButton`に円形の画像を貼り付けてボタンを作成しています。 ---- ボタンの揃えを変更するために、JPanelではなく、Boxを利用しているので、JDK 5 でも JDK 6 と同じように描画するために、Box#paintComponent を以下のようにオーバーライド(([[Bug ID: 4907674 Box disregards setBackground() even when set Opaque(true)>http://bugs.sun.com/view_bug.do?bug_id=4907674]]))しています。 #screenshot(,screenshot1.png) - 円形で同サイズの`PNG`画像(円の外側が透過色)を`3`種類用意し以下のメソッドで`JButton`に設定 -- `setIcon` -- `setPressedIcon` -- `setRolloverIcon` - `setContentAreaFilled(false)`などを設定してボタン自体の描画はしない - `JButton`の推奨、最小、最大サイズを画像のサイズに合わせる -- ただし、縁の線を描画するため、画像サイズより上下左右`1px`大きくなるよう`EmptyBorder`を設定 - `contains`をオーバーライドして円の外側をクリックしてもボタンが反応しないようにする -- このサンプルでは、画像の透過色から円を生成している訳ではなく画像のサイズから円図形を別途作成 -- 画像の透過色からクリック可能な領域を設定する場合は[[JComponentの形状定義を変更する>Swing/MoveNonRectangularImage]]を参照 - `paintBorder`をオーバーライドして元の縁は描画せずにその幅の線で独自に円を描画する -- `contains`で使用した図形を利用 ---- - %%ボタンの揃えを変更するために`JPanel`ではなく`Box`を利用しているので`JDK 5`でも`JDK 6`と同じように描画するために`Box#paintComponent`を以下のようにオーバーライド%% `JDK 6`で修正済み -- [https://bugs.openjdk.org/browse/JDK-4907674 JDK-4907674 Box disregards setBackground() even when set Opaque(true) - Java Bug System] -- &ref(https://lh3.googleusercontent.com/_9Z4BYR88imo/TQTSRb592NI/AAAAAAAAAig/4HrfRUSkPxc/s800/RoundImageButton1.png); #code{{ private final Box box = // JDK 6 Box.createHorizontalBox(); // JDK 5 new Box(BoxLayout.X_AXIS) { protected void paintComponent(Graphics g) { if(ui != null) { @Override protected void paintComponent(Graphics g) { if (ui != null) { super.paintComponent(g); }else if(isOpaque()) { } else if (isOpaque()) { g.setColor(getBackground()); g.fillRect(0, 0, getWidth(), getHeight()); } } }; }} ---- 以下のようなButtonUIを使って、JButtonをオーバーライドしない方法もあります。 #code{{ JButton button = new JButton(icon); button.setUI(new RoundImageButtonUI()); }} #code{{ class RoundImageButtonUI extends BasicButtonUI{ protected Shape shape, base; @Override protected void installDefaults(AbstractButton b) { super.installDefaults(b); Icon icon = b.getIcon(); if(icon==null) return; int iw = Math.max(icon.getIconWidth(), icon.getIconHeight()); int sw = 1; b.setBorder(BorderFactory.createEmptyBorder(sw,sw,sw,sw)); b.setContentAreaFilled(false); b.setFocusPainted(false); b.setOpaque(false); b.setBackground(Color.BLACK); Dimension dim = new Dimension(iw+sw+sw, iw+sw+sw); b.setPreferredSize(dim); b.setMaximumSize(dim); b.setMinimumSize(dim); //b.setVerticalAlignment(SwingConstants.TOP); b.setAlignmentY(Component.TOP_ALIGNMENT); initShape(b); } @Override protected void installListeners(AbstractButton b) { BasicButtonListener listener = new BasicButtonListener(b) { @Override public void mousePressed(MouseEvent e) { AbstractButton b = (AbstractButton) e.getSource(); initShape(b); if(shape.contains(e.getX(), e.getY())) { super.mousePressed(e); } } @Override public void mouseEntered(MouseEvent e) { if(shape.contains(e.getX(), e.getY())) { super.mouseEntered(e); } } @Override public void mouseMoved(MouseEvent e) { if(shape.contains(e.getX(), e.getY())) { super.mouseEntered(e); }else{ super.mouseExited(e); } } }; if(listener != null) { b.addMouseListener(listener); b.addMouseMotionListener(listener); b.addFocusListener(listener); b.addPropertyChangeListener(listener); b.addChangeListener(listener); } } @Override public void paint(Graphics g, JComponent c) { super.paint(g, c); Graphics2D g2 = (Graphics2D)g; initShape(c); //Border g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setColor(c.getBackground()); //g2.setStroke(new BasicStroke(1.0f)); g2.draw(shape); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); } private void initShape(JComponent c) { if(!c.getBounds().equals(base)) { Dimension s = c.getPreferredSize(); base = c.getBounds(); shape = new Ellipse2D.Float(0, 0, s.width-1, s.height-1); } } } }} **参考リンク [#bbf23178] - [[アクア風の球体の描き方(GIMPチュートリアル) > ロゴ・ボタン | GIMP思い込みチュートリアル(GIMPの使い方)>http://gimp.blog.shinobi.jp/Entry/18/]] - [[Bug ID: 4907674 Box disregards setBackground() even when set Opaque(true)>http://bugs.sun.com/view_bug.do?bug_id=4907674]] * 参考リンク [#reference] // - [http://gimp.blog.shinobi.jp/Entry/18/ アクア風の球体の描き方(GIMPチュートリアル) > ロゴ・ボタン | GIMP思い込みチュートリアル(GIMPの使い方)] - [[JButtonの形を変更>Swing/RoundButton]] - [[JComponentの形状定義を変更する>Swing/MoveNonRectangularImage]] **コメント [#kcfc5225] * コメント [#comment] #comment #comment