Android自学之图形图像之使用双缓冲画

本文介绍在处理大量数据时,如何通过双缓冲技术提高绘图速度,并提供了实现过程和代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考文章:http://blog.youkuaiyun.com/lee576/article/details/7870160

在他的基础上稍微补充了一点:


当数据量很大时,绘图可能需要几秒钟甚至更长的时间,而且有时还会出现闪烁现象,为了解决这些问题,可采用双缓冲技术来绘图。
 双缓冲即在内存中创建一个与屏幕绘图区域一致的对象,先将图形绘制到内存中的这个对象上,再一次性将这个对象上的图形拷贝到屏幕上,这样能大大加快绘图的速度。双缓冲实现过程如下:
  1、在内存中创建与画布一致的缓冲区
  2、在缓冲区画图
  3、将缓冲区位图拷贝到当前画布上

  4、释放内存缓冲区


代码已经传到网上,下载地址为:

http://download.youkuaiyun.com/download/qizheguang/9434947


下面贴代码:

MainActivity.java

package com.example.doublebuffer;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.BlurMaskFilter;
import android.graphics.EmbossMaskFilter;
import android.graphics.Color;  
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity{

	 EmbossMaskFilter emboss;  
	 BlurMaskFilter blur;
	
	 DrawView	drawview;			//调用另一个类
	 
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		emboss = new EmbossMaskFilter(new float[]{1.5f,1.5f,1.5f},0.6f,6,4.2f);  
        blur = new BlurMaskFilter(8,BlurMaskFilter.Blur.NORMAL); 
        
        Button button = (Button)findViewById(R.id.Erase_Everything);
        
        drawview = (DrawView)findViewById(R.id.draw);
        
        button.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				drawview.ReleaseDraw();	
			}
		});
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		
		MenuInflater inflator = new MenuInflater(this);  
        //状态R.menu.context对应菜单,并添加到中  
        inflator.inflate(R.menu.main, menu);  
        return super.onCreateOptionsMenu(menu);  
        
        
//		getMenuInflater().inflate(R.menu.main, menu);
//		return true;
	}

	
	//菜单项被单击后的回调方法  
	@Override
    public boolean onOptionsItemSelected(MenuItem mi)  
    {  
        DrawView dv = (DrawView)findViewById(R.id.draw);  
        //判断单击的是哪个菜单项,并有针对性地做出响应  
        switch(mi.getItemId())  
        {  
            case R.id.red:  
                dv.paint.setColor(Color.RED);  
                mi.setChecked(true);  
                break;  
            case R.id.green:  
                dv.paint.setColor(Color.GREEN);  
                mi.setChecked(true);  
                break;  
            case R.id.blue:  
                dv.paint.setColor(Color.BLUE);  
                mi.setChecked(true);  
                break;  
            case R.id.width_1:  
                dv.paint.setStrokeWidth(1);  
                mi.setChecked(true);  
                break;  
            case R.id.width_3:  
                dv.paint.setStrokeWidth(3);  
                mi.setChecked(true);  
                break;  
            case R.id.width_5:  
                dv.paint.setStrokeWidth(5);  
                mi.setChecked(true);  
                break;  
            case R.id.blur:  
                dv.paint.setMaskFilter(blur);  
                mi.setChecked(true);  
                break;  
            case R.id.emboss:  
                dv.paint.setMaskFilter(emboss);  
                mi.setChecked(true);  
                break;
        }  
        return true;  
    }  
    
}



DrawView.java

package com.example.doublebuffer;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;

public class DrawView extends View {
	
//	public Button btnEraseAll;
//  public LayoutParams params;
    
	float preX;  
    float preY;  
    private Path path;  
    public Paint paint = null;  
//    final int VIEW_WIDTH = 320;  
 //   final int VIEW_HEIGHT = 480;  
    //定义一个内存中的图片,该图片将作为缓冲区  
    Bitmap cacheBitmap = null;  
    //定义cacheBitmap上的canvas对象  
    Canvas cacheCanvas = null;  
    int width;								//手机屏幕宽度
    int height;								//手机屏幕高度
    
    public DrawView(Context context, AttributeSet attrs) {  
        super(context, attrs);  
        //创建一个与该View相同大小的缓存区  
 //      cacheBitmap = Bitmap.createBitmap(VIEW_WIDTH,VIEW_HEIGHT,Config.ARGB_8888);
    	
       WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
       width = wm.getDefaultDisplay().getWidth();			//--表示函数很老
       height = wm.getDefaultDisplay().getHeight();
        
//      btnEraseAll = new Button(context);
//      btnEraseAll.setText("Erase Everything!!");
//      params = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT);			//动态构建布局
//      btnEraseAll.setLayoutParams(params);
           	
    } 
    
