2017-07-26 74 views
2

我有一個全屏幕繪圖畫布與綠色背景。在同一表單的分層面板上,以用戶選擇的圖像作爲背景啓動另一個繪圖畫布。現在,我想要的是我畫的路徑應該像橡皮擦一樣,所以我繪製的區域應該暴露背景(在這種情況下是綠色背景)。我不想將描邊顏色設置爲綠色。任何方式筆觸顏色可以是透明的?如何繪製透明描邊來顯示CodeName背景中的背景?

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; 

/** 
* This file was generated by <a href="https://www.codenameone.com/">Codename One</a> for the 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 all Forms by default 
     Toolbar.setGlobalToolbar(true); 

     // Pro only feature, uncomment if you have a 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類(用於創建畫布): -

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 to try to make this component as sensitive as possible to 
    * drag events. If we don't do this, it requires a longer drag before the "drag" 
    * events will 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 just the signature portion of the panel. This is is reuised to 
    * also create the image of the 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 a rectangle (in parent component space) used for the drawn "rectangle" inside 
    * which the user should draw their signature. It tries to create a 16x9 rectangle that 
    * fits inside the component with a 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 an x coordinate from screen space, to parent component space. 
    * @param x 
    * @return 
    */ 
    private int x(int x) { 
     return x - getParent().getAbsoluteX(); 
    } 

    /** 
    * Converts a y coordinate from screen space to parent component space. 
    * @param y 
    * @return 
    */ 
    private int y(int y) { 
     return y - getParent().getAbsoluteY(); 
    } 

    /** 
    * Gets the currently drawn signature as an image. This only includes the 
    * areas inside the {@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 the signature as a blank path. 
    */ 
    private void clear() { 
     path.reset(); 
    } 
} 

請忽略的代碼的註釋部分。

回答

0

透明筆畫只會畫任何東西。

您需要一個清晰的操作,這是我們目前沒有的操作。這是我們內部的一個功能,但我們沒有看到用例將其作爲API公開,因爲它包含性能損失。

這是一個合理的用例,所以請隨意file an RFE(請求增強),我想我們可以爲圖形公開清晰的矩形方法。

目前您的選項相對有限,您可以通過在可變圖像上繪製而不是直接在屏幕上進行像素操作,然後通過更改圖像的RGB內容並創建新圖像來擦除圖像中的像素與新的內容。這並不理想,但可行。

+0

這是否會導致性能下降(性能是當前的優先事項)? 此外,我們可以使用中風寬度的GeneralPath對象中的點剪切圖像嗎?會給橡皮擦的效果嗎?你能提供某種類型的代碼從這裏繼續嗎?非常感謝您的幫助 – Gurankas

+0

繪製柵格較慢,但可能不明顯。不同之處在於,當您繪製1000個元素時,柵格的性能將保持不變,因爲它只繪製一個圖像。載體將緩慢降解您添加的更多元素。無論您想使用像素還是矢量,柵格與矢量的問題更多的是概念問題 –