请教各位高手一个android 绘图和线程的问题 本帖最后由 zgy441008825 于 2012-08-31 11:36:02 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 这样在子线程和主线程之间交互的问题还真有点复杂。我还不知道这个是怎么回事,我建议, 把那个runnable去掉,写个函数。用一个for循环 int t = 当前时间; for(int i = 0; i < 6; i++){ sendMessageDelayed(Message,t + i *100);}这样就能依次延时100毫秒发消息,而且在UI线程。然后那边handleMessage里面调用mCanvas.drawRect(),全部在UI线程做试试。希望我的回答能给楼主帮助。 按照楼上的意思 改正这样的import java.util.Calendar;import android.annotation.SuppressLint;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.os.Handler;import android.os.Message;import android.util.DisplayMetrics;import android.view.View;public class Histogram extends View implements Runnable{ private int displayw = 0; private int displayy = 0; private static int cardinalX = 0; // 第一个矩形X轴基点 private static int cardinalY = 0; // 第一个矩形Y轴基点 private static int rectwidth = 30; // 矩形宽 private static int rectheight = 15; // 矩形高 private static int betweenrect = 2; int x_end, y_end, temp; Paint paint = new Paint(); boolean flag = true; Canvas mCanvas; public Histogram(Context context) { super(context); DisplayMetrics dm = MainActivity.getdm(); displayw = dm.widthPixels; displayy = dm.heightPixels; cardinalX = displayw - displayw / 5; cardinalY = displayy - displayy / 5; x_end = cardinalX + rectwidth; y_end = cardinalY + rectheight; temp = rectheight + betweenrect; paint.setAntiAlias(true); paint.setColor(Color.BLUE); // TODO Auto-generated constructor stub } @SuppressLint("DrawAllocation") @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); mCanvas = canvas; this.run(); } Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); switch(msg.what){ case 0x01:{ mCanvas.drawRect(cardinalX, cardinalY -= temp, x_end, y_end -= temp,paint); System.out.println(" "+mCanvas); }break; } } }; @Override public void run() { // TODO Auto-generated method stub for(int i = 0; i < 6; i++){ mHandler.sendEmptyMessageDelayed(0x01,i*1000); } }}但是直接就看不到效果了 什么都没画出来 不过下面的System能正常的延时打印 这个VIEW implements Runnable我怎么感觉怪怪的。试过把implements Runnable删掉,然后把run()换个名字在onDraw()里面调用吗?仅是好奇 @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); mCanvas = canvas; // Don't do this !!! this.run(); }If you want to use the canvas elsewhere,extends your class from SurfaceView. 我把所有代码都贴出来吧MainActivityimport android.app.Activity;import android.os.Bundle;import android.util.DisplayMetrics;import android.view.ViewGroup;import android.view.ViewGroup.LayoutParams;public class MainActivity extends Activity { private static DisplayMetrics dm = new DisplayMetrics(); private Histogram mHistogram; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //覆盖父类的onCreate方法 getWindowManager().getDefaultDisplay().getMetrics(dm); ViewGroup viewGroup=(ViewGroup)getLayoutInflater().inflate(R.layout.activity_main,null); mHistogram = new Histogram(this); //将画布放置在两个按键下面 viewGroup.addView(mHistogram,new LayoutParams(LayoutParams.FILL_PARENT,dm.heightPixels)); setContentView(viewGroup); } public static DisplayMetrics getdm(){ return dm; }}package com.zou.test;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.DisplayMetrics;import android.view.View;public class Histogram extends View{ private int displayw = 0; private int displayy = 0; private static int cardinalX = 0; // 第一个矩形X轴基点 private static int cardinalY = 0; // 第一个矩形Y轴基点 private static int rectwidth = 30; // 矩形宽 private static int rectheight = 15; // 矩形高 private static int betweenrect = 2; int x_end, y_end, temp; Paint paint = new Paint(); boolean flag = true; Canvas mCanvas; HistogramThread myHistogramThread = null; public Histogram(Context context) { super(context); DisplayMetrics dm = MainActivity.getdm(); displayw = dm.widthPixels; displayy = dm.heightPixels; cardinalX = displayw - displayw / 5; cardinalY = displayy - displayy / 5; x_end = cardinalX + rectwidth; y_end = cardinalY + rectheight; temp = rectheight + betweenrect; myHistogramThread = new HistogramThread(this); paint.setAntiAlias(true); paint.setColor(Color.BLUE); System.out.println("构造完成"); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas);// mCanvas = canvas;// myHistogramThread.start();// System.out.println(canvas); for(int i=0; i<6; i++){ canvas.drawRect(cardinalX, cardinalY -= temp, x_end, y_end -= temp,paint); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }//这里加了sleep就不能显示 不加就可以 } } //这个方法是在HistogramThread 中调用的 现在没用启动它 启动之后跟上面加了sleep的效果一样 public void doDraw(){ System.out.println("Histogram--重绘--"+mCanvas); mCanvas.drawRect(cardinalX, cardinalY -= temp, x_end, y_end -= temp,paint); System.out.println(cardinalX+" "+cardinalY+" "+" "+x_end+" "+y_end); }}HistogramThread public class HistogramThread extends Thread{ Histogram father; // WelcomeView对象的引用 int sleepSpan = 100; // 休眠时间 boolean flag; // 线程执行标志位 // 构造器:初始化主要的成员变量 public HistogramThread(Histogram father) { this.father = father; this.flag = true; } // 方法:线程执行方法 public void run() { for(int i = 0; i < 6; i++){ System.out.println("Thread-------重绘"); father.doDraw(); // 重新绘制屏幕 } } }}感觉只要有线程在绘图里面就不能显示了 但是绘图的方法还是会执行的 就是显示不出来 画一次重绘一次才会有效果- -~你只是画却没有重绘当然不行咯,另外这代码真是一团乱,既然是线程,又怎么会直接调用run()方法,这是违背java机制的……,直接调用run(),不是意味着在主线程中执行这个方法么?何来另起线程一说,这样根本无法让线程sleep嘛。给你改了一下,没做测试,自己试试吧package com.android.et_billing;import android.annotation.SuppressLint;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.os.Handler;import android.os.Message;import android.util.DisplayMetrics;import android.view.View;public class Histogram extends View implements Runnable{ private int displayw = 0; private int displayy = 0; private static int cardinalX = 0; // 第一个矩形X轴基点 private static int cardinalY = 0; // 第一个矩形Y轴基点 private static int rectwidth = 30; // 矩形宽 private static int rectheight = 15; // 矩形高 private static int betweenrect = 2; int x_end, y_end, temp; Paint paint = new Paint(); boolean flag = true; Canvas mCanvas; public Histogram(Context context) { super(context); displayw = dm.widthPixels; displayy = dm.heightPixels; cardinalX = displayw - displayw / 5; cardinalY = displayy - displayy / 5; x_end = cardinalX + rectwidth; y_end = cardinalY + rectheight; temp = rectheight + betweenrect; paint.setAntiAlias(true); paint.setColor(Color.BLUE); new Thread(this).start(); //启动线程,系统会自动调用run()方法,这样做才能使线程休眠 // TODO Auto-generated constructor stub } @SuppressLint("DrawAllocation") @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); mCanvas = canvas; } Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); } }; @Override public void run() { // TODO Auto-generated method stub for(int i = 0; i < 6; i++){ mCanvas.drawRect(cardinalX, cardinalY -= temp, x_end, y_end -= temp,paint);// invalidate();//错误重绘,这个方法只能在主线程中执行,要用他的话,就通过mHandler来与主线程通信吧 postInvalidate(); //重绘画布,使用post方法,可以不用传到主线程中去更新界面 //注意:重绘画布,系统会调用onDraw(Canvas canvas)方法,所以你刚刚在onDraw()调用run()是不行的,重绘时会进入死循环 try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }} 上面7楼的也不行啊 这样的话mCanvas就没有值了 是空的 我改成这样的也不行package com.zou.test;import android.annotation.SuppressLint;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.os.Handler;import android.os.Message;import android.util.DisplayMetrics;import android.view.View;public class Histogram extends View implements Runnable { private int displayw = 0; private int displayy = 0; private static int cardinalX = 0; // 第一个矩形X轴基点 private static int cardinalY = 0; // 第一个矩形Y轴基点 private static int rectwidth = 30; // 矩形宽 private static int rectheight = 15; // 矩形高 private static int betweenrect = 2; int x_end, y_end, temp; Paint paint = new Paint(); boolean flag = true; Canvas mCanvas; public Histogram(Context context) { super(context); DisplayMetrics dm = MainActivity.getdm(); displayw = dm.widthPixels; displayy = dm.heightPixels; cardinalX = displayw - displayw / 5; cardinalY = displayy - displayy / 5; x_end = cardinalX + rectwidth; y_end = cardinalY + rectheight; temp = rectheight + betweenrect; paint.setAntiAlias(true); paint.setColor(Color.BLUE); System.out.println("构造完成"); // TODO Auto-generated constructor stub } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); mCanvas = canvas; System.out.println("onDraw "+canvas+" "+mCanvas); } public void startThread(){ new Thread(Histogram.this).start(); // 启动线程,系统会自动调用run()方法,这样做才能使线程休眠 } Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); switch (msg.what) { case 0x01: { // 注意:重绘画布,系统会调用onDraw(Canvas // canvas)方法,所以你刚刚在onDraw()调用run()是不行的,重绘时会进入死循环 invalidate();// 错误重绘,这个方法只能在主线程中执行,要用他的话,就通过mHandler来与主线程通信吧 postInvalidate(); //重绘画布,使用post方法,可以不用传到主线程中去更新界面 System.out.println("绘图"+mCanvas); mCanvas.drawRect(cardinalX, cardinalY -= temp, x_end,y_end -= temp, paint); // postInvalidate(); //重绘画布,使用post方法,可以不用传到主线程中去更新界面 } break; } } }; @Override public void run() { // TODO Auto-generated method stub for (int i = 0; i < 6; i++) { mHandler.sendEmptyMessageDelayed(0x01,i*2000); } }}然后在MainActivity里面实例化这个对象后调用了startThread() 也不行 上面的写错了一点 invalidate();// 错误重绘,这个方法只能在主线程中执行,要用他的话,就通过mHandler来与主线程通信吧 postInvalidate(); //重绘画布,使用post方法,可以不用传到主线程中去更新界面只调用了invalidate()这个 Android读取zip包中图片,并显示的View [求助]关于box2d引擎 imgage.setImageBitmap((position&1)==1? micon1:micon2);这句话什么意思 使用sensor出现android runtime错误 avd manage无法获取package,怎么办 android 版本升级 发这样的短信的程序如何实现? 如何删除短信 想通过反射动态生成一个列表,结果失败了,求高手 AsyncHttpClient 上传两个以上文件出错 急! android 怎样播放 rtmp 视频流 android读取pdf文件,有包吗?
用一个for循环
int t = 当前时间;
for(int i = 0; i < 6; i++){
sendMessageDelayed(Message,t + i *100);}
这样就能依次延时100毫秒发消息,而且在UI线程。
然后那边handleMessage里面调用mCanvas.drawRect(),全部在UI线程做试试。希望我的回答能给楼主帮助。
import java.util.Calendar;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.view.View;public class Histogram extends View implements Runnable{ private int displayw = 0;
private int displayy = 0;
private static int cardinalX = 0; // 第一个矩形X轴基点
private static int cardinalY = 0; // 第一个矩形Y轴基点
private static int rectwidth = 30; // 矩形宽
private static int rectheight = 15; // 矩形高
private static int betweenrect = 2;
int x_end, y_end, temp;
Paint paint = new Paint();
boolean flag = true;
Canvas mCanvas; public Histogram(Context context) {
super(context);
DisplayMetrics dm = MainActivity.getdm();
displayw = dm.widthPixels;
displayy = dm.heightPixels;
cardinalX = displayw - displayw / 5;
cardinalY = displayy - displayy / 5;
x_end = cardinalX + rectwidth;
y_end = cardinalY + rectheight;
temp = rectheight + betweenrect;
paint.setAntiAlias(true);
paint.setColor(Color.BLUE);
// TODO Auto-generated constructor stub
} @SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
mCanvas = canvas;
this.run();
} Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch(msg.what){
case 0x01:{
mCanvas.drawRect(cardinalX, cardinalY -= temp, x_end, y_end -= temp,paint);
System.out.println(" "+mCanvas);
}break;
}
}
}; @Override
public void run() {
// TODO Auto-generated method stub
for(int i = 0; i < 6; i++){
mHandler.sendEmptyMessageDelayed(0x01,i*1000);
}
}}但是直接就看不到效果了 什么都没画出来 不过下面的System能正常的延时打印
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
mCanvas = canvas; // Don't do this !!!
this.run();
}If you want to use the canvas elsewhere,
extends your class from SurfaceView.
MainActivityimport android.app.Activity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;public class MainActivity extends Activity {
private static DisplayMetrics dm = new DisplayMetrics();
private Histogram mHistogram; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); //覆盖父类的onCreate方法
getWindowManager().getDefaultDisplay().getMetrics(dm);
ViewGroup viewGroup=(ViewGroup)getLayoutInflater().inflate(R.layout.activity_main,null);
mHistogram = new Histogram(this); //将画布放置在两个按键下面
viewGroup.addView(mHistogram,new LayoutParams(LayoutParams.FILL_PARENT,dm.heightPixels));
setContentView(viewGroup);
}
public static DisplayMetrics getdm(){
return dm;
}}package com.zou.test;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.DisplayMetrics;
import android.view.View;public class Histogram extends View{ private int displayw = 0;
private int displayy = 0;
private static int cardinalX = 0; // 第一个矩形X轴基点
private static int cardinalY = 0; // 第一个矩形Y轴基点
private static int rectwidth = 30; // 矩形宽
private static int rectheight = 15; // 矩形高
private static int betweenrect = 2;
int x_end, y_end, temp;
Paint paint = new Paint();
boolean flag = true;
Canvas mCanvas;
HistogramThread myHistogramThread = null; public Histogram(Context context) {
super(context);
DisplayMetrics dm = MainActivity.getdm();
displayw = dm.widthPixels;
displayy = dm.heightPixels;
cardinalX = displayw - displayw / 5;
cardinalY = displayy - displayy / 5;
x_end = cardinalX + rectwidth;
y_end = cardinalY + rectheight;
temp = rectheight + betweenrect;
myHistogramThread = new HistogramThread(this);
paint.setAntiAlias(true);
paint.setColor(Color.BLUE);
System.out.println("构造完成");
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// mCanvas = canvas;
// myHistogramThread.start();
// System.out.println(canvas);
for(int i=0; i<6; i++){
canvas.drawRect(cardinalX, cardinalY -= temp, x_end, y_end -= temp,paint);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}//这里加了sleep就不能显示 不加就可以
}
}
//这个方法是在HistogramThread 中调用的 现在没用启动它 启动之后跟上面加了sleep的效果一样
public void doDraw(){
System.out.println("Histogram--重绘--"+mCanvas);
mCanvas.drawRect(cardinalX, cardinalY -= temp, x_end, y_end -= temp,paint);
System.out.println(cardinalX+" "+cardinalY+" "+" "+x_end+" "+y_end);
}
}
HistogramThread public class HistogramThread extends Thread{ Histogram father; // WelcomeView对象的引用
int sleepSpan = 100; // 休眠时间
boolean flag; // 线程执行标志位
// 构造器:初始化主要的成员变量
public HistogramThread(Histogram father) {
this.father = father;
this.flag = true;
}
// 方法:线程执行方法
public void run() {
for(int i = 0; i < 6; i++){
System.out.println("Thread-------重绘");
father.doDraw(); // 重新绘制屏幕 }
}
}
}
感觉只要有线程在绘图里面就不能显示了 但是绘图的方法还是会执行的 就是显示不出来
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.view.View;public class Histogram extends View implements Runnable{ private int displayw = 0;
private int displayy = 0;
private static int cardinalX = 0; // 第一个矩形X轴基点
private static int cardinalY = 0; // 第一个矩形Y轴基点
private static int rectwidth = 30; // 矩形宽
private static int rectheight = 15; // 矩形高
private static int betweenrect = 2;
int x_end, y_end, temp;
Paint paint = new Paint();
boolean flag = true;
Canvas mCanvas; public Histogram(Context context) {
super(context);
displayw = dm.widthPixels;
displayy = dm.heightPixels;
cardinalX = displayw - displayw / 5;
cardinalY = displayy - displayy / 5;
x_end = cardinalX + rectwidth;
y_end = cardinalY + rectheight;
temp = rectheight + betweenrect;
paint.setAntiAlias(true);
paint.setColor(Color.BLUE);
new Thread(this).start(); //启动线程,系统会自动调用run()方法,这样做才能使线程休眠
// TODO Auto-generated constructor stub
} @SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
mCanvas = canvas;
} Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
}
}; @Override
public void run() {
// TODO Auto-generated method stub
for(int i = 0; i < 6; i++){
mCanvas.drawRect(cardinalX, cardinalY -= temp, x_end, y_end -= temp,paint);
// invalidate();//错误重绘,这个方法只能在主线程中执行,要用他的话,就通过mHandler来与主线程通信吧
postInvalidate(); //重绘画布,使用post方法,可以不用传到主线程中去更新界面
//注意:重绘画布,系统会调用onDraw(Canvas canvas)方法,所以你刚刚在onDraw()调用run()是不行的,重绘时会进入死循环
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}}
package com.zou.test;import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.util.DisplayMetrics;
import android.view.View;public class Histogram extends View implements Runnable { private int displayw = 0;
private int displayy = 0;
private static int cardinalX = 0; // 第一个矩形X轴基点
private static int cardinalY = 0; // 第一个矩形Y轴基点
private static int rectwidth = 30; // 矩形宽
private static int rectheight = 15; // 矩形高
private static int betweenrect = 2;
int x_end, y_end, temp;
Paint paint = new Paint();
boolean flag = true;
Canvas mCanvas; public Histogram(Context context) {
super(context); DisplayMetrics dm = MainActivity.getdm();
displayw = dm.widthPixels;
displayy = dm.heightPixels;
cardinalX = displayw - displayw / 5;
cardinalY = displayy - displayy / 5;
x_end = cardinalX + rectwidth;
y_end = cardinalY + rectheight;
temp = rectheight + betweenrect;
paint.setAntiAlias(true);
paint.setColor(Color.BLUE);
System.out.println("构造完成"); // TODO Auto-generated constructor stub
} @Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
mCanvas = canvas;
System.out.println("onDraw "+canvas+" "+mCanvas);
}
public void startThread(){
new Thread(Histogram.this).start(); // 启动线程,系统会自动调用run()方法,这样做才能使线程休眠
} Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch (msg.what) {
case 0x01: {
// 注意:重绘画布,系统会调用onDraw(Canvas
// canvas)方法,所以你刚刚在onDraw()调用run()是不行的,重绘时会进入死循环
invalidate();// 错误重绘,这个方法只能在主线程中执行,要用他的话,就通过mHandler来与主线程通信吧
postInvalidate(); //重绘画布,使用post方法,可以不用传到主线程中去更新界面
System.out.println("绘图"+mCanvas);
mCanvas.drawRect(cardinalX, cardinalY -= temp, x_end,y_end -= temp, paint);
// postInvalidate(); //重绘画布,使用post方法,可以不用传到主线程中去更新界面
}
break;
}
}
}; @Override
public void run() {
// TODO Auto-generated method stub for (int i = 0; i < 6; i++) {
mHandler.sendEmptyMessageDelayed(0x01,i*2000);
}
}}
然后在MainActivity里面实例化这个对象后调用了startThread() 也不行
postInvalidate(); //重绘画布,使用post方法,可以不用传到主线程中去更新界面
只调用了invalidate()这个