Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

transparent for real

Posted on 2004-03-22
7
761 Views
Last Modified: 2012-05-04
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
0
Comment
Question by:hapciu
  • 3
  • 2
  • 2
7 Comments
 
LVL 86

Expert Comment

by:CEHJ
ID: 10653061
Did you call

super.paintComponent();

?
0
 

Author Comment

by:hapciu
ID: 10653176
of course.... first thing in the method ...
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 10653204
That's just my 2c i'm afraid.
0
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 9

Expert Comment

by:doronb
ID: 10820033
Working on it, but could you post some code? :)
0
 
LVL 9

Accepted Solution

by:
doronb earned 80 total points
ID: 10821488
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
 

Author Comment

by:hapciu
ID: 10829219
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
 
LVL 9

Expert Comment

by:doronb
ID: 10829680
No problem, thanks for the points, I was going to suggest working with the UI classes, and do it myself too :)
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
netstat -ano | find "8000" and taskkill /f /pid 2984 3 83
factorial example 4 47
servlet filter example 37 71
going to wrong jsp page 2 33
For customizing the look of your lightweight component and making it look opaque like it was made of plastic.  This tip assumes your component to be of rectangular shape and completely opaque.   (CODE)
Are you developing a Java application and want to create Excel Spreadsheets? You have come to the right place, this article will describe how you can create Excel Spreadsheets from a Java Application. For the purposes of this article, I will be u…
Viewers will learn about the different types of variables in Java and how to declare them. Decide the type of variable desired: Put the keyword corresponding to the type of variable in front of the variable name: Use the equal sign to assign a v…
This video teaches viewers about errors in exception handling.

856 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question