Stretching buttons in libgdx? - java

In libgdx, you can create a TextButtonStyle that has images for up and down states, but when you set the size of a button it stretches the image. Is there anyway to make a button style that allows you to set the corners, sides and middle of a button so that instead of stretching the button image, it just tiles the sides and middle images? For example, a button in java's swing library can be set to any size without having a stretched look, but in libgdx a button stretches its image to fit the rectangle. This is more noticable on rounded buttons. How can I fix this?

What you are looking for is called a NinePatch. Basically that is an special kind of image that defines strechable and not-strechable parts of the image. A typical use case for the NinePatch is a Button as you usually don't want the edges to get stretched and just stretch the rest.
A Simple example of instantiating would be:
NinePatch patch = new NinePatch(new Texture(Gdx.files.internal("knob.png")), 12, 12, 12, 12);
For more details about this example you can see the wiki page about NinePatches: https://github.com/libgdx/libgdx/wiki/Ninepatches

Related

Scaling ImageView object does not seem to change the clickable area

First of all, this is my first project in JavaFX, so if my general approach is wrong, I very much appreciate feedback on how else to implement this.
I'm trying to set up a hexagon grid of clickable tiles, similar to Settlers of Catan. I did this by creating a hex class that includes an imageview. For scaling purposes, these imageviews are scaled by a common parameter, where I tried both the .setScaleX/Y and setFitWidth/Heigth functions.
For what it matters, each hex is combined into a StackPane object and then all the hexes are combined into a Group.
To detect mouseclicks, I'm using the .setOnMouseClicked() function.
The problem I've been facing is that when the scaling parameter gets small, the imageviews seem to overlap their clickable areas. The graphic, however, scales properly. Since the setOnMouseClicked() function only responds non-transparent parts, this means there is no response when clicking on tiles overlapped by others.
How can I solve this problem?
Is there a way to scale the clickable area using my global scale parameter?
Can I somehow define the clickable area using some kind of path along the border?
Would it work to define a transparent hexagon shaped button and place on top of my image?
I tried using different approaches to scaling, such as setScaleX and setFitWidth.
I tried using setMaxSize() on the StackPane.
I tried using viewport and clip, but I don't think they do what I'm looking for.
public Hex(Point2D pos, double sizeScale){
...
Image img = new Image( "images/hex.png" );
m_size = new Point2D(img.getWidth(), img.getHeight());
m_image = new ImageView( img );
...
m_image.setFitWidth( m_sizeScale * m_size.getX() );
m_image.setFitHeight( m_sizeScale * m_size.getY() );
...
}
Expected result:
Each hex is clickable, giving different responses based on which hex is clicked.
Actual result:
Hexes added before added hexes are not clickable if positioned to the right or below. (Anchor point is top-left)

Displaying a part of an image in libGDX - looks stretched

I'm trying to build an progress bar in libGDX, for that I have one full horizontal image and in two lines I trying to display 2 different widths of that image:
imageFull:
imageFull.draw(batch,10,80,600,50);
imageFull.draw(batch,10,20,100,50);
the result is:
Its looks like when the width is 'small' its stretched and looks bad.
Why I can't display only part of the image without destroying the left side of the image?
Any ideas how to fix it?
That is normal behavior. If you stretch a image without keeping it's aspect ratio it will deform, it does not know the stretchable part by itself.
9-patch will help you here but you cannot simply draw the sprite as you are doing now (maybe with SpriteDrawable though?).
If I where you I would use the Scene2D Actor named ProgressBar. Feed that a 9-patch image, then it should stretch correctly. Or just use a Image if you want to control it yourself, and feed this image a ninepatch.
A quick way to create a ninepatch is to specify it's stretching regions yourself by hardcoding it.
texture = new NinePatch(yourTexture, A, B, C, D)
Where ABCD corresponds to the following image:
Now create a Scene2D Image with that ninepatch and it should stretch properly.
If you have a this texture already in a Atlas you can also supply the line split:a,b,c,d to the image data in the .atlas file and Scene2D will automatically pick it up as a ninepatch.
If you don't want to use Scene2D and/or ninepatch (but I recommend you to use it) you have to code the behavior yourself. Or cut the texture up yourself and stick the caps on the left and right side of your rectangle. But Scene2D is invented for this and a ton more GUI functionality.

Android layout glitch: reusing 9-patch image as backgrounds

I'm making a minesweeper app in AndroidStudio, and have a layout which I dynamically add the buttons to. I have tried multiple layouts and button types, which have all given me the same problem. I have created 9-patch images for the different background states:
which I set for each button using btn.setBackgroundResource(R.drawable.btn_up).
This all works fine normally, however if the buttons are made too small or there are too many of them, the screen displays strange glitch shapes. The glitch is made worse the larger the number of buttons, and the smaller the size of the buttons. The images below show respectively: small buttons/big grid; slightly bigger buttons; using the red 9-patch as the default background.
This is fixed by using normal png images but I would quite like to use the scalable 9-patch ones. Clicking the buttons changes the glitch shapes, tending to improve the visibility. I have tried simplifying the layout, and I am sure nothing else is affecting it - it is as simple as I've stated. The glitch shapes seem to originate in the top-left corner, and contain the colour of the 9-patch image, as you can see in the screenshots.
Does anyone have any idea why this is happening or how to fix it?

libgdx Resizing an Image with Border

i have an image with a 5px black border what i will use for serveral buttons.
The only problem is, that the buttons have different sizes.
Is there a way to resize it properly?
The only way i can figure it out, is to split it in individually pieces.
Eg.:
The Image is 200x200 and the Button 200x200 -> Border is ok.
The Image is 200x200 (the same) and the button 400x200 -> Border is stretched.
resize an image to diffrerent image ratio without stretch i don't know i someting like taht could exist , but here what i will do to solve your problem
this is your what is happening
to solve this i would use an image border full black and draw it under the image like the picture
when re-size it instead of 400X200 i will decrease it with a little margin like 380x200
hope this was clear and helpfull
After the last Months i´ve learned very much about libgdx and i must say that the use of ninepatches are the best solution.
See here to learn more about 9patch in libGDX

What is the best way to rotate several buttons in a jpanel around a central point?

I am working on a project in which I have a background image with specific points of interest. Each of these specific points will have a custom button class overlaid on it so that when I click the point, I'm actually clicking the button. However, I would like to be able to rotate the background image and have the buttons rotate with the image so that the custom buttons are still overlaid on the specific points. Any tips as to how I should go about doing this?
Are you actually wanting to rotate 4 different images and move them around the square, but always keeping them upright? Or are you rotating a single image so that after one button click the single image is on its side? If the former, then that can be easily done by using a container (a JPanel) that uses BorderLayout, and having four JPanels with background images and JButtons held in the container JPanel at the four compass points of the BorderLayout: BorderLayout.EAST, BorderLayout.WEST, BorderLayout.NORTH, and BorderLayout.SOUTH (although Java gurus prefer you use the newer constants, i.e., BorderLayout.PAGE_START). Then when a button is pressed, remove components and re-add but in a rotated order.
If you want to do the latter, then things get a bit trickier in that you'll likely need to use AffineTransforms, rotate instance to rotate the container, and you'll need to perform the same transformation on the point of the mouse press/click/release, so that the rotated buttons receive correct clicks. If the container is not square, things get even trickier still.

Categories