2017-02-14 1 views
2

У меня есть InfiniteScrollAdapter, в котором я использую Multibutton, чтобы отобразить список с изображением фотографии и ее описание.Можно ли сделать закругленное изображение (через маску) на Multibutton (Codename One)

Это хорошо работает, но мне нужно сделать фотографию округлой. Вот почему я получил вдохновение от 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 в Codename One? Если да, то как я могу это сделать?

Любая помощь приветствуется,

Резюме после прочтения ответы и комментарии 2017-02-16

я имел трудное время, чтобы выяснить, почему @ ответ Даймонда сделал дело, а не мое, хотя я следуйте руководству @ Shai по маскировке, чтобы получить округленные изображения. Поэтому я пишу результаты моих выводов, если другие новички в CN1 столкнулись с этой проблемой. Thnaks снова @Diamond за его большие объяснения, которые помогли много!

Прежде всего, круглая маска, введенная выше, работает, так как она дает черный круг. Действительно к тому времени, когда применяется reportImage еще не загружены since quoting from the javadoc

По умолчанию изображение скачиваются лениво, как она запрашивается с помощью графического интерфейса пользователя, если не получать маски() вызывается метод, в этом случае Код ввода-вывода выполняется немедленно.

Следовательно, reportImage все еще так же черным, как и определитель. Кстати, именно поэтому @Diamond предложила определить круглый заполнитель с приятным цветом, который будет показан до того, как появится реальное (круглое) изображение (см. Первый звонок cmps[iter].setIcon(placeholder) в его ответе).

И URLImage фактически будет загружен только тогда, когда InfiniteScrollAdapter потребности и делает выборку image.That почему @Diamond обертывания

Так как вывод приведенный выше код не может работать в InfiniteScrollAdapter и после всех моих исследований я, как правило, думаю, что единственный способ добиться того, что я хотел сделать, - это код @Diamond, написанный с предложением @ Shai.

Обратите внимание, что если загруженное изображение является адаптером для круглой маски PNG @ Diamond, похоже, больше не работает => результирующее изображение будет округлено, только если PNG будет преобразован как JPEG.

ответ

2

Да это многокнопочный значок представляет собой компонент Ярлыка, который вы можете получить, позвонив

cmps[iter].getIconComponent() 

Edit:

Основываясь на комментарии Шая, ваш код должен стать чем-то вроде этого ...

Круглая маска адаптер:

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

Correct. Я также хотел бы добавить, что было бы быстрее обойти изображение заранее (например, как 'URLImage'), что сделает приложение заикающимся меньше. –

+0

Спасибо @Diamond! Однако я не могу заставить его работать, поэтому я должен лучше понять. Поэтому, если я могу задать вам еще несколько заданий о вашем коде: 1) почему вы вызываете 'setIcon' перед вызовом' getIconComponent'? 2) Кроме того, какова цель инкапсуляции 'getIconComponent' в' callSerially'. 3) И, наконец, почему вы называете 'revalidate', тогда как компонент' cmps' не был добавлен? – HelloWorld

+0

Чтобы быть более точным в том, что не работает, я думаю, что маска не работает, потому что картинки выглядят не округлыми (но не черными больше, так что это уже изменение). Я буду погружаться в ваш код, чтобы лучше понять его! – HelloWorld

Смежные вопросы