button background image transparency

I have a image: test.tif with transparency.

When I declare a button with:


self.button = DirectButton(self.frame, image="models/test.tif")

it doesn’t display the transparency

But, if I do it this way:


self.button = DirectButton(self.frame)
self.button['image'] = 'models/test.tif'

It does display the proper transparency. However, it is not clickable unless I put some text on the button. Also, the area of the button that responds to “roll_over” event seems to be only affected by the button this way.

Can I have a button with transparent background image but also be able to click it?

I’m gonna look in the BVW tutorial for that…

Well, here’s what I found:


startScreen = DirectButton(image = "models/SplashScreen.tif", command = runWorld, scale = 1.0)

It’s probably the “scale” in there, try that.

How does adding a “scale” parameter affect the transparency of a image?

In addition, I have a scale parameter in the constructor of the button. It still doesn’t have the propery transparency.

There’s a couple of complex things going on here.

First, you should understand how transparency works with Panda. Simply having an alpha channel does not automatically imply transparency; you can turn transparency on and off independently of the alpha channel. (If you load an texture up from an egg file, the egg loader automatically detects the presence of an alpha channel, and assumes that means you meant to have transparency turned on, so it turns it on for you–that’s why a lot of the time you don’t have to think about this.)

But when you pass a texture image name to the DirectButton class, it has no idea whether the texture you give it has an alpha channel or not, so it doesn’t set up transparency by default. But you can always enable transparency after you have created your button like this:


self.button.setTransparency(1)

Now in your second example, when you create a DirectButton with no parameters, you have created a DirectButton that has no contents, and therefore doesn’t take up any space on the screen. When you then add the image separately, it doesn’t update the size of its clickable region. That’s why you can’t click on the button in your second example–it’s really a very tiny button, though it looks big. That’s arguably a bug, but you can work around it by calling this:


self.button.setFrameSize()

This doesn’t explain why transparency works in the second example but not in the first. In fact, I don’t understand that at all; there’s no reason why transparency should work in the second example either, if you haven’t explicitly turned it on. Maybe you are doing something slightly different with the button in that case; for instance, maybe you are parenting it to a frame that does have transparency enabled, and it is inheriting that transparency setting.

Finally, although you can pass just the name of a texture to the DirectButton class and it will load the texture, it is generally better to load a texture up from an egg file instead of loading it directly by filename. This gets several nice benefits, including the automatic detection of an alpha channel and automatic enabling of transparency (as mentioned above).

To do this, make an egg file that contains a single polygon with your texture applied to it. If you don’t have one, you can make one with this command line:


egg-texture-cards -o mycard.egg test.tif

Then you can load this and use it as the background of your button, like this:

card = loader.loadModel('models/mycard.egg')
self.button = DirectButton(self.frame, image=card.find('test'))

That obviates the need to explicitly enable transparency.

David

Yes, in the examples I gave, I did use:



self.button.setTransparency(1)

so I had:


self.button = DirectButton(self.mobile_frame, image="models/image.tif")
self.button.setTransparency(1)

this refuses to work. Even when I enabled transparency on self.mobile_frame

Again, only way I could get it to show transparency is:


self.button = directionButton(self.moble_frame)
self.button['image'] = 'models/image.tif'
self.button.setTransparency(1)

But, this is not clickable.

… When I tried your method of re- calculating the frame size by:


self.button = directionButton(self.moble_frame)
self.button['image'] = 'models/image.tif'
self.button.setTransparency(1)
self.button.setFrameSize()

the transparency goes away again.

Does this have to do with the extra libraries I installed again? :confused:

Going to try to convert it to egg file and I will let you know if it works. :imp:

Oh! I see what’s going on. Try this:

self.button = DirectButton(self.mobile_frame, image="models/image.tif", relief=None)
self.button.setTransparency(1)

Without relief=None, the default behavior is to put a gray card behind your texture, of the same size as the clickable region, which might make it look like your texture doesn’t have transparency. :slight_smile:

David

Duuude…

That explains also why below works, but not clickable


self.button = DirectButton()
self.button['image'] = 'models/image.tif'
self.button.setTransparency(1)

:laughing:

Once again, you the man.

I found it :

  • Frame - the background (not image)
  • Frame has size and color
  • Frame is clickable region

=> In my opinion, you should change color of background like that:

self.button['frameColor'] = 0, 0, 0, 0

combine with Flat style:

b['relief'] = DirectGuiGlobals.FLAT