Swingを使用してアプリを開発しています。ユーザーがアプリを操作しているときに、ヘルプデータが画面の閉じたセクションで利用できるようになる場合があります。その場合は、そのセクションを指す小さな矢印を描画したいと思います。
これを行うために、JPanelを拡張し、アプリjframeのガラス板として追加しました。カスタムガラスペインクラスの名前はAlertGlassPaneです。
AlertGlassPaneはこれを行います:新しいヘルプデータが利用可能になるまで待機します。これが発生してヘルプセクションが閉じられると、画面上のヘルプセクションの位置が検出され、その横にアニメーションの矢印が描画されます。
矢印を描画するために、ガラスペインのメソッドpaintComponentを拡張しました。
矢印をアニメーション化するために、100ミリ秒ごとにループする小さなスレッドを作成し、ガラスペインで再ペイントを呼び出しました。
問題:Javaは私の描画を無視します...トリガーがアニメーションの開始をトリガーして静止した場合、何も起こりません。アプリに描画は表示されません。
ループが実行され、paintComponentが呼び出されていることはわかっていますが、カスタムペイントが有効になっていません。
しかし、矢印を表示する領域にマウスを移動すると、表示されます。しかし、マウスが動いているとき。停止するとマウスが移動し、アニメーションも停止し、マウスが停止する(または領域を離れる)前の最後の位置で矢印がフリーズします。
多くのことを試しましたが(たとえば、図面のクリップ領域を設定するなど)、何も機能しないようです。動作するのは、paintComponent内から誤って再ペイントを呼び出したときだけでした。
現時点では、ガラス板のギブム領域を再ペイントする必要があることをレンダリングシステムに伝達する方法を探しています(repaint(x、y、w、h)は機能しませんでした...)。たぶん、カスタムレンダリングをJLabelに移動してから、このラベルをガラス板に追加しますか?私はこのアプローチが好きではありません...
ここにスニペットを投稿する前に、コードをクリーンアップしてみます。それが役立つだろう?
前もって感謝します!
snnipet:
package br.com.r4j.test;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.image.BufferedImage;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.text.JTextComponent;
/**
*
* @author
*/
public class TestGlassPaneAnimation extends JPanel
{
private static TestGlassPaneAnimation gvp = new TestGlassPaneAnimation();
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
JFrame f = new JFrame("Anitest in glass");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//f.setResizable(false);
f.setLayout(new GridLayout(5, 3));
f.add(new JLabel("First Name :"));
f.add(new JTextField(20));
f.add(new JLabel("Last Name :"));
f.add(new JTextField(20));
f.add(new JLabel("Phone Number :"));
f.add(new JTextField(20));
f.add(new JLabel("Email:"));
f.add(new JTextField(20));
f.add(new JLabel("Address :"));
f.add(new JTextField(20));
JButton btnStart = new JButton("Click me, please!");
f.add(btnStart);
btnStart.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
gvp.startAnimation();
}
});
f.setGlassPane(gvp);
f.pack();
f.setVisible(true);
gvp.setVisible(true);
}
});
}
private BufferedImage icon;
private boolean animate = false;
private long timeStart = 0;
private Thread thrLastActive = null;
public TestGlassPaneAnimation()
{
setLayout(null);//this is the exception to the rule case a layoutmanager might make setting Jlabel co-ords harder
setOpaque(false);
Icon icon1 = UIManager.getIcon("OptionPane.warningIcon");
int imgW = icon1.getIconWidth();
int imgH = icon1.getIconHeight();
this.icon = ImageUtilities.getBufferedImageOfIcon(icon1, imgW, imgH);
this.animate = false;
}
public void startAnimation()
{
this.animate = true;
this.timeStart = (new Date()).getTime();
if (this.thrLastActive != null)
this.thrLastActive.interrupt();
this.thrLastActive = new Thread(new Runnable()
{
public void run()
{
try
{
while (true)
{
// int x = 250, y = 250;
// int width = 60, height = 60;
Thread.currentThread().sleep(100);
// frmRoot.invalidate();
// repaint(x, y, width, height);
repaint(new Rectangle(x, y, width, height));
// repaint(new Rectangle(10, 10, 2000, 2000));
// repaint();
// paintComponent(getGraphics());
}
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
this.thrLastActive.start();
}
protected void paintComponent(Graphics g)
{
try
{
// enables anti-aliasing
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
java.awt.Composite composite = g2.getComposite();
System.err.println("b1: " + g.getClipBounds());
if (this.animate)
{
long timeSpent = (new Date()).getTime() - timeStart;
int x = 10, y = 150;
int width = 60, height = 60;
float maxAlpha = 0.8f;
x += (-100*Math.sin(5*2*Math.PI*timeSpent/10000)+50)/15;
System.err.println("painting::x: " + x + ", y: " + y + ", sin: " + (Math.sin(6*2*Math.PI*timeSpent/10000)));
// g.setClip(x-10, y-10, width, height);
System.err.println("b2: " + g.getClipBounds());
AlphaComposite alpha2 = AlphaComposite.SrcOver.derive(maxAlpha);
g2.setComposite(alpha2);
g2.drawImage(this.icon, x, y, null);
g2.setComposite(composite);
g2.setComposite(composite);
}
}
catch (Throwable e)
{
System.err.println("Errr!");
e.printStackTrace();
}
}
}
class ImageUtilities {
public static BufferedImage resize(BufferedImage image, int width, int height) {
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TRANSLUCENT);
Graphics2D g2d = (Graphics2D) bi.createGraphics();
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(image, 0, 0, width, height, null);
g2d.dispose();
return bi;
}
public static BufferedImage getBufferedImageOfIcon(Icon icon, int imgW, int imgH) {
BufferedImage img = new BufferedImage(imgW, imgH, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = (Graphics2D) img.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
icon.paintIcon(null, g2d, 0, 0);
g2d.dispose();
return img;
}
}