2017-02-13 1 views
0

J'ai créé JFrame, définissez une couleur transparente (new Color (0, 0, 0, 0)) en arrière-plan et placez-y JPanel. J'ai surchargé la méthode paintComponent de JPanel et dessine une image avec un canal alpha dessus. Aussi, je montre le menu contextuel lorsque l'utilisateur clique droit sur mon JPanel.Problèmes avec JFrame transparent

Et j'ai été confronté au fait que l'image du menu pop-up reste sur le JFrame après qu'il devrait disparaître (juste maintenant l'image d'un JPanel le couvre). Si je comprends bien, JFrame n'est pas effacé avant de dessiner un nouveau cadre.

Exemple

public class MainWindow extends JFrame { 

    private MyPanel widget = new MyPanel(); 
    private Action quitAction = new AbstractAction("Quit") { 
     @Override 
     public void actionPerformed(ActionEvent actionEvent) { 
      setVisible(false); 
      dispose(); 
     } 
    }; 

    private MainWindow() { 
     super(); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setUndecorated(true); 
     setBackground(new Color(0, 0, 0, 0)); 
     widget.loadImage("image.png"); 
     setContentPane(widget); 
     pack(); 
     setAlwaysOnTop(true); 
    } 

    public static void main(String[] args) { 
     javax.swing.SwingUtilities.invokeLater(() -> { 
      MainWindow window = new MainWindow(); 
      window.setVisible(true); 
     }); 
    } 

    class MyPanel extends JPanel implements MouseListener { 
     BufferedImage image; 

     MyPanel() { 
      super(); 
      addMouseListener(this); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintCompontent(g); 
      if (characterImage != null) { 
       g.drawImage(characterImage, 0, 0, this); 
      } 
     } 

     @Override 
     public void mouseClicked(MouseEvent e) { 
     } 

     @Override 
     public void mousePressed(MouseEvent e) { 
      clickPos = e.getLocationOnScreen(); 
      if (SwingUtilities.isRightMouseButton(e)) { 
       JPopupMenu popupMenu = new JPopupMenu(); 
       popupMenu.add(quitAction); 
       popupMenu.show(this, e.getX(), e.getY()); 
      } 
     } 

     @Override 
     public void mouseReleased(MouseEvent e) { 
     } 

     @Override 
     public void mouseEntered(MouseEvent e) { 
     } 

     @Override 
     public void mouseExited(MouseEvent e) { 
     } 

     boolean loadImage(String name) { 
      BufferedImage backupImage = image; 
      try { 
       image = ImageIO.read(MainWindow.class.getResourceAsStream("/images/" + name)); 
       setPreferredSize(new Dimension(image.getWidth(), image.getHeight())); 
      } catch (IOException ex) { 
       image = backupImage; 
       return false; 
      } 
      return true; 
     } 

    } 

} 
+0

Vous avez également oublié de fournir un [exemple exécutable] (https://stackoverflow.com/help/mcve) qui illustre votre problème. Ce n'est pas un vidage de code, mais un exemple de ce que vous faites qui met en évidence le problème que vous rencontrez. Cela entraînera moins de confusion et de meilleures réponses – MadProgrammer

+0

Je "devine" que soit vous n'appelez pas 'super.paintComponent' et/ou vous utilisez une couleur alpha pour définir l'arrière-plan du panneau – MadProgrammer

+0

*" Si je comprends bien, JFrame n'est pas effacé avant de dessiner un nouveau cadre. "* - Seulement si vous honorez la chaîne de peinture et assurez-vous que lorsque vous substituez des méthodes de peinture, vous appelez leurs super méthodes (et vous n'essayez pas d'appliquer une couleur alpha à un panneau opaque) – MadProgrammer

Répondre

1

Ainsi, vaguement basé sur votre code, une fois que je l'ai corrigé à travailler, je ne semble pas avoir de problèmes

Transparent Popup Menu

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.awt.image.BufferedImage; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import javax.swing.AbstractAction; 
import javax.swing.Action; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JPopupMenu; 
import javax.swing.SwingUtilities; 

public class MainWindow extends JFrame { 

    private MyPanel widget = new MyPanel(); 
    private Action quitAction = new AbstractAction("Quit") { 
     @Override 
     public void actionPerformed(ActionEvent actionEvent) { 
      setVisible(false); 
      dispose(); 
     } 
    }; 

    private MainWindow() { 
     super(); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setUndecorated(true); 
     setBackground(new Color(0, 0, 0, 0)); 
     widget.loadImage("MT.png"); 
     setContentPane(widget); 
     pack(); 
     setLocationRelativeTo(null); 
     setAlwaysOnTop(true); 
    } 

    public static void main(String[] args) { 
     javax.swing.SwingUtilities.invokeLater(() -> { 
      MainWindow window = new MainWindow(); 
      window.setVisible(true); 
     }); 
    } 

    class MyPanel extends JPanel implements MouseListener { 

     BufferedImage image; 

     MyPanel() { 
      super(); 
      addMouseListener(this); 
      setOpaque(false); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      g.setColor(Color.RED); 
      g.drawRect(0, 0, getWidth() - 1, getHeight() - 1); 
      if (image != null) { 
       g.drawImage(image, 0, 0, this); 
      } 
     } 

     @Override 
     public void mouseClicked(MouseEvent e) { 
     } 

     @Override 
     public void mousePressed(MouseEvent e) { 
//   clickPos = e.getLocationOnScreen(); 
      if (SwingUtilities.isRightMouseButton(e)) { 
       JPopupMenu popupMenu = new JPopupMenu(); 
       popupMenu.add(quitAction); 
       popupMenu.show(this, e.getX(), e.getY()); 
      } 
     } 

     @Override 
     public void mouseReleased(MouseEvent e) { 
     } 

     @Override 
     public void mouseEntered(MouseEvent e) { 
     } 

     @Override 
     public void mouseExited(MouseEvent e) { 
     } 

     boolean loadImage(String name) { 
      BufferedImage backupImage = image; 
      try { 
       image = ImageIO.read(MainWindow.class.getResourceAsStream("/images/" + name)); 
       setPreferredSize(new Dimension(image.getWidth(), image.getHeight())); 
      } catch (IOException ex) { 
       image = backupImage; 
       return false; 
      } 
      return true; 
     } 

    } 

} 
+0

Hm ... J'ai vérifié mon code sous Windows 10 et ça marche bien. Vous utilisez Mac OS si je comprends bien. Il semble que le problème n'apparaisse pas toujours, mais seulement dans certaines conditions. Dans mon cas, c'est Linux + Gnome 3. Mais j'ai trouvé une solution. –

0

J'ai trouvé un problème dans mon code. Pour que tout fonctionne correctement, j'ai besoin d'insérer ce code avant de dessiner avec g.drawImage dans paintCompontent.

if (g instanceof Graphics2D) { 
    Graphics2D g2d = (Graphics2D)g; 
    g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC)); 
} 

De plus, le problème n'apparaît pas dans tous les cas. Par exemple, sous Windows cela a bien fonctionné comme ça.