2010-01-29 9 views
12

Estoy tratando de crear una ventana translúcida con Java en OSX y agregarle un JLabel.Vuelva a pintar en el marco/panel/componente translúcido.

Este JLabel cambia su texto cada segundo ....

alt text

Sin embargo, el componente no está bien repintado.

¿Cómo puedo resolver este problema?

He encontrado el thesearticles, pero no puedo encontrar la manera de solucionarlo.

Si es posible, por favor pegue el código fuente de fijación, aquí está la mía:

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


    } 
} 
+1

Intente restablecer el fondo en el código del temporizador también, o llame a repintado en todo el panel. Creo que el fondo simplemente no sabe que necesita ser repintado. – jjnguy

+0

Si eso lo soluciona, lo convertiré en una respuesta, pero es solo una suposición en este momento. – jjnguy

+3

+1 por incluir el logotipo SO. :-) – trashgod

Respuesta

14

Tuve un poco de suerte extendiendo JLabel e implementando Icon para obtener un componente translúcido que funcione como yo quiero. Puede ver el resultado de varias combinaciones de reglas en este AlphaCompositeDemo. El siguiente ejemplo es 100% blanco encima de 50% negro.

Adición: tenga en cuenta cómo este ejemplo compone texto opaco sobre un fondo claro fuera de pantalla sobre el fondo de marco translúcido.

Adición: Aquí hay una forma de hacer el whole frame translucent. Desafortunadamente, atenúa el contenido, también.

image

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

+1 para agregar la captura de pantalla. Parece prometedor. La única diferencia es que el texto no debe ser translúcido, sino opaco (como esta captura de pantalla en Windows), pero dado el estado actual de mi código, supongo que esta debería ser la solución para OSX. Voy a probarlo mañana cuando tenga mi Mac a mano nuevamente. Gracias. – OscarRyz

+0

Oh, no estás usando un JLabel sino pintando directamente en el panel ... mmhhhh Tengo que intentar eso. – OscarRyz

+0

Sí, en algún momento debe hacer un compuesto con el fondo del marco. Voy a actualizar para mostrar cómo hacer texto opaco. – trashgod

4

El problema también puede tener que ver con el hecho de que se está configurando el texto del JLabel 's de un hilo que no es el hilo de envío del evento.

Hay dos formas de solucionar esto. Sin probar su problema, lo resolvería utilizando la clase javax.swing.Timer, en lugar de la clase java.util.Timer. javax.swing.Timer asegurará que los eventos se disparen en el hilo de envío.

Así (código no probado):

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

La otra manera de resolverlo es seguir utilizando java.util.Timer pero para asegurarse de que utiliza EventQueue.invokeLater(Runnable) para garantizar que las actualizaciones de la etiqueta se llevan a cabo en la EDT.

+0

En caso de que no esté claro, si desactiva el EDT para desactivar el EDT, entonces obtendrá artefactos como los que está experimentando: los eventos de pintura, por ejemplo, podrían llegar a averiarse. jjnguy: una revalidación debería activarse automáticamente mediante el método JLabel setText(); la razón por la que un evento repaint() podría funcionar aquí es porque se programará en el EDT para su posterior ejecución. Es mejor asegurarse de que la llamada setText() inicial se realizó en el EDT en primer lugar. –

+0

He intentado cambiar el TimerTask a esto: timer.schedule (nueva TimerTask() {int i = 0; public void run() { SwingUtilities.invokeLater (nueva Ejecutable() { public void run() { label.setText ("Hola" + i ++); } }); } }, 0, 1000); Y no funcionó. Sun Bug: http://bugs.sun.com/view_bug.do?bug_id=4297006 indica que es posible que deba anular paintComponent() porque la opacidad y la translúcida no interactúan bien. – Kylar

+0

Yeap, en realidad intenté con 'SwingUtilities.invokeLater' que tiene el mismo efecto (envíe el mensaje en el EDT) con exactamente los mismos resultados. Lo elimino antes de publicarlo para que el código sea breve. – OscarRyz

2

No sé si el problema se resuelve, pero lo resolví en mi aplicación con un "Frame.repaint();"

De modo que cada segundo mi Marco se volverá a pintar y mi JLabel se actualizará con el tiempo real.

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

     } 

    } 



} 
+0

Debe evitar el código solo responde. – croxy

Cuestiones relacionadas