    //释放
    public void ReleaseDraw()
	{	
    	cacheBitmap = null;
    	cacheCanvas = null;
    	
		path.reset();
		postInvalidate();  
	}
    
    public boolean onTouchEvent(MotionEvent event)  
    {  
        //获取拖动事件发生的位置  
        float x = event.getX();  
        float y = event.getY();  
        switch(event.getAction())  
        {  
            case MotionEvent.ACTION_DOWN:  					//按下
                 path.moveTo(x, y);  
                 preX = x;  
                 preY = y;  
                 break;  
            case MotionEvent.ACTION_MOVE:  					//移动
                 path.quadTo(preX, preY, x, y);  
                 preX = x;  
                 preY = y;  
                 break;  
            case MotionEvent.ACTION_UP:  					//抬起
                 cacheCanvas.drawPath(path, paint);  
                 path.reset();  
                 break;  
        }  
        
        invalidate(); 
        
        //返回true表明处理方法已经处理该事件  
        return true;  
    }
    
    public void onDraw(Canvas canvas)  
    {  
    	if (cacheBitmap == null) {
    		cacheBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);  
            cacheCanvas = new Canvas();  
            path = new Path();  
            //设置cacheCanvas将会绘制到内存中的cacheBitmap上  
            cacheCanvas.setBitmap(cacheBitmap);  
            
            //设置画笔的颜色  
            paint = new Paint(Paint.DITHER_FLAG);  
            paint.setColor(Color.RED);  
            
            //设置画笔的风格  
            paint.setStyle(Paint.Style.STROKE);  
            paint.setStrokeWidth(5);  
            
            //设置结合处的样子,MITER:结合处为锐角, ROUND:结合处为圆弧:BEVEL:结合处为直线。
            paint.setStrokeJoin(Paint.Join.ROUND);
            
            //反锯齿  
            paint.setAntiAlias(true);  
            paint.setDither(true);  
		}
    	
        Paint bmpPaint = new Paint();  
        //将cacheBitmap绘制到该View组件上  
        canvas.drawBitmap(cacheBitmap, 0, 0, bmpPaint);  
        //沿着path绘制  
        canvas.drawPath(path, paint);  
    } 
}



布局文件:

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
         
    <com.example.doublebuffer.DrawView
        android:id="@+id/draw"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="9"
      />
    
    <Button
		android:id="@+id/Erase_Everything"
		android:layout_width="match_parent"
		android:layout_height="0dp"
		android:layout_weight="1"
		android:text="Erase Everything"
		/>
    
    <!-- View 
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#000000"/-->
    </LinearLayout>   
     
</LinearLayout>


menu菜单文件:

main.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <!-- item
        android:id="@+id/action_settings"
        android:orderInCategory="100"
        android:showAsAction="never"
        android:title="@string/action_settings"/-->

        <item android:title="@string/color">  
        <menu>  
            <!-- 定义一组单选菜单项 -->  
            <group android:checkableBehavior="single">  
                <!-- 定义多个菜单项 -->  
                <item  
                    android:id="@+id/red" android:title="@string/color_red"/>  
                <item  
                    android:id="@+id/green" android:title="@string/color_green"/>  
                <item  
                    android:id="@+id/blue" android:title="@string/color_blue"/>  
            </group>  
        </menu>  
    </item>  
    <item android:title="@string/width">  
        <menu>  
            <!-- 定义一组菜单项 -->  
            <group>  
                <!-- 定义3个菜单项 -->  
                <item  
                    android:id="@+id/width_1" android:title="@string/width_1"/>  
                <item  
                    android:id="@+id/width_3" android:title="@string/width_3"/>  
                <item  
                    android:id="@+id/width_5" android:title="@string/width_5"/>                        
            </group>  
        </menu>  
    </item>  
    <item  
        android:id="@+id/blur" android:title="@string/blur"/>      
    <item  
        android:id="@+id/emboss" android:title="@string/emboss"/> 
        
</menu>

strings.xml

    <string name="hello">Hello World, HandDraw!</string> 
    <string name="width_1">1像素</string>   
	<string name="width_3">3像素</string>   
	<string name="width_5">5像素</string>   
	<string name="color_red">红色</string>   
	<string name="color_green">绿色</string>   
	<string name="color_blue">蓝色</string>   
	<string name="color">画笔颜色</string>   
	<string name="width">画笔宽度</string>   
	<string name="blur">模糊效果</string>   
	<string name="emboss">浮雕效果</string>   



















