我正在制作一个绘图应用程序,我想用手指触摸移动屏幕绘制心形。所以我将BitmapShader设置为以下代码
QString username = ui->lineEdit->text();
QString password = ui->lineEdit_2->text();
QMessageBox Failed;
Failed.setWindowFlags(Qt::FramelessWindowHint);
if(username == "Jon" && password == "12345")
{
Failed.setText("Login failed. Try again.");
Failed.exec();
} else {
Failed.setText(password);
Failed.exec();
}
然后我指定着色器绘画对象。
//Initialize the bitmap object by loading an image from the resources folder
Bitmap fillBMP = BitmapFactory.decodeResource(context.getResources(), R.drawable.heart);
fillBMP = Bitmap.createScaledBitmap(fillBMP, 20, 20, false);
//Initialize the BitmapShader with the Bitmap object and set the texture tile mode
shader= new BitmapShader(fillBMP, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
我还设置了触控监听器来跟踪用户手指。在用户触摸时,我在canvas对象上绘制为。
paint.setShader(preset.shader);
这给我这个
某些心形被歪曲,并且这些也是重复的。我想要的不是这些都是重复的,永远不会像这样发作。
提前致谢。
答案 0 :(得分:7)
上传到Git时遇到了一些麻烦,所以现在我会在这里发布解决方案。
这是我写的一个帮助类,用于创建你想要的效果。我在线添加评论来解释我在做什么。
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
// Use this class with a Canvas to create the effect you want.
public class CurvedBitmapDrawer
{
private Context mContext;
private Paint mPaint;
private int mResourceId;
private Bitmap mBitmap;
private Path mPath;
private int mBitmapMargin;
// Create with a context so that this class can use resource ids.
public CurvedBitmapDrawer(Context context) {
mContext = context;
mPath = new Path();
}
// getters setters for paint.
// this paint will be used to draw the bitmaps, and the strokeWidth value in the paint
// will be used to set the thickness of the curve / line that is drawn.
public Paint getPaint() {
return mPaint;
}
public void setPaint(Paint paint) {
mPaint = paint;
}
// getters setters for the space between the bitmaps.
public int getBitmapMargin()
{
return mBitmapMargin;
}
public void setBitmapMargin(int bitmapMargin)
{
mBitmapMargin = bitmapMargin;
}
// getters setters for res id
public int getResourceId() {
return mResourceId;
}
public void setResourceId(int resourceId)
{
mResourceId = resourceId;
mBitmap = null;
}
// alternative optional getters setters for bitmap.
public Bitmap getBitmap()
{
return mBitmap;
}
public void setBitmap(Bitmap bitmap)
{
mBitmap = bitmap;
mResourceId = 0;
}
// I decided to only use a local path here, but feel free to change it.
// call getPath to perform actions on the path that is drawn by this class.
public Path getPath()
{
return mPath;
}
// draw method. comments inline.
public void draw(Canvas canvas)
{
// grab a bitmap in the desired size.
final Bitmap scaledBitmap = getScaledBitmap();
// find the center of the bitmap.
final float centerX = scaledBitmap.getWidth() / 2;
final float centerY = scaledBitmap.getHeight() / 2;
// wrap the path with a measurement tool for paths - PathMeasure
final PathMeasure pathMeasure = new PathMeasure(mPath, false);
// initialize the distance to the center of the bitmap.
float distance = scaledBitmap.getWidth() / 2;
// initialize position and slope buffers.
float[] position = new float[2];
float[] slope = new float[2];
float slopeDegree;
// draw so long as the distance traveled on the path isn't longer than
// the total distance of the path.
while (distance < pathMeasure.getLength())
{
// grab the position & slope (tangent) on a particular distance along the path.
pathMeasure.getPosTan(distance, position, slope);
// convert the vector to a degree.
slopeDegree = (float)((Math.atan2(slope[1], slope[0]) * 180f) / Math.PI);
// preserve the current state of the canvas
canvas.save();
// translate the canvas to the position on the path.
canvas.translate(position[0] - centerX, position[1] - centerY);
// rotate the canvas around the center of the bitmap the amount of degrees needed.
canvas.rotate(slopeDegree, centerX, centerY);
// draw the bitmap
canvas.drawBitmap(scaledBitmap, 0, 0, mPaint);
// revert the bitmap to the previous state
canvas.restore();
// increase the distance by the bitmap's width + the desired margin.
distance += scaledBitmap.getWidth() + mBitmapMargin;
}
}
// returns a scaled bitmap from the asset specified.
private Bitmap getScaledBitmap()
{
// no bitmap or resId, return null (no special handing of this! add if you like).
if (mBitmap == null && mResourceId == 0)
return null;
// if no bitmap is specified, create one from the resource id.
// Optimization: be sure to clear the bitmap once done.
if (mBitmap == null)
mBitmap = BitmapFactory.decodeResource(mContext.getResources(), mResourceId);
// width / height of the bitmap[
float width = mBitmap.getWidth();
float height = mBitmap.getHeight();
// ratio of the bitmap
float ratio = width / height;
// set the height of the bitmap to the width of the path (from the paint object).
float scaledHeight = mPaint.getStrokeWidth();
// to maintain aspect ratio of the bitmap, use the height * ratio for the width.
float scaledWidth = scaledHeight * ratio;
// return the generated bitmap, scaled to the correct size.
return Bitmap.createScaledBitmap(mBitmap, (int)scaledWidth, (int)scaledHeight, true);
}
}
这是一个用法示例:
ImageView image = (ImageView)findViewById(R.id.img);
CurvedBitmapDrawer drawer = new CurvedBitmapDrawer(this);
Paint paint = new Paint();
paint.setStrokeWidth(50);
drawer.setPaint(paint);
drawer.setResourceId(R.drawable.heart_icon);
drawer.setBitmapMargin(10);
Path path = drawer.getPath();
path.moveTo(80, 90);
path.cubicTo(160, 470, 750, 290, 440, 880);
Bitmap finalBitmap = Bitmap.createBitmap(800, 1000, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(finalBitmap);
drawer.draw(canvas);
image.setImageBitmap(finalBitmap);
我已经在这里进行了测试,它似乎运行良好,可能会减去一些边缘情况。这是使用给定用法示例的样子:
请记住在您提供的绘画对象上设置笔触宽度,否则将不会绘制任何内容(并且可能会导致当前代码出现异常)。
希望这会对你有所帮助。