请教各位高手一个android 绘图和线程的问题

野狼孤 2012-08-31 11:23:06
先看代码 再说说我遇到的问题

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);

// 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);
}
};

@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);

try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

}


现在的问题是在程序运行起来后 屏幕上什么都没有 等到过了延时时间的总和后绘制的图像就一下全出来了 看不到延时的效果 好像是在延时的时候界面没办法显示 等0.1*6秒之后才能显示界面 怎么回事呢
...全文
240 12 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
野狼孤 2012-09-05
  • 打赏
  • 举报
回复
根据七楼的办法 还是搞定了 谢谢咯
野狼孤 2012-09-02
  • 打赏
  • 举报
回复
上面的写错了一点

invalidate();// 错误重绘,这个方法只能在主线程中执行,要用他的话,就通过mHandler来与主线程通信吧
postInvalidate(); //重绘画布,使用post方法,可以不用传到主线程中去更新界面


只调用了invalidate()这个
野狼孤 2012-09-02
  • 打赏
  • 举报
回复
上面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() 也不行
张和阳 2012-08-31
  • 打赏
  • 举报
回复
这样在子线程和主线程之间交互的问题还真有点复杂。我还不知道这个是怎么回事,我建议, 把那个runnable去掉,写个函数。
用一个for循环
int t = 当前时间;
for(int i = 0; i < 6; i++){
sendMessageDelayed(Message,t + i *100);

}
这样就能依次延时100毫秒发消息,而且在UI线程。
然后那边handleMessage里面调用mCanvas.drawRect(),全部在UI线程做试试。

希望我的回答能给楼主帮助。
独领风骚的猫 2012-08-31
  • 打赏
  • 举报
回复
楼主这代码写的真是。。。。!! 7楼的代码 有点意思了。。顶一下
流星叶雨 2012-08-31
  • 打赏
  • 举报
回复
画一次重绘一次才会有效果- -~你只是画却没有重绘当然不行咯,另外这代码真是一团乱,既然是线程,又怎么会直接调用run()方法,这是违背java机制的……,直接调用run(),不是意味着在主线程中执行这个方法么?何来另起线程一说,这样根本无法让线程sleep嘛。给你改了一下,没做测试,自己试试吧

package com.android.market_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();
}
}
}

}


野狼孤 2012-08-31
  • 打赏
  • 举报
回复
我把所有代码都贴出来吧
MainActivity

import 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(); // 重新绘制屏幕 }
}
}
}


感觉只要有线程在绘图里面就不能显示了 但是绘图的方法还是会执行的 就是显示不出来
coxfilur_2008 2012-08-31
  • 打赏
  • 举报
回复
@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.
张和阳 2012-08-31
  • 打赏
  • 举报
回复
这个VIEW implements Runnable我怎么感觉怪怪的。

试过把implements Runnable删掉,然后把run()换个名字在onDraw()里面调用吗?

仅是好奇
野狼孤 2012-08-31
  • 打赏
  • 举报
回复
按照楼上的意思 改正这样的

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能正常的延时打印
野狼孤 2012-08-31
  • 打赏
  • 举报
回复
我之前是没有现场的 直接在主程序中延时 也是这样的效果

80,471

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