基于数据挖掘的音乐推荐系统设计与实现 需要一个代码说明,不需要论文 采用python语言,django框架,mysql数据库开发 编程环境:pycharm,mysql8.0 系统分为前台+后台模式开发 网站前台: 用户注册, 登录 搜索音乐,音乐欣赏(可以在线进行播放) 用户登陆时选择相关感兴趣的音乐风格 音乐收藏 音乐推荐算法:(重点) 本课题需要大量用户行为(如播放记录、收藏列表)、音乐特征(如音频特征、歌曲元数据)等数据 (1)根据用户之间相似性或关联性,给一个用户推荐与其相似或有关联的其他用户所感兴趣的音乐; (2)根据音乐之间的相似性或关联性,给一个用户推荐与其感兴趣的音乐相似或有关联的其他音乐。 基于用户的推荐和基于物品的推荐 其中基于用户的推荐是基于用户的相似度找出相似相似用户,然后向目标用户推荐其相似用户喜欢的东西(和你类似的人也喜欢**东西); 而基于物品的推荐是基于物品的相似度找出相似的物品做推荐(喜欢该音乐的人还喜欢了**音乐); 管理员 管理员信息管理 注册用户管理,审核 音乐爬虫(爬虫方式爬取网站音乐数据) 音乐信息管理(上传歌曲MP3,以便前台播放) 音乐收藏管理 用户 用户资料修改 我的音乐收藏 完整前后端源码,部署后可正常运行! 环境说明 开发语言:python后端 python版本:3.7 数据库:mysql 5.7+ 数据库工具:Navicat11+ 开发软件:pycharm
MPU6050是一款广泛应用在无人机、机器人和运动设备中的六轴姿态传感器,它集成了三轴陀螺仪和三轴加速度计。这款传感器能够实时监测并提供设备的角速度和线性加速度数据,对于理解物体的动态运动状态至关重要。在Arduino平台上,通过特定的库文件可以方便地与MPU6050进行通信,获取并解析传感器数据。 `MPU6050.cpp`和`MPU6050.h`是Arduino库的关键组成部分。`MPU6050.h`是头文件,包含了定义传感器接口和函数声明。它定义了类`MPU6050`,该类包含了初始化传感器、读取数据等方法。例如,`begin()`函数用于设置传感器的工作模式和I2C地址,`getAcceleration()`和`getGyroscope()`则分别用于获取加速度和角速度数据。 在Arduino项目中,首先需要包含`MPU6050.h`头文件,然后创建`MPU6050`对象,并调用`begin()`函数初始化传感器。之后,可以通过循环调用`getAcceleration()`和`getGyroscope()`来不断更新传感器读数。为了处理这些原始数据,通常还需要进行校准和滤波,以消除噪声和漂移。 I2C通信协议是MPU6050与Arduino交互的基础,它是一种低引脚数的串行通信协议,允许多个设备共享一对数据线。Arduino板上的Wire库提供了I2C通信的底层支持,使得用户无需深入了解通信细节,就能方便地与MPU6050交互。 MPU6050传感器的数据包括加速度(X、Y、Z轴)和角速度(同样为X、Y、Z轴)。加速度数据可以用来计算物体的静态位置和动态运动,而角速度数据则能反映物体转动的速度。结合这两个数据,可以进一步计算出物体的姿态(如角度和角速度变化)。 在嵌入式开发领域,特别是使用STM32微控制器时,也可以找到类似的库来驱动MPU6050。STM32通常具有更强大的处理能力和更多的GPIO口,可以实现更复杂的控制算法。然而,基本的传感器操作流程和数据处理原理与Arduino平台相似。 在实际应用中,除了基本的传感器读取,还可能涉及到温度补偿、低功耗模式设置、DMP(数字运动处理器)功能的利用等高级特性。DMP可以帮助处理传感器数据,实现更高级的运动估计,减轻主控制器的计算负担。 MPU6050是一个强大的六轴传感器,广泛应用于各种需要实时运动追踪的项目中。通过 Arduino 或 STM32 的库文件,开发者可以轻松地与传感器交互,获取并处理数据,实现各种创新应用。博客和其他开源资源是学习和解决问题的重要途径,通过这些资源,开发者可以获得关于MPU6050的详细信息和实践指南
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zheguangqi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值