• ベストアンサー

試験管のような画像をグラデーション

こんにちは。 試験管のように細長い楕円形(上下対称)で、設定した値に応じて試験管の中のバーが上下に伸び縮みするようなことを実現したいと考えています。 そして、そのバーにグラデーションを掛けたいと思っています。 このようなことを実現できるオープンソースのソフトウェアはありますでしょうか。 あるいは、標準的なライブラリを用いて自分で作成できる方法があればそれでも良いのですが。 よろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • _ranco_
  • ベストアンサー率58% (126/214)
回答No.2

以下は大急ぎで書いたもので、細部的にはアラがありますが、やり方の基本は学べると思います。このプログラムでは、外枠(”注射器")にBufferedImageを使っていますが、実際は外枠もグラデーションも、どちらも単なるShapeにしてpaintComponent()の中でdrawやfillできます。そのほうが、考え方としてはシンプルです。BufferedImageを使ったのは、透明属性(AlphaComposite)を、下のグラデーションを見せるために便利に使えると思ったからです。2つのShapeを作ったほうが、楽だったかな…。 -------------------------------------------------- import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.awt.image.*; public class Tube extends JPanel{  int panelWidth, panelHeight;  GeneralPath tube, bar;  BufferedImage tubeImg;  GradientPaint gp;  Arc2D topArc, bottomArc,   leftTopBarc, rightTopBarc; // parts of topArc  Line2D tleft, tright, bleft, bright;  float bodyWidth, bodyLength, bodyFullLength, barWidth, barLength,   domeHeight, barTopY;  Point2D.Float bodyLtop, bodyRtop, bodyLbottom, bodyRbottom,   barBottomLeft, barBottomRight, barCielLeft, barCielRight;  float wrate, hrate;     public Tube(int width, int height){   panelWidth = width;   panelHeight = height;   setPreferredSize(new Dimension(width, height));   setBackground(new Color(240, 240, 240));   wrate = 2f / 5f; // tube width ratio against panel width   hrate = 2f / 4f; // tube height ratio against panel height   bodyWidth = barWidth = (int)(panelWidth * wrate);   domeHeight = bodyWidth / 2;   bodyLength = panelHeight * hrate;   bodyFullLength = bodyLength + bodyWidth; // bw == domeHeight * 2   barLength = bodyFullLength * 0.85f;   bodyLtop = new Point2D.Float    (((1 - wrate) / 2) * panelWidth, ((1 - hrate) / 2) * panelHeight);   bodyLbottom = new Point2D.Float(bodyLtop.x, bodyLtop.y + bodyLength);   bodyRtop = new Point2D.Float(bodyLtop.x + bodyWidth, bodyLtop.y);   bodyRbottom = new Point2D.Float(bodyRtop.x, bodyLbottom.y);   barTopY = (bodyLtop.y - domeHeight) + (bodyFullLength - barLength);   barCielLeft = new Point2D.Float(bodyLtop.x, barTopY);   barCielRight = new Point2D.Float(bodyRtop.x, barTopY);   barBottomLeft    = new Point2D.Float(bodyLbottom.x, bodyLbottom.y + domeHeight);   barBottomRight    = new Point2D.Float(bodyRbottom.x, bodyLbottom.y + domeHeight);   tube = makeTube(bodyLtop, bodyLbottom, bodyRbottom, bodyRtop, bodyWidth);   tubeImg = makeTubeImg(tube);      bar = makeBar(barBottomLeft, barBottomRight, barCielRight, barCielLeft);  }  GeneralPath makeTube(Point2D.Float tl, Point2D.Float bl, Point2D.Float br,   Point2D.Float tr, float width){   GeneralPath gp = new GeneralPath();   gp.append(new Line2D.Float(tl, bl), true);   gp.append(new Arc2D.Float    (new Rectangle2D.Float(bl.x, bl.y - width / 2, width, width),    180, 180, Arc2D.OPEN), true);   gp.append(new Line2D.Float(tr, br), true);   gp.append(new Arc2D.Float    (new Rectangle2D.Float(tl.x, tl.y - width / 2, width, width),    0, 180, Arc2D.OPEN), true);   return gp;  }  GeneralPath makeBar   (Point2D.Float bl, Point2D.Float br, Point2D.Float tr, Point2D.Float tl){   GeneralPath gp = new GeneralPath();   gp.append(new Line2D.Float(bl, br), true);   gp.append(new Line2D.Float(br, tr), true);   gp.append(new Line2D.Float(tr, tl), true);   gp.append(new Line2D.Float(tl, bl), true);   return gp;  }  BufferedImage makeTubeImg(GeneralPath closedShape){   BufferedImage bim    = new BufferedImage(panelWidth, panelHeight, BufferedImage.TYPE_INT_ARGB);   Graphics2D g2d = bim.createGraphics();   g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,    RenderingHints.VALUE_ANTIALIAS_ON);   g2d.setColor(Color.white);   g2d.fillRect(0, 0, panelWidth, panelHeight);   g2d.setColor(Color.black);   g2d.setStroke(new BasicStroke(2.0f));   g2d.draw(closedShape);   g2d.setComposite(AlphaComposite.Clear);   g2d.fill(closedShape);   g2d.dispose();   return bim;  }  public void paintComponent(Graphics g){   super.paintComponent(g);   Graphics2D g2 = (Graphics2D)g;   g2.setPaint(new GradientPaint     (barCielLeft, Color.yellow, bodyLbottom, Color.pink, true));   g2.fill(bar);   g2.drawImage(tubeImg, 0, 0, this);  }  /* test program */  static Tube t;  static JButton up, dw;  public static void main(String[] args){   JFrame frame = new JFrame();   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);   Container con = frame.getContentPane();   t = new Tube(400, 400);   con.add(t, BorderLayout.CENTER);   up = new JButton("<html>U<br>P<br></html>");   dw = new JButton("<html>D<br>O<br>W<br>N<br></html>");   up.setPreferredSize(new Dimension(40, 100));   dw.setPreferredSize(new Dimension(40, 100));   UpDown ud = new UpDown();   up.addActionListener(ud);   dw.addActionListener(ud);   JPanel p = new JPanel(new GridLayout(2, 1));   p.add(up);   p.add(dw);   con.add(p, BorderLayout.WEST);   frame.pack();   frame.setVisible(true);  }  static class UpDown implements ActionListener{      public void actionPerformed(ActionEvent e){    float inc;    JButton bt = (JButton)e.getSource();    if (bt == up){     inc = -5;    }    else{     inc = 5;    }    // 以下、本当は増値/減値に際して値チェックが必要です    t.barCielRight     = new Point2D.Float(t.barCielRight.x, t.barCielRight.y + inc);    t.barCielLeft     = new Point2D.Float(t.barCielLeft.x, t.barCielLeft.y + inc);    t.bar = t.makeBar     (t.barBottomLeft, t.barBottomRight, t.barCielRight, t.barCielLeft);    t.repaint();   }  } } --------------------------------------------------

oubokun
質問者

お礼

ここまで作成して頂き、本当にありがとうございます。 実行してみたら、やりたかったことが全て実現されていました。 透明属性も付けたかったので、BufferedImageを使う方法も教えて頂けて良かったです。

すると、全ての回答が全文表示されます。

その他の回答 (1)

  • _ranco_
  • ベストアンサー率58% (126/214)
回答No.1

> 標準的なライブラリを用いて自分で作成できる方法 それは簡単ですが、小さなプログラミングを2~3経験して、以下の二つの技法に慣れる必要があります。 (1)直線や曲線を使って図形(java.awt.Shape -> java.awt.geom.GeneralPath <- java.awt.geom.Path2D)を定義し、図形をランタイムに変える方法。 (2)java.awt.GradientPaint(2色のグラデーション)やMultipleGradientPaint (多色のグラデーション)の作り方と使い方。 実現は、コンポーネントのpaintComponent()の中で、Graphics2Dのfill(Shape)を呼ぶだけなので、非常に簡単です。当面の課題は、Shapeの定義の仕方とグラデーションの作り方に慣れることです。

oubokun
質問者

お礼

ご回答ありがとうございました。 自前でもそれほどは苦労せずにできそうですね。 勉強してみます。

すると、全ての回答が全文表示されます。

関連するQ&A