2010-01-29 7 views
12

Ich versuche, ein transparentes Fenster mit Java auf OSX zu erstellen und fügen Sie ein JLabel hinzu.Re-paint auf transluzenten Rahmen/Panel/Komponente.

Diese JLabel ändert seinen Text jede Sekunde ....

alt text

jedoch die Komponente nicht gut ist neu zu streichen.

Wie kann ich dieses Problem lösen?

Ich habe die thesearticles gefunden, aber ich kann nicht herausfinden, wie man es löst.

Wenn möglich, bitte auf den Befestigungs Quellcode einfügen, hier ist meins:

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

Versuchen Sie auch, den Hintergrund im Timer-Code zurückzusetzen oder Repaint auf dem gesamten Panel aufzurufen. Ich weiß, dass der Hintergrund einfach nicht weiß, dass es neu gestrichen werden muss. – jjnguy

+0

Wenn das behoben wird, werde ich eine Antwort geben, aber es ist nur eine Vermutung. – jjnguy

+3

+1 für das SO-Logo. :-) – trashgod

Antwort

14

Ich hatte ein wenig Glück, JLabel zu erweitern und Icon zu implementieren, um eine durchscheinende Komponente zu bekommen, die arbeitet, wie ich will. Sie können das Ergebnis verschiedener Regelkombinationen in diesem AlphaCompositeDemo sehen. Das folgende Beispiel ist 100% weiß auf 50% Schwarz.

Nachtrag: Beachten Sie, wie in diesem Beispiel undurchsichtiger Text auf einem freien Hintergrund außerhalb des Bildschirms über den Hintergrund des transluzenten Rahmens zusammengesetzt wird.

Nachtrag: Hier ist ein Weg, die whole frame translucent zu machen. Leider dimmt es auch den Inhalt.

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 zum Hinzufügen des Screenshots. Sieht vielversprechend aus. Der einzige Unterschied ist, dass der Text nicht durchsichtig sein sollte, aber undurchsichtig (wie dieser Screenshot in Windows), aber angesichts des aktuellen Status meines Codes, ich denke, das sollte die Umgehung für OSX sein. Ich werde es morgen versuchen, wenn ich meinen Mac wieder zur Hand habe. Vielen Dank. – OscarRyz

+0

Oh, Sie benutzen kein JLabel, sondern malen direkt auf dem Panel ... mmhhhh Ich muss das versuchen. – OscarRyz

+0

Ja, irgendwann müssen Sie eine Zusammensetzung mit dem Hintergrund des Rahmens machen. Ich werde aktualisieren, um zu zeigen, wie man undurchsichtigen Text macht. – trashgod

4

Das Problem kann auch mit der Tatsache zu tun, dass Sie die JLabel ‚s Text aus einem Thread sind Einstellung, die nicht der Event Dispatch Thread.

Es gibt zwei Möglichkeiten, dies zu lösen. Ohne Ihr Problem zu testen, würde ich es lösen, indem Sie die Klasse javax.swing.Timer anstelle der Klasse java.util.Timer verwenden. javax.swing.Timer wird sichergestellt, dass Ereignisse auf dem Versandthread ausgelöst werden.

So (ungetestet 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); 

Der andere Weg, es zu lösen ist es, weiterhin java.util.Timer zu verwenden, sondern um sicherzustellen, dass Sie EventQueue.invokeLater(Runnable) verwenden, um sicherzustellen, dass Updates auf das Etikett Platz auf dem EDT nehmen.

+0

Wenn es nicht klar ist, wenn Sie Swing-bezogene Sachen aus der EDT machen, dann erhalten Sie Artefakte, wie Sie sie erleben - Paint-Events, zum Beispiel, könnten außer Betrieb kommen. jjnguy: Eine Revalidierung sollte automatisch bereits durch die JLabel setText() Methode ausgelöst werden; Der Grund dafür, dass ein Ereignis repaint() hier funktionieren könnte, liegt darin, dass es für die spätere Ausführung auf dem EDT geplant wird. Es ist besser sicherzustellen, dass der erste Aufruf von setText() überhaupt auf dem EDT ausgeführt wurde. –

+0

ich versuchte, die Timertask zu diesem Schalt: timer.schedule (new Timertask() { int i = 0; public void run() { SwingUtilities.invokeLater (new Runnable() { public void run() { label.setText ("Hola" + i ++); } }); } }, 0, 1000); Und es hat nicht funktioniert. Sun Bug: http://bugs.sun.com/view_bug.do?bug_id=4297006 besagt, dass Sie möglicherweise paintComponent() überschreiben müssen, weil Opazität und Transparenz nicht gut interagieren. – Kylar

+0

Yeap, ich habe es eigentlich mit 'SwingUtilities.invokeLater' versucht, das den gleichen Effekt hat (sende die Nachricht im EDT) mit genau den gleichen Ergebnissen. Ich entferne es vor dem Posten, um den Code kurz zu machen. – OscarRyz

2

Ich weiß nicht, ob das Problem gelöst ist, aber ich löste es in meiner Anwendung mit einem "Frame.repaint();"

Also jede Sekunde wird mein Frame neu gezeichnet und mein JLabel wird mit der aktuellen Zeit aktualisiert.

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

Sie sollten Code nur Antworten vermeiden. – croxy