2010-01-29 4 views
12

Sto provando a creare una finestra traslucida con Java su OSX e aggiungere un JLabel ad esso.Rifinitura su telaio/pannello traslucido/componente.

Questo JLabel cambia il testo ogni secondo ....

alt text

Tuttavia il componente non è riverniciatura bene.

Come posso risolvere questo problema?

Ho trovato il thesearticles, ma non riesco a capire come risolverlo.

Se possibile, si prega di incollare il codice sorgente di fissaggio, ecco la mia:

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

Provare a reimpostare lo sfondo anche nel codice del timer o richiamare il ridisegno sull'intero pannello. Per me lo sfondo non sa che deve essere ridipinto. – jjnguy

+0

Se lo risolve, farò una risposta, ma è solo una supposizione in questo momento. – jjnguy

+3

+1 per includere il logo SO. :-) – trashgod

risposta

14

Ho avuto un po 'di fortuna nell'estendere JLabel e nell'implementazione di Icon per far funzionare un componente traslucido nel modo che preferisco. Puoi vedere il risultato di varie combinazioni di regole in questo AlphaCompositeDemo. L'esempio sotto è 100% bianco in cima al 50% nero.

Addendum: notare come questo esempio componga testo opaco su uno sfondo fuori schermo chiaro sullo sfondo del fotogramma traslucido.

Addendum: ecco un modo per rendere whole frame translucent. Sfortunatamente, attenua anche il contenuto.

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 per aggiungere lo screenshot. Sembra promettente. L'unica differenza è che il testo non dovrebbe essere traslucido, ma opaco (come questo screenshot in Windows) ma dato lo stato attuale del mio codice, immagino che questo dovrebbe essere un modo per aggirare OSX. Domani ci proverò quando avrò di nuovo a portata di mano il mio Mac. Grazie. – OscarRyz

+0

Oh, non stai usando una JLabel ma dipingi direttamente sul pannello ... mmhhhh Devo provarlo. – OscarRyz

+0

Sì, ad un certo punto devi fare un composito con lo sfondo del riquadro. Aggiornerò per mostrare come fare testo opaco. – trashgod

4

Il problema può anche avere a che fare con il fatto che si sta impostando il testo s il JLabel' da un filo che non è il thread di invio degli eventi.

Ci sono due modi per risolvere questo. Senza testare il tuo problema, lo risolverei usando la classe javax.swing.Timer, invece della classe java.util.Timer. javax.swing.Timer assicurerà che gli eventi vengano generati sul thread di invio.

Così (codice non testato):

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

L'altro modo per risolverlo è quello di continuare ad utilizzare java.util.Timer, ma per essere sicuri di utilizzare EventQueue.invokeLater(Runnable) per garantire che gli aggiornamenti l'etichetta si svolgono sul EDT.

+0

Nel caso in cui non sia chiaro, se fai cose relative a Swing su EDT, ottieni artefatti come quello che stai vivendo: gli eventi di disegno, ad esempio, potrebbero arrivare fuori ordine. jjnguy: una riconvalida dovrebbe essere automaticamente attivata già dal metodo jLabel setText(); il motivo per cui un evento repaint() potrebbe funzionare qui è perché verrà programmato sull'EDT per l'esecuzione successiva. È meglio assicurarsi che la chiamata iniziale di setText() sia stata effettuata sull'EDT in primo luogo. –

+0

Ho provato commutare il TimerTask a questo: timer.schedule (nuovo TimerTask() { int i = 0; public void run() { SwingUtilities.invokeLater (nuovo Runnable() { public void run() { label.setText ("Hola" + i ++); } }); } }, 0, 1000); E non ha funzionato. Sun Bug: http://bugs.sun.com/view_bug.do?bug_id=4297006 afferma che potrebbe essere necessario sovrascrivere paintComponent() perché opacità e traslucido non interagiscono bene. – Kylar

+0

Yeap, ho provato effettivamente con 'SwingUtilities.invokeLater' che ha lo stesso effetto (invia il messaggio nell'EDT) con esattamente gli stessi risultati. Lo rimuovo prima di postare per rendere il codice breve. – OscarRyz

2

Non so se il problema è risolto, ma ho risolto nella mia domanda con un "Frame.repaint();"

Così ogni secondo il mio telaio sarà ridipinto e il mio JLabel sarà aggiornato con il tempo reale.

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

Si dovrebbe evitare solo le risposte al codice. – croxy