将九个补丁图像加载为 Libgdx Scene2d 按钮背景看起来很糟糕

2022-01-12 00:00:00 java libgdx nine-patch

我正在尝试使用 通过 (libgdx) NinePatch 像这样:

this.dialogBu​​ttonUp = new NinePatchDrawable(new NinePatch(new Texture(Gdx.files.internal("data/button-round.9.png"))));this.dialogBu​​ttonDown = new NinePatchDrawable(new NinePatch(new Texture(Gdx.files.internal("data/button-round-down.9.png"))));

然后我制作一个描述按钮的 TextButtonStyle,并引用两个 NinePatch 可绘制对象:

TextButton.TextButtonStyle buttonStyle = new TextButton.TextButtonStyle();buttonStyle.font = aValidFontReally;buttonStyle.fontColor = 颜色.黑色;buttonStyle.up = this.dialogBu​​ttonUp;buttonStyle.down = this.dialogBu​​ttonDown;buttonStyle.pressedOffsetX = -2;

我正在通过 Dialog 框间接构建按钮:

new Dialog( ... ).button("Continue", null, buttonStyle);

我检查了 .9.png 文件以确保:

  • 资产文件已在 Eclipse 中刷新
  • 元数据边框像素是完全不可见或完全可见的黑色
  • Android draw9patch 工具可以加载图像并验证它们

关于检查或更改什么的任何其他建议?

解决方案

感谢@RodHyde 的一些指示,看起来 libgdx NinePatch 类旨在接受后处理"九补丁纹理(即,具有描述如何将单个纹理切割成补丁的单独整数值).这种处理"通常作为将.9.png"文件打包到 TextureAtlas 的副作用发生(参见 https://github.com/libgdx/libgdx/wiki/Texture-packer#ninePatches).纹理图集是一个非常好的主意(尤其是当您的 UI 包含一堆不同的纹理元素时),所以这是有道理的,但在开发和尝试运行某些东西时有点令人惊讶.

为了解决这个问题,我可以直接包含我写的.9.png"文件:

private static NinePatch processNinePatchFile(String fname) {最终纹理 t = new Texture(Gdx.files.internal(fname));最终 int 宽度 = t.getWidth() - 2;最终 int 高度 = t.getHeight() - 2;return new NinePatch(new TextureRegion(t, 1, 1, width, height), 3, 3, 3, 3);}

这会加载纹理,创建一个修剪掉 1 像素元数据边框的子区域,然后猜测九个补丁边框元素是 3 像素宽/高.(通过在纹理数据中乱搞来正确计算似乎是可能的,但不值得付出努力——在这种情况下,只需将纹理放入图集中即可.)

I'm trying to use a Nine Patch as a background for a Libgdx Scene2d UI button. It is loading, buts it is really ugly. I can see the "meta-data" pixels, and its being stretched as if it were just a regular image (the text on the button is "Continue"):

I'm loading the .9.png files directly into a (libgdx) NinePatchDrawable via a (libgdx) NinePatch like this:

this.dialogButtonUp = new NinePatchDrawable(
   new NinePatch(new Texture(Gdx.files.internal("data/button-round.9.png"))));
this.dialogButtonDown  = new NinePatchDrawable(
   new NinePatch(new Texture(Gdx.files.internal("data/button-round-down.9.png"))));

Then I make a TextButtonStyle that describes the button, and references the two NinePatch drawables:

TextButton.TextButtonStyle buttonStyle = new TextButton.TextButtonStyle();
buttonStyle.font =  aValidFontReally;
buttonStyle.fontColor = Color.BLACK;
buttonStyle.up = this.dialogButtonUp;
buttonStyle.down = this.dialogButtonDown;
buttonStyle.pressedOffsetX = -2;

I'm building the button indirectly, via a Dialog box:

new Dialog( ... ).button("Continue", null, buttonStyle);

I've checked the .9.png files to make sure that:

  • that the asset files were refreshed in Eclipse
  • that the meta-data border pixels are either fully-invisible or fully-visible-black
  • that the Android draw9patch tool can load the images and verify them

Any other suggestions on what to check or change?

解决方案

Thanks to some pointers from @RodHyde, it looks like the libgdx NinePatch class is designed to accept a "post-processed" nine patch texture (i.e., with separate integer values that describe how to cut the single texture into patches). This "processing" usually happens as a side-effect of packing a ".9.png" file into a TextureAtlas (see https://github.com/libgdx/libgdx/wiki/Texture-packer#ninePatches). A texture atlas is a really good idea (especially when your UI includes a bunch of different texture elements), so this makes sense, but is a bit surprising when developing and trying to get something running.

To work-around this so I can directly include ".9.png" files I wrote this:

private static NinePatch processNinePatchFile(String fname) {
    final Texture t = new Texture(Gdx.files.internal(fname));
    final int width = t.getWidth() - 2;
    final int height = t.getHeight() - 2;
    return new NinePatch(new TextureRegion(t, 1, 1, width, height), 3, 3, 3, 3);
}

This loads the texture, creates a sub-region that trims off the 1-pixel meta-data border, and then just guesses that the nine-patch border elements are 3 pixels wide/tall. (Computing that correctly by mucking about in the texture data seems possible, but not worth the effort -- just put the texture in an atlas in that case.)

相关文章