I am trying to display several PNG Images on a JLayeredPane with overlapping.
Here is the current code for generating the JLabel containing the image and adding it to the JLayeredPane :
BufferedImage im = ImageIO.read(new File(fname));
JLabel uLabel = createLabelForImage(im);
mapLayeredPane.add(uLabel, new Integer(zIndex++), 1);
And the createLabelForImage() method :
protected JLabel createLabelForImage(BufferedImage im) {
JLabel label = new JLabel(new ImageIcon(im));
label.setVerticalAlignment(JLabel.TOP);
label.setHorizontalAlignment(JLabel.CENTER);
label.setOpaque(true);
label.setBounds(0, 0, im.getWidth(), im.getHeight());
return label;
}
What I get is the objects are correctly overlapping but the transparent background of the PNG images is replaced with a kind of white-gray color.
Is it a problem with ImageIcon ? With JLayeredPane ? Maybe I have to set something like label.setBakground(sort_of_transparency_code) or something like that ?
Thanks in advance :)
Your label should not be opaque if you want to see through, see JComponent.setOpaque
If true the component paints every pixel within its bounds.
Otherwise, the component may not paint some or all of its
pixels, allowing the underlying pixels to show through.
Related
It should probably go without saying, but I'm fairly new to swing.
I'm trying to make a simple little thing which will display two images side by side, as large as the window will allow.
In theory what happening is:
We get an imageIcon, in this case 001.jpg.
We figure out the ratio of width/height of the imageIcon.
We turn the imageIcon into an image.
We turn that image into a new correctly sized image.
We turn that image back into an image icon.
This all breaks down because the only way I've found to get the window size is size, but that keeps returning 0s.
This is the code I have right now:
class UI extends MainFrame {
title = "Matt's window header"
preferredSize = new Dimension(1920, 1080)
var imageIcon = new ImageIcon("001.jpg")
val imgRatio = imageIcon.getIconWidth.toDouble / imageIcon.getIconHeight.toDouble
println(size)
pack()
println(imgRatio)
val image = imageIcon.getImage()
val newimg = image.getScaledInstance(size.width, (size.width * imgRatio.toInt), java.awt.Image.SCALE_SMOOTH)
imageIcon = new ImageIcon(newimg)
contents = new Label {
icon = imageIcon
}
}
As an aside, it would be great if someone could give me info about how to load a different image, instead of just 001.jpg.
sizeis not determined at the point you are accessing it.
However, preferredSizeis. If you add println(preferredSize) you will get the Dimensions you just set.
This seems like it should be so easy that I'm embarrassed to ask, but I just can't get it.
I have a large round MovieClip (being used as a button). This MovieClip contains a PNG with a transparent background inserted into the MovieClip.
Due to its size there are large empty registration areas on the 4 corners (the bounding box).
How can I have the mouse register as being over only the circle pixels and not the blank space (of Alpha channel pixels) in the square boundary box?
Simple sample code:
public function simpleSample () : void
{
mc1.buttonMode = true;
mc1.addEventListener(MouseEvent.CLICK, doStuff);
}
public function doStuff (event:MouseEvent) : void
{
mc2.gotoAndStop(2);
}
Here are 3 different ways to accomplish this.
EDIT Since you've later explained that your button is an image, this first option won't work for you
If the shape flag on hitTestPoint works with your button (eg it's a shape), you can use hitTestPoint inside your mouse click handler to figure out if the click is actually over the object:
public function doStuff(event:MouseEvent){
//only continue if hit test point is true,
//the x and y values are global (not relative to the mc your testing as one might suppose)
//the third parameter should be true, so it takes into account the shape of object and not just it's bounds
if(mc1.hitTestPoint(stage.mouseX, stage.mouseY, true)){
mc2.gotoAndStop(2);
}
}
If the above doesn't work because you have bimtap data in your button, then an easy way to accomplish this is to just add a shape mask to the button.
So, either inside your button using FlasPro, mask everything with a circle shape, or, do it via code by doing the following when you first show the button:
var s:Shape = new Shape();
s.graphics.beginFill(0);
s.graphics.drawCircle(mc1.x + (mc1.width * .5), mc1.y + (mc1.height * .5), mc1.width / 2);
addChild(s);
mc1.mask = s;
If using an image as the button, or you want to set a threshold of how transparent to consider a click, then you can check the transparency of the pixel under the mouse:
function doStuff(event:MouseEvent){
//only continue if pixel under the mosue is NOT transparent
//first, you need a bitmap to work with
//if you know for sure the position of your bitmap, you can do something like this:
var bm:Bitmap = mc1.getChildAt(0) as Bitmap;
//annoyingly though, FlashPro makes timeline bitmaps shapes,
//so the above won't work UNLESS you take your bitmap in the FlashPro Library
//and export it for actionscript, giving it a class name, then it will be an actual bitmap on the timeline.
//As an alternative, you could (very CPU expensively) draw the whole button as a bitmap
var bmd:BitmapData = new BitmapData(mc1.width,mc1.height,true,0x00000000);
bmd.draw(mc1);
var bm:Bitmap = new Bitmap(bmd);
//we get the 32bit pixel under the mouse point
var pixel:uint = bm.bitmapData.getPixel32(bm.x + event.localX,bm.y + event.localY);
//then we grab just the Alpha part of that pixel ( >> 24 & 0xFF ).
//if the value is 0, it's totally transparent, if it's 255, it's totally opaque.
//for this example, let's say anything greater than 0 is considered good to be a click
if((pixel >> 24 & 0xFF) > 0){
mc2.gotoAndStop(2);
}
}
I need the ability to be able to create an image of size 400x400 on the fly in a Windows Phone app, which will have a color of ARGB values that a user selects from a color picker. For instance, the user will click on a HyperlinkButton to take them to a ColorPickerPage and then will select a color, and I will retrieve that value and create the image from it, and display this image back on the MainPage. How might something like this be accomplished one I have retrieved the ARGB value from the user? I have not had luck finding any resources on this particular issue.
EDIT**
I came across http://www.geekchamp.com/forums/windows-phone-development/how-to-correctly-save-uicontrol-with-opacity-to-writeablebitmap which creates a rectangle on the screen and then saves to WriteableBitmap, but how might I skip that step and just save the Rectangle to WriteableBitmap? Note, I only have a single rectangle that I Fill with a custom Color.
You can save any UI element as an image using the code below. Here rect is the name of the rectangle in your XAML. If the rectangle isn't present in the UI then simply create one using C#. I have added the code to create a rectangle using C# and commented it.
public void saveimage(int height, int width, String filename)
{
//Rectangle rect = new Rectangle();
//rect.Height = 40;
//rect.Width = 40;
//rect.Fill = new SolidColorBrush(System.Windows.Media.Colors.Cyan);
var bmp = new WriteableBitmap(width, height);
bmp.Render(rect, null);
bmp.Invalidate();
var isf = IsolatedStorageFile.GetUserStoreForApplication();
if (!isf.FileExists(filename))
{
using (var stream = isf.OpenFile(filename, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite))
{
bmp.SaveJpeg(stream, width, height, 0, 100);
stream.Close();
}
}
}
Did you try using the Drawing Class.
here's the reference from msdn.
These are some samples: System.Drawing and System.Drawing.Imaging alternatives for Windows Phone
http://code.msdn.microsoft.com/windowsapps/Multi-Touch-Drawing-744a0b48
Hope it helps!
I use Stage in libGDX for drawing GUI and adding listeners to controls in my game.
But when I draw text on ImageTextButton I get mirrored text as displayed on image below.
Can some help me and tell me how to draw normal text, not mirrored ?
stage = new Stage(Constants.VIEWPORT_GUI_WIDTH, Constants.VIEWPORT_GUI_HEIGHT);
stage.clear();
....
ImageTextButtonStyle imageTextButtonStyle = new ImageTextButtonStyle();
imageTextButtonStyle.font = Assets.instance.fonts.defaultSmall;
ImageTextButton imageTextButton = new ImageTextButton("ddsds", imageTextButtonStyle);
imageTextButton.setBackground( gameUISkin.getDrawable("fil_coins"));
imageTextButton.setPosition(50, 600);
imageTextButton.setHeight(85);
imageTextButton.setWidth(183);
stage.addActor(imageTextButton);
....
public void render (float deltaTime) {
stage.act(deltaTime);
stage.draw();
}
Thanks
Edit:
Button images are shown correct, only text has mirrored view
As #Springrbua suggest me in comment below, my bitmap font was flipped when creating.
defaultSmall = new BitmapFont(Gdx.files.internal("images/font.fnt"), true);
should be
defaultSmall = new BitmapFont(Gdx.files.internal("images/font.fnt"), false);
Even it's not case here it may be useful for someone - if font size parameter is set to negative value, text will be rendered upside-down (Y-scale).
I have a problem and I have potential solution. But I wanted to confirm if there is an easy and simple way to solve my problem.
App type:
Isometric Game
Problem statement:
I am loading images in my flash app and have mouse events attached to them.
The images I load are prop images like vehicles, trees, buildings etc., and all of them are transparent.
Example: Red ball asset (please ignore the yellow background which I applied to describe the problem)
If I click on the actual image area (colored in red), then every thing works perfect
I don't want to trigger mouseevent when I click on empty image part (or transparent area, which I have shown in yellow color)
There is one way I know by creating masks in flash. I don't want to do it unless that is the final option left because I load image assets instead of flash assets and I don't want to create a new mask asset for all the assets
There is another method I was going to adopt by using getPixel method of Bitmap. Which is discussed here.
But there is another problem with this method.
I might be able to ignore the click event when I click on the empty part of the asset but if there is some other asset is behind the image in the same location, then I need to process the click event for the occluded image.
Well, thinking of solution to this problem takes me to the getObjectsUnderPoint where I can scan the occluded assets
Well, what you proposed as a solution is 100% valid. Just move the logic of determining what game object is clicked outside of that object.
Listen for MOUSE_DOWN/MOUSE_UP events at container which contains your game objects.
Catch an event
Check if the game object which is the target of this event is transparent at this point using BitmapData.getPixel32
If it is use getObjectsUnderPoint to find out all other game objects at this point
Find in a loop the first object which is not transparent at this point
Now you got the actual object which is hit.
One interesting solution is to use Sprite objects with the individual non-transparent pixels burnt onto them.
Suppose this is your Loader "complete" handler:
private function loaderCompleteHandler(event:Event):void
{
// Loader is not our child, we use a Sprite instead (below).
var loader:Loader = Loader(event.target);
var sprite:Sprite = new Sprite();
addChild(sprite);
var w:Number = loader.content.width;
var h:Number = loader.content.height;
// Use transparent bitmap.
var bitmapData:BitmapData = new BitmapData(w, h, true, 0);
bitmapData.draw(loader.content);
// Now burn the image onto the Sprite object, ignoring
// the transparent pixels.
for (var xPos:int = 0; xPos < w; xPos++) {
for (var yPos:int = 0; yPos < h; yPos++) {
var pixel32:uint = bitmapData.getPixel32(xPos, yPos);
var alpha:int = pixel32 >>> 24;
if (alpha != 0) {
sprite.graphics.beginFill(pixel32 & 0xFFFFFF, alpha / 0xFF);
sprite.graphics.drawRect(xPos, yPos, 1, 1);
sprite.graphics.endFill();
}
}
}
}
Essentially you want "empty" pixels that aren't clickable, and fully transparent pixels aren't quite the same thing. With this solution you get empty pixels.
Only problem is that this might be slow. Give it a shot.