首页 文章

是否可以在Multibutton(Codename One)上制作圆形图像(通过蒙版)

提问于
浏览
2

我有一个 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 . 是否可以在Codename One中的 MultiButton 上应用蒙版?如果是这样,我该怎么做?

任何帮助,赞赏,

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

我很难弄清楚为什么@Diamond的答案确实有效而不是我的答案,尽管我确实按照@ Shai的指导进行掩蔽以获得圆润的图像 . 所以我写了我的调查结果,以防CN1的其他新手遇到这个问题 . 再次向@Diamond致敬,他的出色解释帮助了很多!

首先,上面介绍的圆形面罩正在工作,因为它会产生黑色圆形 . 实际上,在应用蒙版的时候 reportImage 尚未下载since quoting from the javadoc

默认情况下,除非调用fetch()方法,否则会在GUI请求时懒惰地获取图像,在这种情况下,IO代码会立即执行 .

因此 reportImage 仍然像占位符一样黑 . 顺便说一下,这就是为什么@Diamond建议在实际(圆形)图像可用之前定义一个漂亮颜色的 round placeholder (参见他答案中的第一个 cmps[iter].setIcon(placeholder) 调用) .

只有在 InfiniteScrollAdapter 需要并获取图像时才会实际下载URLImage . 这就是@Diamond包装的原因

所以作为一个结论,上面的代码不能在_2588083中工作,在我所有的试验之后,我倾向于认为实现我想要做的唯一方法是@Diamond用@ Shai的建议写的代码 .

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 回答

  • 2

    是的,Multibutton图标是一个Label组件,您可以通过调用获得

    cmps[iter].getIconComponent()
    

    Edit:

    根据Shai的评论,你的代码应该变成这样的......

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

相关问题