2010-01-29 25 views
12

Próbuję utworzyć półprzezroczyste okno z Javą na OSX i dodać do niego JLabel.Ponownie malować na półprzezroczystej ramie/panelu/komponencie.

Ten JLabel zmienia swój tekst co drugi ....

alt text

Jednak składnik nie jest malowanie dobrze.

Jak mogę rozwiązać ten problem?

Znalazłem thesearticles, ale nie mogę wymyślić, jak go rozwiązać.

Jeśli to możliwe, należy wkleić kod źródłowy mocowanie, oto moje:

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

Spróbuj również zresetować tło w kodzie timera lub wywołać odświeżenie na całym panelu. Wiem, że tło nie wie, że musi zostać przemalowane. – jjnguy

+0

Jeśli to naprawi, zrobię to jako odpowiedź, ale teraz to tylko przypuszczenie. – jjnguy

+3

+1 za dołączenie logo SO. :-) – trashgod

Odpowiedz

14

Miałem trochę szczęścia przedłużając JLabel i wykonując Icon, aby uzyskać półprzezroczysty składnik działa tak, jak chcę. Możesz zobaczyć wyniki różnych kombinacji reguł w tym AlphaCompositeDemo. Poniższy przykład to 100% bieli na 50% czerni.

Dodatek: Zwróć uwagę, jak w tym przykładzie kompozyty są nieprzezroczystym tekstem na przezroczystym tle poza ekranem nad przezroczystym tłem ramki.

Dodatek: Oto sposób wykonania whole frame translucent. Niestety przyciemnia też treść.

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 za dodanie zrzutu ekranu. Wygląda obiecująco. Jedyna różnica polega na tym, że tekst nie powinien być przezroczysty, ale nieprzejrzysty (jak ten zrzut ekranu w oknach), ale biorąc pod uwagę obecny stan mojego kodu, myślę, że powinno to być obejściem dla OSX. Spróbuję jutro, kiedy znów będę mieć pod ręką mojego Macintosha. Dziękuję Ci. – OscarRyz

+0

Och, nie używasz JLabel, lecz malujesz bezpośrednio na panelu ... mmhhhh Muszę to wypróbować. – OscarRyz

+0

Tak, w pewnym momencie musisz zrobić kompozyt z tłem ramki. Zaktualizuję, aby pokazać, jak zrobić nieprzezroczysty tekst. – trashgod

4

Problem może też mieć do czynienia z faktem, że jesteś zachodzącego tekst JLabel dydaktycznego z wątku, który nie jest wątek wywołania zdarzenia.

Istnieją dwa sposoby rozwiązania tego problemu. Bez testowania twojego problemu rozwiązałbym go, używając klasy javax.swing.Timer, zamiast klasy java.util.Timer. javax.swing.Timer zapewnia, że ​​zdarzenia są uruchamiane w wątku wysyłki.

Tak (kod niesprawdzone):

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

Innym sposobem rozwiązania jest to, aby nadal korzystać java.util.Timer ale aby upewnić się, że używasz EventQueue.invokeLater(Runnable) aby upewnić się, że aktualizacje do etykiety odbędzie się EDT.

+0

W przypadku, gdy nie jest jasne, czy robisz rzeczy związane z Huśtawka WYŁ z EDT, otrzymujesz artefakty, których doświadczasz - na przykład zdarzają się przypadki malowania. jjnguy: rewalidacja powinna być automatycznie wyzwalana już przez metodę setText() JLabela; powodem, dla którego może tu zajść funkcja repaint(), jest to, że zostanie zaplanowane w EDT w celu późniejszego wykonania. Lepiej upewnić się, że początkowe wywołanie setText() zostało wykonane na EDT w pierwszej kolejności. –

+0

Próbowałem przełączania TimerTask do tego: timer.schedule (nowa TimerTask() { int i = 0; public void run () { SwingUtilities.invokeLater (nowa Runnable() {public void run () { label.setText ("Hola" + i ++); } }); } }, 0, 1000); I to nie zadziałało. Sun Bug: http://bugs.sun.com/view_bug.do?bug_id=4297006 stwierdza, że ​​możesz przesłonić paintComponent(), ponieważ nieprzezroczystość i półprzezroczystość nie współdziałają dobrze. – Kylar

+0

Yeap, próbowałem faktycznie z 'SwingUtilities.invokeLater', który ma ten sam efekt (wyślij wiadomość w EDT) z dokładnie takimi samymi wynikami. Usuwam go przed wysłaniem, aby skrócić kod. – OscarRyz

2

Nie wiem, czy problem został rozwiązany, ale rozwiązać go w mojej aplikacji z "Frame.repaint();"

Co sekundę moja ramka zostanie przemalowana, a mój JLabel będzie aktualizowany o aktualny czas.

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

Powinieneś unikać odpowiedzi tylko na kod. – croxy

Powiązane problemy