transparent for real

in my swing application (with windows L&F) i want to set a gradient paint on my menu bar. so i extend JMenuBar and override the paintComponent method (that's the way, right?). all's ok until i add a JMenu to this menu bar of mine. I can't make the menu button (such as "File") to be transparent. Apparently setOpaque(false) works only with the Metal L&F. So how do i set my JMenu-s to see the menubar through them (both when they are selected and not selected) ??? thanks


p.s: i think the same problem occurs even if you only set the background of the menuBar
hapciuAsked:
Who is Participating?
 
doronbCommented:
Ok, I've built a GradientPainter object that performs the gradient work.
I also extended JMenuBar, JMenu, JMenuItem into their respective Gradient counter-parts.
I setup the Menus and MenuItems to share the Gradient of the MenuBar so that it looks ok.

However, under Windows for some reason, things don't seem to work right.
The JMenuBar doesn't draw the Gradient background while the other menu components do!
I'm working with JBuilder and inside JBuilder everything works just fine.
However, if I use the SystemLookAndFeel classes (Windows L&F) running my program from the executable JAR, then the JMenuBar doesn't work right.
If I run the JAR with the CrossPlatform L&F, everything works fine.

I think the problem lies in the L&F UI classes themselves because I believe its not entirely up to the Menu components to draw everything by themselves!

I don't know if it'd be any help, but here's my GradientPainter class :)

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

public class GradientPainter {
      private Image background;
      private Rectangle rect;
      private TransparentColourFilter filter;
      private GradientPaint gradient;
      private Rectangle gradientRect;
      private Color start = Color.black;
      private Color finish = Color.white;
      private JComponent swingComponent;
      private GradientPainter linkedGradient;
      private boolean isMaster = false;

      // Create a GradientPainter for a specific Swing component..
      public GradientPainter(JComponent c) {
            swingComponent = c;
      }

      public void setMasterGradient(GradientPainter gp) {
            linkedGradient = gp;
            linkedGradient.setMaster();
            gradient = null;
      }

      protected void setMaster() {
            isMaster = true;
      }

      protected GradientPaint getGradientPaint() {
            verifyGradientColour();
            return gradient;
      }

      // This is the TransparentColourFilter that will help us put the Gradient as background..
      private class TransparentColourFilter extends RGBImageFilter {
            protected int from;
            protected static final int rgbMask = 0x00ffffff;

            private TransparentColourFilter(Color transparentColour) {
                  super();
                  from = transparentColour.getRGB() & rgbMask;
                  canFilterIndexColorModel = true;
            }

            public int filterRGB(int x, int y, int rgb) {
                  return ((rgb & rgbMask) == from) ? rgbMask : rgb;
            }
      }

      private Rectangle getCurrentBounds() {
            Container current = swingComponent;
            if (isMaster) {
                  while (current.getParent() != null) {
                        current = current.getParent();
                  }
            }
            return current.getBounds();
      }

      // Make sure a GradientColor object is created for our use..
      private void verifyGradientColour() {
            gradientRect = getCurrentBounds();
            if (linkedGradient != null) {
                  gradient = linkedGradient.getGradientPaint();
            } else if ((gradient == null) || ((rect.width != gradientRect.width) || (rect.height != gradientRect.height))) {
                  gradient = new GradientPaint(0, 0, start, gradientRect.width, gradientRect.height, finish, true);
            }
      }

      public void setStartColor(Color colour) {
            start = colour;
      }

      public void setEndColor(Color colour) {
            finish = colour;
      }

      public Color getStartColor() {
            return start;
      }

      public Color getEndColor() {
            return finish;
      }

      // This method is used to prepare the Gradient background on the Component's Graphics..
      public Graphics prepareGraientBackground(Graphics g) {
            // Prepare a TransparentColourFilter object..
            filter = new TransparentColourFilter(swingComponent.getParent().getBackground());
            // Get the rectangle where we'll draw..
            rect = g.getClipBounds();
            // Get the Graphics object color..
            Color c = g.getColor();
            // Cast to Graphics2D..
            Graphics2D g2d = (Graphics2D)g;
            // Make sure we've created the Gradient colour..
            verifyGradientColour();
            // Set the Gradient as the Paint Object..
            g2d.setPaint(gradient);
            // Fill the rectangle with the gradient colour..
            g2d.fillRect(rect.x, rect.y, rect.width, rect.height);
            // Return to the previous paint colour..
            g2d.setPaint(c);
            // Create the background image..
            background = swingComponent.createImage(rect.width, rect.height);
            // Return the Graphics object that belongs to the background image..
            return background.getGraphics();
      }

      // This method is used to paint the transparent image over the Gradient background..
      public void paintComponent(Graphics g) {
            // Create a transparent image based on filtering the background image with the Gradient colour..
            background = swingComponent.createImage(new FilteredImageSource(background.getSource(), filter));
            // Finally, draw the transparent-gradient-background image together with the rest of the component..
            g.drawImage(background, rect.x, rect.y, null);
      }
}

I now of course have a GradientMenuBar:

public class GradientMenuBar extends JMenuBar {
      private GradientPainter tmHelper;

      public GradientMenuBar() {
            super();
            tmHelper = new GradientPainter(this);
      }

      public GradientPainter getGradientPainter() {
            return tmHelper;
      }

      public void setStartColor(Color colour) {
            tmHelper.setStartColor(colour);
      }

      public void setEndColor(Color colour) {
            tmHelper.setEndColor(colour);
      }

      public Color getStartColor() {
            return tmHelper.getStartColor();
      }

      public Color getEndColor() {
            return tmHelper.getEndColor();
      }

      protected void paintComponent(Graphics g) {
            super.paintComponent(tmHelper.prepareGraientBackground(g));
            tmHelper.paintComponent(g);
      }
}

And I also extended JMenu and JMenuItem into their respective GradientMenu and GradientMenuItem using the same template from GradientMenuBar.

The code that creates the Menus in my frame is almost the same as JBuilder's designer created for me:

      private GradientMenuBar jMenuBar1 = new GradientMenuBar();
      private GradientMenu jMenuFile = new GradientMenu();
      private GradientMenuItem jMenuFileExit = new GradientMenuItem();
      private GradientMenuItem jMenuFileStart = new GradientMenuItem();
      private GradientMenu jMenuHelp = new GradientMenu();
      private GradientMenuItem jMenuHelpAbout = new GradientMenuItem();

And I added this code to ensure the Gradient of the MenuBar is shared by its children like this:

      GradientPainter gp = jMenuBar1.getGradientPainter();
      jMenuFile.getGradientPainter().setMasterGradient(gp);
      jMenuHelp.getGradientPainter().setMasterGradient(gp);
      jMenuFileStart.getGradientPainter().setMasterGradient(gp);
      jMenuFileExit.getGradientPainter().setMasterGradient(gp);
      jMenuHelpAbout.getGradientPainter().setMasterGradient(gp);

It works for me, unless I run my JAR file completely from Windows with the Windows L&F, if this is not you current problem, my code may help.
If my code does help, I urge you to reconsider the amount of points you've dedicated to this question because it seems a bit low for the amount of work and knowledge that has to go into this, then again, you may already solved everything, in which case, the reward is the code itself ;)

Hope this helps,
Doron
0
 
CEHJCommented:
Did you call

super.paintComponent();

?
0
 
hapciuAuthor Commented:
of course.... first thing in the method ...
0
Cloud Class® Course: Amazon Web Services - Basic

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

 
CEHJCommented:
That's just my 2c i'm afraid.
0
 
doronbCommented:
Working on it, but could you post some code? :)
0
 
hapciuAuthor Commented:
well thanks a lot for the effort, but i've already solved my problem on my own - unlike you i have  extended the UI classes (BasicMenuBarUI, BasicMenuUI and BasicMenuItemUI) and it works just fine. but as i said, i did that on my own, eventually.
i will give you the points because it doesn't hurt me, but i won't increase them.
0
 
doronbCommented:
No problem, thanks for the points, I was going to suggest working with the UI classes, and do it myself too :)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.