Ben
Ben

Reputation: 57207

Java Swing - Change JComponent opacity from mouse listener

Pretty much like the title says - I've got a JPanel, and I'd like to have it at 90% opacity if inactive, and full opacity if moused over.

I've got the separate components working - the mouse over and out is OK and I can change the opacity from overriding the paintComponent method, but I suppose I'm having trouble with the connection between the MouseAdapter and the paintComponent.

It seems there's probably a really easy way to do this - any tips?

(BTW sorry left the code at home so no example for now :( unless it's not quickly solvable then I'll throw some code up tomorrow.)

Upvotes: 1

Views: 1332

Answers (3)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285403

Shoot, I don't have the Haase and Guy book with me, and I don't remember the way they recommend to code for translucent components, but I guess overriding either paint or paintComponent work except that overriding paint will show the effect on child components from the get-go. For example:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class OpaqueJPanels {

   private static void createAndShowUI() {
      JPanel mainPanel = new JPanel(new GridLayout(1, 0));
      mainPanel.add(new OpaqueJPanel(false, "Override paintComponent"));
      mainPanel.add(new OpaqueJPanel(true, "Override paint"));

      JFrame frame = new JFrame("Opaque JPanels");
      frame.getContentPane().add(mainPanel);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }
}

class OpaqueJPanel extends JPanel {
   private static final int OJP_WIDTH = 250;
   private static final int OJP_HEIGHT = OJP_WIDTH;
   private static final Composite TRANSLUSCENT_COMPOSITE = AlphaComposite
            .getInstance(AlphaComposite.SRC_OVER, 0.4f);
   private static final Composite NON_TRANSLUSCENT_COMPOSITE = AlphaComposite
            .getInstance(AlphaComposite.SRC_OVER, 1.0f);
   private boolean overridePaint;
   private boolean transluscent = true;

   public OpaqueJPanel(boolean overridePaint, String title) {
      add(new JButton("Button"));
      setBorder(BorderFactory.createTitledBorder(title));
      addMouseListener(new MouseAdapter() {
         @Override
         public void mouseEntered(MouseEvent e) {
            transluscent = false;
            getParent().repaint();
         }

         @Override
         public void mouseExited(MouseEvent e) {
            if (!OpaqueJPanel.this.contains(e.getPoint())) {
               transluscent = true;
               getParent().repaint();
            }
         }
      });
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(OJP_WIDTH, OJP_HEIGHT);
   }

   @Override
   public void paint(Graphics g) {
      if (!overridePaint) {
         super.paint(g);
         return;
      }
      Graphics2D g2 = (Graphics2D) g;
      Composite composite = transluscent ? TRANSLUSCENT_COMPOSITE
               : NON_TRANSLUSCENT_COMPOSITE;
      g2.setComposite(composite);
      super.paint(g);
   }

   @Override
   protected void paintComponent(Graphics g) {
      if (overridePaint) {
         super.paintComponent(g);
         return;
      }
      Graphics2D g2 = (Graphics2D) g;
      Composite composite = transluscent ? TRANSLUSCENT_COMPOSITE
               : NON_TRANSLUSCENT_COMPOSITE;
      g2.setComposite(composite);
      super.paintComponent(g);
   }
}

I also found that it was better if I repainted the JPanel's parent component rather than the JPanel itself.

Upvotes: 3

ty1824
ty1824

Reputation: 1200

If you are overriding the paintComponent method, you should be able to add an opacity variable to the JPanel extension. Modify this in the MouseAdapter (using mutators). Then refer to this variable in the overridden paintComponent method to determine how to paint.

Upvotes: 4

DoubleMalt
DoubleMalt

Reputation: 1283

If you override the paintComponent method already, I'd suggest you make the MouseAdapter an anonymous inner class of your Panel and let it manipulate a private boolean flag.

public class FadingPanel extends JPanel
{
    private boolean active;

    public FadingPanel()
    {
        createMouseAdapter();
    }

    private void createMouseAdapter()
    {
        this.addMouseListener(new MouseAdapter()
        {
            // your mouseadapter code here toggling the active flag
        } 
    }

    @Override
    public boolean paintComponent(Graphics g)
    {
         if(active)
         {
              super.paintComponent(g);
         }
         else
         {
              // your semitransparent painting code here
         }
    }
}

Upvotes: 3

Related Questions