codenameone - How to draw a transparent stroke to reveal the background in CodeName one? -
i have full screen drawing canvas green coloured background. on layered panel of same form, drawing canvas initiated user selected image background. now, want path draw should act eraser region draw should expose background (in case, green background). don't want set stroke colour green. way stroke colour transparent?
mainclass:-
package com.mycompany.myapp; import com.codename1.ui.display; import com.codename1.ui.form; import com.codename1.ui.graphics; import com.codename1.ui.image; import com.codename1.ui.button; import com.codename1.ui.container; import com.codename1.ui.dialog; import com.codename1.ui.label; import com.codename1.ui.painter; import com.codename1.ui.plaf.uimanager; import com.codename1.ui.util.resources; import com.codename1.io.log; import com.codename1.io.multipartrequest; import com.codename1.ui.toolbar; import com.codename1.ui.urlimage; import com.codename1.ui.events.actionevent; import com.codename1.ui.events.actionlistener; import com.codename1.ui.geom.rectangle; import com.codename1.ui.layouts.borderlayout; import com.codename1.ui.layouts.flowlayout; import com.codename1.ui.layouts.layeredlayout; import com.codename1.ui.painter.painterchain; import java.io.ioexception; /** * file generated <a href="https://www.codenameone.com/">codename one</a> purpose * of building native mobile applications using java. */ public class mainclass { private form current; private resources theme; signaturepanel sp; public void init(object context) { theme = uimanager.initfirsttheme("/theme"); // enable toolbar on forms default toolbar.setglobaltoolbar(true); // pro feature, uncomment if have pro subscription // log.bindcrashprotection(true); } public void start() { if(current != null){ current.show(); return; } form hi = new form("hi world"); hi.setlayout(new borderlayout()); button browsegallery = new button("browse"); sp = new signaturepanel(); // hi.getlayeredpane(); // hi.add(layeredlayout.enclosein(new layeredlayout(), sp); system.out.println("before adding"); hi.addcomponent(borderlayout.center, sp); system.out.println("after adding"); //image test = image.createimage(1280, 800, 0xffff00); //hi.add(borderlayout.north,test); hi.addcomponent(borderlayout.south, browsegallery); browsegallery.addactionlistener(new actionlistener<actionevent>() { @override public void actionperformed(actionevent evt) { // todo auto-generated method stub display.getinstance().opengallery(new actionlistener<actionevent>() { @override public void actionperformed(actionevent evt) { // todo auto-generated method stub try { image image = urlimage.createimage((string)evt.getsource()); signaturepanel sp1 = new signaturepanel(); sp1.getallstyles().setbgimage(image); hi.add(hi.getlayeredpane().add(sp1)); //image mutable = image.createimage(1280, 800, 0x00ff00); //hi.add(borderlayout.center_behavior_center,mutable); //image.modifyalpha((byte) 10); } catch (exception e1) { // todo auto-generated catch block e1.printstacktrace(); } } }, display.gallery_image); } }); // hi.setglasspane(new painter() { // // @override // public void paint(graphics g, rectangle rect) { // // todo auto-generated method stub // system.out.println("glasspane"); // } // }); hi.show(); } public void stop() { current = display.getinstance().getcurrent(); if(current instanceof dialog) { ((dialog)current).dispose(); current = display.getinstance().getcurrent(); } } public void destroy() { } }
signaturepanel class (used create drawing canvas):-
package com.mycompany.myapp; import com.codename1.ui.component; import com.codename1.ui.display; import com.codename1.ui.font; import com.codename1.ui.graphics; import com.codename1.ui.image; import com.codename1.ui.stroke; import com.codename1.ui.geom.dimension; import com.codename1.ui.geom.generalpath; import com.codename1.ui.geom.rectangle; class signaturepanel extends component { private final generalpath path = new generalpath(); private final stroke stroke = new stroke(); private final rectangle signaturerect = new rectangle(); private final font xfont; private image value; signaturepanel() { stroke.setlinewidth(math.max(1, display.getinstance().converttopixels(1, true)/2)); getallstyles().setbgcolor(0x00ff00); getallstyles().setbgtransparency(255); xfont = font.createsystemfont(font.face_system, font.style_bold, font.size_large); } /** * overridden try make component sensitive possible * drag events. if don't this, requires longer drag before "drag" * events kick in. * @param x * @param y * @return */ @override protected int getdragregionstatus(int x, int y) { return component.drag_region_likely_drag_xy; } /** * * @param g */ @override public void paint(graphics g) { super.paint(g); g.setcolor(0x666666); calcsignaturerect(signaturerect); g.drawrect(signaturerect.getx(), signaturerect.gety(), signaturerect.getwidth(), signaturerect.getheight()); g.drawstring("x", signaturerect.getx() + display.getinstance().converttopixels(1, true), signaturerect.gety() + signaturerect.getheight() / 2); paintsignature(g); } /** * paints signature portion of panel. is reuised * create image of signature. * @param g */ private void paintsignature(graphics g) { g.setcolor(0x0); boolean oldaa = g.isantialiased(); g.setantialiased(true); g.drawshape(path, stroke); g.setantialiased(oldaa); } /** * calculates rectangle (in parent component space) used drawn "rectangle" inside * user should draw signature. tries create 16x9 rectangle * fits inside component bit of padding (3mm on each edge). * @param r output variable. */ private void calcsignaturerect(rectangle r) { int w = getwidth() - display.getinstance().converttopixels(6, true); int h = (int)(w * 9.0 / 16.0); if (h > getheight()) { h = getheight() - display.getinstance().converttopixels(6, false); w = (int)(h * 16.0 / 9.0); } r.setx(getx() + (getwidth() - w) / 2); r.sety(gety() + (getheight() - h)/2); r.setwidth(w); r.setheight(h); } @override protected dimension calcpreferredsize() { display d = display.getinstance(); return new dimension(d.converttopixels(100, true), d.converttopixels(60, false)); } @override public void pointerpressed(int x, int y) { path.moveto(x(x), y(y)); value = null; repaint(); } @override public void pointerdragged(int x, int y) { path.lineto(x(x), y(y)); value = null; repaint(); } @override public void pointerreleased(int x, int y) { value = null; repaint(); } /** * converts x coordinate screen space, parent component space. * @param x * @return */ private int x(int x) { return x - getparent().getabsolutex(); } /** * converts y coordinate screen space parent component space. * @param y * @return */ private int y(int y) { return y - getparent().getabsolutey(); } /** * gets drawn signature image. includes * areas inside {@link #signaturerect} * @return */ private image getimage() { calcsignaturerect(signaturerect); image img = image.createimage(signaturerect.getwidth(), signaturerect.getheight(), 0xffffff); graphics g = img.getgraphics(); g.translate(-signaturerect.getx(), -signaturerect.gety()); paintsignature(g); return img; } /** * resets signature blank path. */ private void clear() { path.reset(); } }
please ignore commented out portions of code.
a transparent stroke draw nothing.
you need clear operation don't have. it's feature have internally didn't see use case expose api includes performance penalty.
this reasonable use case feel free file rfe (request enhancement) , think we'll able expose clear rect method graphics.
at moment options relatively limited, can pixel manipulation drawing on mutable image instead of directly screen erase pixels image changing rgb content of image , creating new image new content. isn't ideal doable.
Comments
Post a Comment