是否可以在多按钮(代号一)上制作圆形图像(通过蒙版)
Is it possible to make rounded image (via mask) on Multibutton (Codename One)
我有一个 InfiniteScrollAdapter
,我在其中使用 Multibutton
来显示包含照片及其描述的列表。
效果很好,但我需要把照片弄圆。这就是为什么我从 the official guide 图像遮罩中得到启发。不幸的是,我得到的只是一个黑色的圆形。这是我使用的代码:
MultiButton[] cmps = new MultiButton[reports.size()];
for (int iter = 0; iter < reports.size(); iter++) {
Report currentReport = reports.get(iter);
if (currentReport == null) {
InfiniteScrollAdapter.addMoreComponents(this.getContentPane(), new Component[0], false);
return;
}
String photoFilenameInStorage = Report.getFilename(currentReport.getPhotoPath());
Image reportImage = URLImage.createToStorage(placeholder, photoFilenameInStorage, currentReport.getPhotoPath(), URLImage.RESIZE_SCALE_TO_FILL );
int w = reportImage.getWidth();
int h = reportImage.getHeight();
// Generates a mask to make the image round
Image maskImage = Image.createImage(w, h, 0xff000000);
Graphics g = maskImage.getGraphics();
g.setAntiAliased(true);
g.setColor(0xFFFFFF);
g.fillArc(0, 0, w, h, 0, 360);
Object mask = maskImage.createMask();
Image maskedImage = reportImage.applyMask(mask);
String summary = currentReport.getLocation();
cmps[iter] = new MultiButton(summary);
// Only shows a black filled circle!
cmps[iter].setIcon(maskedImage);
}
InfiniteScrollAdapter.addMoreComponents(this.getContentPane(), cmps, true);
我注意到,我能找到的关于 CN1 中圆形图像的所有示例都处理了 Label
。是否可以在代号一中的 MultiButton
上应用掩码?如果可以,我该怎么做?
感谢任何帮助,
2017-02-16看完答案和评论后总结
尽管我确实遵循了@Shai 的蒙版指南以获得圆形图像,但我很难弄清楚为什么@Diamond 的答案有效而不是我的。所以我写下我的发现结果,以防 CN1 的其他新手遇到这个问题。再次感谢@Diamond 的精彩解释,帮助很大!
首先,上面介绍的圆形蒙版有效,因为它会产生黑色圆形。实际上,在应用掩码时 reportImage
尚未下载 since quoting from the javadoc
By default an image is fetched lazily as it is asked for by the GUI unless the fetch() method is invoked in which case the IO code is executed immediately.
因此 reportImage
仍然像定义占位符一样黑。顺便说一句,这就是为什么@Diamond 建议定义一个 round 占位符 并在实际(圆形)图像可用之前显示一个漂亮的颜色(参见第一个 cmps[iter].setIcon(placeholder)
调用在他的回答中)。
只有当 InfiniteScrollAdapter
需要并获取 image.That 时才会实际下载 URLImage,这是 @Diamond 包装
的原因
因此,作为结论,上面的代码无法在 InfiniteScrollAdapter
中运行,经过所有试验后,我倾向于认为实现我想做的事情的唯一方法是@Diamond 和@Shai 一起编写的代码建议。
请注意,如果下载的图片是 PNG @Diamond 的圆形遮罩适配器似乎不再起作用 => 只有当 PNG 转换为 JPEG 时,生成的图像才会是圆形的.
是的,Multibutton icon是一个Label组件,可以调用
cmps[iter].getIconComponent()
编辑:
根据 Shai 的评论,您的代码应该变成这样...
圆形面罩适配器:
private final URLImage.ImageAdapter RESIZE_SCALE_WITH_ROUND_MASK = new URLImage.ImageAdapter() {
@Override
public EncodedImage adaptImage(EncodedImage downloadedImage, EncodedImage placeholderImage) {
Image tmp = downloadedImage.scaledLargerRatio(placeholderImage.getWidth(), placeholderImage.getHeight());
if (tmp.getWidth() > placeholderImage.getWidth()) {
int diff = tmp.getWidth() - placeholderImage.getWidth();
int x = diff / 2;
tmp = tmp.subImage(x, 0, placeholderImage.getWidth(), placeholderImage.getHeight(), true);
} else if (tmp.getHeight() > placeholderImage.getHeight()) {
int diff = tmp.getHeight() - placeholderImage.getHeight();
int y = diff / 2;
tmp = tmp.subImage(0, y, Math.min(placeholderImage.getWidth(), tmp.getWidth()),
Math.min(placeholderImage.getHeight(), tmp.getHeight()), true);
}
Image roundMask = Image.createImage(tmp.getWidth(), tmp.getHeight(), 0xff000000);
Graphics gr = roundMask.getGraphics();
gr.setColor(0xffffff);
gr.fillArc(0, 0, tmp.getWidth(), tmp.getHeight(), 0, 360);
Object mask = roundMask.createMask();
tmp = tmp.applyMask(mask);
return EncodedImage.createFromImage(tmp, false);
}
@Override
public boolean isAsyncAdapter() {
return true;
}
};
代码改进:
//Placeholder image
int size = Display.getInstance().convertToPixels(20);
Image placeholder = Image.createImage(size, size, 0xbfc9d2);
Graphics g = placeholder.getGraphics();
g.setAntiAliased(true);
g.setColor(0xbfc9d2);
g.fillArc(0, 0, size, size, 0, 360);
MultiButton[] cmps = new MultiButton[reports.size()];
for (int iter = 0; iter < reports.size(); iter++) {
Report currentReport = reports.get(iter);
if (currentReport == null) {
InfiniteScrollAdapter.addMoreComponents(this.getContentPane(), new Component[0], false);
return;
}
String photoFilenameInStorage = Report.getFilename(currentReport.getPhotoPath());
String summary = currentReport.getLocation();
cmps[iter] = new MultiButton(summary);
// Only shows a black filled circle!
cmps[iter].setIcon(placeholder);
Display.getInstance().callSerially(() -> {
cmps[iter].setIcon( URLImage.createToStorage(cmps[iter].getIcon(), photoFilenameInStorage, currentReport.getPhotoPath(), RESIZE_SCALE_WITH_ROUND_CORNER_MASK));
cmps[iter].getParent().revalidate();
});
}
InfiniteScrollAdapter.addMoreComponents(this.getContentPane(), cmps, true);
我有一个 InfiniteScrollAdapter
,我在其中使用 Multibutton
来显示包含照片及其描述的列表。
效果很好,但我需要把照片弄圆。这就是为什么我从 the official guide 图像遮罩中得到启发。不幸的是,我得到的只是一个黑色的圆形。这是我使用的代码:
MultiButton[] cmps = new MultiButton[reports.size()];
for (int iter = 0; iter < reports.size(); iter++) {
Report currentReport = reports.get(iter);
if (currentReport == null) {
InfiniteScrollAdapter.addMoreComponents(this.getContentPane(), new Component[0], false);
return;
}
String photoFilenameInStorage = Report.getFilename(currentReport.getPhotoPath());
Image reportImage = URLImage.createToStorage(placeholder, photoFilenameInStorage, currentReport.getPhotoPath(), URLImage.RESIZE_SCALE_TO_FILL );
int w = reportImage.getWidth();
int h = reportImage.getHeight();
// Generates a mask to make the image round
Image maskImage = Image.createImage(w, h, 0xff000000);
Graphics g = maskImage.getGraphics();
g.setAntiAliased(true);
g.setColor(0xFFFFFF);
g.fillArc(0, 0, w, h, 0, 360);
Object mask = maskImage.createMask();
Image maskedImage = reportImage.applyMask(mask);
String summary = currentReport.getLocation();
cmps[iter] = new MultiButton(summary);
// Only shows a black filled circle!
cmps[iter].setIcon(maskedImage);
}
InfiniteScrollAdapter.addMoreComponents(this.getContentPane(), cmps, true);
我注意到,我能找到的关于 CN1 中圆形图像的所有示例都处理了 Label
。是否可以在代号一中的 MultiButton
上应用掩码?如果可以,我该怎么做?
感谢任何帮助,
2017-02-16看完答案和评论后总结
尽管我确实遵循了@Shai 的蒙版指南以获得圆形图像,但我很难弄清楚为什么@Diamond 的答案有效而不是我的。所以我写下我的发现结果,以防 CN1 的其他新手遇到这个问题。再次感谢@Diamond 的精彩解释,帮助很大!
首先,上面介绍的圆形蒙版有效,因为它会产生黑色圆形。实际上,在应用掩码时 reportImage
尚未下载 since quoting from the javadoc
By default an image is fetched lazily as it is asked for by the GUI unless the fetch() method is invoked in which case the IO code is executed immediately.
因此 reportImage
仍然像定义占位符一样黑。顺便说一句,这就是为什么@Diamond 建议定义一个 round 占位符 并在实际(圆形)图像可用之前显示一个漂亮的颜色(参见第一个 cmps[iter].setIcon(placeholder)
调用在他的回答中)。
只有当 InfiniteScrollAdapter
需要并获取 image.That 时才会实际下载 URLImage,这是 @Diamond 包装
因此,作为结论,上面的代码无法在 InfiniteScrollAdapter
中运行,经过所有试验后,我倾向于认为实现我想做的事情的唯一方法是@Diamond 和@Shai 一起编写的代码建议。
请注意,如果下载的图片是 PNG @Diamond 的圆形遮罩适配器似乎不再起作用 => 只有当 PNG 转换为 JPEG 时,生成的图像才会是圆形的.
是的,Multibutton icon是一个Label组件,可以调用
cmps[iter].getIconComponent()
编辑:
根据 Shai 的评论,您的代码应该变成这样...
圆形面罩适配器:
private final URLImage.ImageAdapter RESIZE_SCALE_WITH_ROUND_MASK = new URLImage.ImageAdapter() {
@Override
public EncodedImage adaptImage(EncodedImage downloadedImage, EncodedImage placeholderImage) {
Image tmp = downloadedImage.scaledLargerRatio(placeholderImage.getWidth(), placeholderImage.getHeight());
if (tmp.getWidth() > placeholderImage.getWidth()) {
int diff = tmp.getWidth() - placeholderImage.getWidth();
int x = diff / 2;
tmp = tmp.subImage(x, 0, placeholderImage.getWidth(), placeholderImage.getHeight(), true);
} else if (tmp.getHeight() > placeholderImage.getHeight()) {
int diff = tmp.getHeight() - placeholderImage.getHeight();
int y = diff / 2;
tmp = tmp.subImage(0, y, Math.min(placeholderImage.getWidth(), tmp.getWidth()),
Math.min(placeholderImage.getHeight(), tmp.getHeight()), true);
}
Image roundMask = Image.createImage(tmp.getWidth(), tmp.getHeight(), 0xff000000);
Graphics gr = roundMask.getGraphics();
gr.setColor(0xffffff);
gr.fillArc(0, 0, tmp.getWidth(), tmp.getHeight(), 0, 360);
Object mask = roundMask.createMask();
tmp = tmp.applyMask(mask);
return EncodedImage.createFromImage(tmp, false);
}
@Override
public boolean isAsyncAdapter() {
return true;
}
};
代码改进:
//Placeholder image
int size = Display.getInstance().convertToPixels(20);
Image placeholder = Image.createImage(size, size, 0xbfc9d2);
Graphics g = placeholder.getGraphics();
g.setAntiAliased(true);
g.setColor(0xbfc9d2);
g.fillArc(0, 0, size, size, 0, 360);
MultiButton[] cmps = new MultiButton[reports.size()];
for (int iter = 0; iter < reports.size(); iter++) {
Report currentReport = reports.get(iter);
if (currentReport == null) {
InfiniteScrollAdapter.addMoreComponents(this.getContentPane(), new Component[0], false);
return;
}
String photoFilenameInStorage = Report.getFilename(currentReport.getPhotoPath());
String summary = currentReport.getLocation();
cmps[iter] = new MultiButton(summary);
// Only shows a black filled circle!
cmps[iter].setIcon(placeholder);
Display.getInstance().callSerially(() -> {
cmps[iter].setIcon( URLImage.createToStorage(cmps[iter].getIcon(), photoFilenameInStorage, currentReport.getPhotoPath(), RESIZE_SCALE_WITH_ROUND_CORNER_MASK));
cmps[iter].getParent().revalidate();
});
}
InfiniteScrollAdapter.addMoreComponents(this.getContentPane(), cmps, true);