简体   繁体   English

在半透明框架/面板/组件上重新涂漆。

[英]Re-paint on translucent frame/panel/component.

I'm trying to create a translucent window with Java on OSX and add a JLabel to it. 我正在尝试在OSX上创建一个带有Java的半透明窗口并向其添加JLabel

This JLabel changes its text every second.... 这个JLabel每秒都会更改它的文本....

替代文字

However the component is not repainting well. 然而,该组件不能很好地重新粉刷。

How can I solve this problem? 我怎么解决这个问题?

I've found the these articles , but I can't figure out how to solve it. 我找到了这些 文章 ,但我无法弄清楚如何解决它。

If possible, please paste the fixing source code, here's mine: 如果可能的话,请粘贴修复源代码,这是我的:

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.Color;
import java.awt.Font;
import java.util.Timer;
import java.util.TimerTask;

public class Translucent {
    public static void main( String [] args ) {

        JFrame frame = new JFrame();

        frame.setBackground( new Color( 0.0f,0.0f,0.0f,0.3f));

        final JLabel label =  new JLabel("Hola");
        label.setFont( new Font( label.getFont().getFamily(), Font.PLAIN, 46 ) );
        label.setForeground( Color.white );

        frame.add( label );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible( true );

        Timer timer = new Timer();
        timer.schedule( new TimerTask(){
            int i = 0;
            public void run() {
                label.setText("Hola "+ i++ );
            }
        }, 0, 1000 );


    }   
}

I've had some luck extending JLabel and implementing Icon to get a translucent component working the way I want. 我有幸运行JLabel并实现Icon ,以便按照我想要的方式运行半透明组件。 You can see the result of various rule combinations in this AlphaCompositeDemo . 您可以在此AlphaCompositeDemo中查看各种规则组合的结果。 The example below is 100% white atop 50% black. 以下示例为50%黑色的100%白色。

Addendum: Note how this example composites opaque text on a clear offscreen background over the translucent frame background. 附录:请注意此示例如何在半透明框架背景上的透明屏幕外背景上合成不透明文本。

Addendum: Here's a way to make the whole frame translucent . 附录:这是一种使整个框架半透明的方法 Unfortunately, it dims the content, too. 不幸的是,它也使内容变暗。

图片

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Translucent extends JPanel implements ActionListener {

    private static final int W = 300;
    private static final int H = 100;
    private static final Font font =
        new Font("Serif", Font.PLAIN, 48);
    private static final SimpleDateFormat df =
        new SimpleDateFormat("HH:mm:ss");
    private final Date now = new Date();
    private final Timer timer = new Timer(1000, this);
    private BufferedImage time;
    private Graphics2D timeG;

    public Translucent() {
        super(true);
        this.setPreferredSize(new Dimension(W, H));
        timer.start();
    }

    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        int w = this.getWidth();
        int h = this.getHeight();
        g2d.setComposite(AlphaComposite.Clear);
        g2d.fillRect(0, 0, w, h);
        g2d.setComposite(AlphaComposite.Src);
        g2d.setPaint(g2d.getBackground());
        g2d.fillRect(0, 0, w, h);
        renderTime(g2d);
        int w2 = time.getWidth() / 2;
        int h2 = time.getHeight() / 2;
        g2d.setComposite(AlphaComposite.SrcOver);
        g2d.drawImage(time, w / 2 - w2, h / 2 - h2, null);
    }

    private void renderTime(Graphics2D g2d) {
        g2d.setFont(font);
        String s = df.format(now);
        FontMetrics fm = g2d.getFontMetrics();
        int w = fm.stringWidth(s);
        int h = fm.getHeight();
        if (time == null && timeG == null) {
            time = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            timeG = time.createGraphics();
            timeG.setRenderingHint(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
            timeG.setFont(font);
        }
        timeG.setComposite(AlphaComposite.Clear);
        timeG.fillRect(0, 0, w, h);
        timeG.setComposite(AlphaComposite.Src);
        timeG.setPaint(Color.green);
        timeG.drawString(s, 0, fm.getAscent());
    }

    private static void create() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setBackground(new Color(0f, 0f, 0f, 0.3f));
        f.setUndecorated(true);
        f.add(new Translucent());
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        now.setTime(System.currentTimeMillis());
        this.repaint();
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                create();
            }
        });
    }
}

The problem may also have to do with the fact that you're setting the JLabel 's text from a thread that is not the Event Dispatch Thread. 问题可能还与您从不是事件调度线程的线程设置JLabel的文本这一事实有关。

There are two ways to solve this. 有两种方法可以解决这个问题。 Without testing your problem, I'd solve it by using the javax.swing.Timer class, instead of the java.util.Timer class. 在没有测试你的问题的情况下,我将使用javax.swing.Timer类而不是java.util.Timer类来解决它。 javax.swing.Timer will ensure that events are fired on the dispatch thread. javax.swing.Timer将确保在调度线程上触发事件。

So (untested code): 所以(未经测试的代码):

final ActionListener labelUpdater = new ActionListener() {
  private int i;
  @Override
  public final void actionPerformed(final ActionEvent event) {
    label.setText("Hola " + this.i++);
  }
};
final javax.swing.Timer timer = new javax.swing.Timer(1000L, labelUpdater);

The other way to solve it is to continue to use java.util.Timer but to make sure that you use EventQueue.invokeLater(Runnable) to ensure that updates to the label take place on the EDT. 另一种解决方法是继续使用java.util.Timer但要确保使用EventQueue.invokeLater(Runnable)以确保在EDT上对标签进行更新。

I don't know if the problem is solved, but I solved it in my application with a "Frame.repaint();" 我不知道问题是否已经解决,但我在我的应用程序中用“Frame.repaint();”解决了它。

So every second my Frame will be repainted and my JLabel will be updatet with the actual time. 所以每一秒我的画面都会被重新粉刷,而我的JLabel将会根据实际时间进行更新。

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package mreg;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

/**
 *
 * @author Manoj
 */
public class TranscluentWindow {

 public static void main(String[] args) {
        new TranscluentWindow();
    }

    public TranscluentWindow() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (Exception ex) {
                    }

                    JWindow frame = new JWindow();
                    frame.setAlwaysOnTop(true);
                    frame.addMouseListener(new MouseAdapter() {



                    });
                    frame.setBackground(new Color(0,0,0,0));
                    frame.setContentPane(new TranslucentPane());
                    frame.add(new JLabel(new ImageIcon(ImageIO.read(getClass().getResource("/124742-high-school-collection/png/image_4.png")))));
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);

                       new Thread(new Runnable() {
            public void run() {

                    try {

                        Thread.sleep(2500);
                    } catch (InterruptedException ex) {
                    }

                frame.dispose();
                new loging().setVisible(true);
            }
        }).start();






                } catch (IOException ex) {
                    ex.printStackTrace();
                }

            }
        });
    }

    public class TranslucentPane extends JPanel {

        public TranslucentPane() {
            setOpaque(false);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g); 

            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setComposite(AlphaComposite.SrcOver.derive(0.0f));
            g2d.setColor(getBackground());
            g2d.fillRect(0, 0, getWidth(), getHeight());

        }

    }   



}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM