Is it possible to make rounded image (via mask) on Multibutton (Codename One)

限于喜欢 提交于 2019-12-08 02:05:49

问题


I have an InfiniteScrollAdapter in which I use Multibutton to display a list featuring a photo and its description.

It works well but I need to make the photo rounded. That's why I got inspired by the official guide on image masking. Unfortunately what I get is only a black round. Here is the code I used:

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);

What I've noticed is that all examples I could find about the rounded image in CN1 dealt with Label. Is it possible to apply a mask on a MultiButton in Codename One? If so, how can I do that?

Any help appreciated,

Summary after reading the answers and comments 2017-02-16

I have had hard time to figure out why @Diamond's answer did work and not mine although I did follow @Shai's guide on masking to get rounded images. So I write the outcome of my findings in case other newbies at CN1 came across this issue. Thnaks again to @Diamond for his great explanations that helped a lot!

First of all, the round mask introduced above is working since it yields a black round. Indeed by the time where the mask is applied the reportImage has not been downloaded yet 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.

Consequently reportImage is still as black as the placeholder was defined. By the way this is why @Diamond suggested to define a round placeholder with a nice color to be shown before the actual (round) image gets available (see the first cmps[iter].setIcon(placeholder) call in his answer).

And the URLImage will only be actually downloaded when the InfiniteScrollAdapter needs and fetches the image.That's why @Diamond wraps

So as a conclusion the code above cannot work in an InfiniteScrollAdapter and after all my trials I tend to think that the only way to achieve what I wanted to do is the code @Diamond wrote with @Shai's suggestion.

Please note that with if the downloaded picture is a PNG @Diamond's round mask adapter does not seem to work anymore => the resulting image is only rounded if the PNG is converted as JPEG.


回答1:


Yes it is, Multibutton icon is a Label component which you can get by calling

cmps[iter].getIconComponent()

Edit:

Based on Shai's comment, your code should become something like this...

Round Mask Adapter:

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;
    }
};

Code Improvement:

//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);


来源:https://stackoverflow.com/questions/42236165/is-it-possible-to-make-rounded-image-via-mask-on-multibutton-codename-one

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!