直接在玻璃板上绘图:不工作

时间:2013-02-15 14:08:47

标签: java swing glasspane

我正在使用Swing开发一个应用程序。当用户与应用程序进行交互时,帮助数据可能会在屏幕的关闭部分显示,并且我想在发生这种情况时绘制一个指向该部分的小箭头。

为此,我扩展了一个JPanel并将其添加为app jframe的glasspane。自定义玻璃窗格类的名称是AlertGlassPane。

AlertGlassPane执行此操作:等待新的帮助数据可用。当发生这种情况并关闭帮助部分时,它会在屏幕上找到帮助部分的位置,然后在其侧面绘制一个动画箭头。

为了绘制箭头,我扩展了玻璃窗格的方法paintComponent。

要为箭头设置动画,我创建了一个每100毫秒循环一次的小线程,在玻璃窗格上调用重绘。

问题:Java忽略了我的绘图......如果触发动画的开始并且静止不动,则没有任何反应。应用程序上没有显示绘图。

我知道循环正在运行并且正在调用paintComponent,但自定义绘制没有生效。

但是如果我将鼠标移动到应该渲染箭头的区域,那就确实如此!但就在鼠标移动的时候。如果停止移动鼠标,动画也会停止,箭头会在鼠标停止(或离开该区域)之前的最后位置冻结。

我尝试了很多东西(例如设置绘图的剪辑区域),但似乎没有任何效果。唯一有效的是当我在paintComponent中错误地重新调用时。

此刻我正在寻找一种方法来与渲染系统联系,我的玻璃板的一个区域需要重新绘制(重绘(x,y,w,h)不起作用......)。也许将自定义渲染移动到JLabel,然后将此标签添加到glasspane?我不喜欢这种方法......

我会尝试在发布代码段之前清理代码。会有帮助吗?

提前致谢!

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;
    }
}

1 个答案:

答案 0 :(得分:1)

嗯,不确定你所提供的片段到底是怎么回事,但是因为看起来它是从我的片段中拍摄的,我写了另一个例子(我必须在showWarningIcon(Component c)和{{更改1行或2行代码1}}方法,但没什么大的:

如果输入除 david 之外的任何内容并按下(点击我,请)点击它将显示:

enter image description here

refreshLocations()

如果您正在寻找更成熟的图书馆,请查看JXLayer - Validation OverlaysValidation overlays using glass pane

也可能需要阅读here,其中显示了验证文本字段数据(按钮按下除外)的多种方法,例如import java.awt.Component; import java.awt.Graphics2D; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; 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.image.BufferedImage; import java.util.HashMap; import java.util.Map; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.SwingUtilities; import javax.swing.UIManager; public class TestGlassPaneAnimation { private static GlassValidationPane gvp = new GlassValidationPane(); public static void main(String args[]) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { JFrame f = new JFrame("Anitest in glass"); f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); //f.setResizable(false); f.setLayout(new GridBagLayout()); GridBagConstraints gc = new GridBagConstraints(); gc.fill = GridBagConstraints.HORIZONTAL; gc.weightx = 1; gc.weighty = 1; gc.insets = new Insets(15, 15, 15, 15);//give some space so icon doesnt cover components when shown gc.gridx = 0; gc.gridy = 0; f.add(new JLabel("First Name:"), gc); final JTextField jtf = new JTextField(20); gc.gridx = 1; f.add(jtf, gc); gc.gridx = 0; gc.gridy = 1; f.add(new JLabel("Surname:"), gc); final JTextField jtf2 = new JTextField(20); gc.gridx = 1; f.add(jtf2, gc); JButton btnStart = new JButton("Click me, please!"); gc.gridx = 2; f.add(btnStart, gc); btnStart.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (!jtf.getText().equalsIgnoreCase("david")) { gvp.showWarningIcon(jtf); } } }); f.addComponentListener(new ComponentAdapter() {//so wjen frame is resized icons follow @Override public void componentResized(ComponentEvent ce) { super.componentResized(ce); gvp.refreshLocations(); } }); f.setGlassPane(gvp); f.pack(); f.setVisible(true); gvp.setVisible(true); } }); } } class GlassValidationPane extends JPanel { private HashMap<Component, JLabel> warningLabels = new HashMap<>(); private ImageIcon warningIcon; public GlassValidationPane() { setLayout(null);//this is the exception to the rule case a layoutmanager might make setting Jlabel co-ords harder setOpaque(false); Icon icon = UIManager.getIcon("OptionPane.warningIcon"); int imgW = icon.getIconWidth(); int imgH = icon.getIconHeight(); BufferedImage img = ImageUtilities.getBufferedImageOfIcon(icon, imgW, imgH); warningIcon = new ImageIcon(ImageUtilities.resize(img, 24, 24)); } void showWarningIcon(Component c) { if (warningLabels.containsKey(c)) { return; } JLabel label = new JLabel(); label.setIcon(warningIcon); //int x=c.getX();//this will make it insode the component int x = c.getX() - warningIcon.getIconWidth();//this makes it appear outside/next to component if space int y = c.getY(); label.setBounds(x, y, warningIcon.getIconWidth(), warningIcon.getIconHeight()); add(label); revalidate(); repaint(); warningLabels.put(c, label); } public void removeWarningIcon(Component c) { for (Map.Entry<Component, JLabel> entry : warningLabels.entrySet()) { Component component = entry.getKey(); JLabel jLabel = entry.getValue(); if (component == c) { remove(jLabel); revalidate(); repaint(); break; } } warningLabels.remove(c); } public void refreshLocations() { for (Map.Entry<Component, JLabel> entry : warningLabels.entrySet()) { Component c = entry.getKey(); JLabel label = entry.getValue(); //int x=c.getX();//this will make it insode the component int x = c.getX() - label.getIcon().getIconWidth();//this makes it appear outside/next to component int y = c.getY(); label.setBounds(x, y, label.getIcon().getIconWidth(), label.getIcon().getIconHeight()); revalidate(); repaint(); } } } 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; } } DocumentFilter等。