Re-pintar em quadro / painel / componente translúcido.

Estou tentando criar uma janela translúcida com Java no OSX e adicionar um JLabel a ela.

Este JLabel muda seu texto a cada segundo ….

texto alternativo

No entanto, o componente não está repintando bem.

Como posso resolver este problema?

Eu encontrei esses artigos , mas não consigo descobrir como resolvê-los.

Se possível, cole o código fonte de correção, aqui está o meu:

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

    Eu tive alguma sorte em estender o JLabel e implementar o Icon para fazer um componente translúcido funcionar do jeito que eu quero. Você pode ver o resultado de várias combinações de regras neste AlphaCompositeDemo . O exemplo abaixo é 100% branco sobre 50% preto.

    Adendo: observe como este exemplo compõe texto opaco em um plano de fundo fora da canvas sobre o plano de fundo do quadro translúcido.

    Adenda: Aqui está uma maneira de tornar o quadro inteiro translúcido . Infelizmente, também escurece o conteúdo.

    imagem

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

    O problema também pode ter a ver com o fato de que você está definindo o texto do JLabel de um segmento que não é o segmento de expedição de events.

    Existem duas maneiras de resolver isso. Sem testar seu problema, eu o resolveria usando a class javax.swing.Timer , em vez da class java.util.Timer . javax.swing.Timer irá garantir que os events sejam triggersdos no encadeamento de despacho.

    Então (código não testado):

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

    A outra maneira de resolvê-lo é continuar usando java.util.Timer mas para garantir que você use EventQueue.invokeLater(Runnable) para garantir que as atualizações para o label ocorram no EDT.

    Não sei se o problema está resolvido, mas resolvi-o na minha aplicação com um “Frame.repaint ();”

    Assim, a cada segundo meu quadro será repintado e meu JLabel será atualizado com o tempo real.

     /* * 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()); } } }