Codenameone 如何绘制一个透明的笔划以显示代号为1的背景?
我有一个绿色背景的全屏绘画画布。在同一表单的分层面板上,启动另一个图形画布,以用户选择的图像作为背景。现在,我想要的是,我绘制的路径应该作为一个橡皮擦,所以我绘制的区域应该暴露背景(在本例中为绿色背景)。我不想将笔划颜色设置为绿色。笔画的颜色是透明的吗 主要类别:-Codenameone 如何绘制一个透明的笔划以显示代号为1的背景?,codenameone,Codenameone,我有一个绿色背景的全屏绘画画布。在同一表单的分层面板上,启动另一个图形画布,以用户选择的图像作为背景。现在,我想要的是,我绘制的路径应该作为一个橡皮擦,所以我绘制的区域应该暴露背景(在本例中为绿色背景)。我不想将笔划颜色设置为绿色。笔画的颜色是透明的吗 主要类别:- package com.mycompany.myapp; import com.codename1.ui.Display; import com.codename1.ui.Form; import com.codename1.u
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() {
}
}
请忽略代码中注释掉的部分。透明的笔划将不会绘制任何内容 你需要一个清晰的操作,这是我们目前没有的。这是我们内部拥有的一个特性,但我们没有看到将其作为API公开的用例,因为它包含性能损失 这是一个合理的用例,所以请随意(请求增强),我认为我们将能够公开一个清晰的rect图形方法
目前,您的选项相对有限,您可以通过在可变图像上绘制而不是直接在屏幕上进行像素操作,然后通过更改图像的RGB内容并使用该新内容创建新图像来擦除图像中的像素。这并不理想,但可行。这是否会导致性能下降(性能是当前的首要任务)?此外,我们可以使用具有笔划宽度的GeneralPath对象中的点剪裁图像吗?那会有橡皮擦的效果吗?你能提供一些代码从这里开始吗?非常感谢您的帮助在光栅上绘图速度较慢,但可能不明显。不同之处在于,当您绘制1000个元素时,光栅的性能将保持不变,因为它只绘制一个图像。添加的元素越多,向量将慢慢降级。光栅与矢量的问题更像是一个概念性的问题,无论您是想处理像素还是矢量
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();
}
}