对一个CanVas的操作是否可以实现“多线程”(100分)

  • 主题发起人 主题发起人 atop
  • 开始时间 开始时间
A

atop

Unregistered / Unconfirmed
GUEST, unregistred user!
用多线程在一个CANVAS上操作图象特技,需要临界区的锁定。是不是意味着在一个
CANVAS上就不可能实现“多线程”。我是想在一个CANVAS上同时出现两个或多个以上的
图片特技效果,是不是不可能?
有没有这种可能:CANVAS的锁定,可以对CANVAS上的某一区域进行锁定,其他区域其
他线程可以对其操作?
有没有其他方法。(因为图象、区域、出现时间都是可变参数,用一个TIMER好象
太麻烦)
如果能提供更多的图象特技方法 将不胜感谢。
 
没有可能,如果你追求稳定的话。你为什么不多建几个CANVAS呢,设置其背景为透明行不行?
这样可以一个线程单独管理一个canvas。
 
我在做LED排版、播放程序。等待设计好的文件进行播放,文字很快,如果是图片特技
时间就长了,所以考虑多线程。
"only you" 兄提出的方法不失为一种方法。
 
是可以的,我有一个例子:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Menus;
type
TForm1 = class(TForm)
MainMenu1: TMainMenu;
Options1: TMenuItem;
AddThread1: TMenuItem;
RemoveThread1: TMenuItem;
RemoveAll1: TMenuItem;
ColorDialog1: TColorDialog;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure RemoveAll1Click(Sender: TObject);
procedure AddThread1Click(Sender: TObject);
procedure RemoveThread1Click(Sender: TObject);
private
{ Private declarations }
ThreadList:TList;
public
{ Public declarations }
end;
TDrawThread=class(TThread)
private
FColor:TColor;
FForm:TForm;
public
Constructor Create(AForm:TForm;AColor:TColor);
procedure Execute;override;
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
Constructor TDrawThread.Create(AForm:TForm;AColor:TColor);
begin
FColor:=AColor;
FForm:=AForm;
inherited Create(False);
end;

procedure TDrawThread.Execute;
var
P1,P2:TPoint;
procedure GetRandCoords;
var
Maxx,Maxy:Integer;
begin
Maxx:=FForm.ClientWidth;
Maxy:=FForm.ClientHeight;
P1.x:=Random(Maxx);
P1.y:=Random(Maxy);
P2.x:=Random(Maxx);
P2.y:=Random(Maxy);
end;
begin
FreeonTerminate:=True;
while not(Terminated or Application.Terminated)do
begin
GetRandCoords;
with FForm.Canvasdo
begin
Lock;
Pen.Color:=FColor;
MoveTo(P1.x,P1.y);
LineTo(P2.x,P2.y);
UnLock;
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
ThreadList := TList.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
RemoveAll1Click(nil);
ThreadList.Free;
end;

procedure TForm1.RemoveAll1Click(Sender: TObject);
var
I:integer;
begin
Cursor:=crHourGlass;
try
for I:= ThreadList.Count -1do
wnto 0do
begin
TDrawThread(ThreadList).Terminate;
TDrawThread(ThreadList).WaitFor;
end;
ThreadList.Clear;
finally
Cursor:=crDefault;
end;
end;

procedure TForm1.AddThread1Click(Sender: TObject);
begin
if ColorDialog1.Execute then
ThreadList.Add(TDrawThread.Create(Self,ColorDialog1.Color))
end;

procedure TForm1.RemoveThread1Click(Sender: TObject);
begin
TDrawThread(ThreadList[ThreadList.Count -1]).Terminate;
ThreadList.Delete(ThreadList.Count -1);
end;

initialization
Randomize;
end.
 
以上说明对同一个Canvas可以用多线程进行操作
 
canvas本来就是thread-safe的。
 
可以的!canvas类本身就有一个lock属性,专为多线程设计的!
具体你可以查一查canvas类的说明!
 
不是LOCK属性是LOCK/UNLOCK方法
 
你说你是想在一个CANVAS上同时出现两个或多个以上的
图片特技效果,那根本不用多线程,看看下面的代码,我用来实现下雪特级的动画
具体代吗到http://mypage.xueyou.com/~codehunter上下载
/*★★★★★★★★★★★★★★★★
★ copyright codehunter 2001★
★ 名字:杨华 ★
★E-Mail:codehunter@sohu.com★
★★★★★★★★★★★★★★★★*/
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <stdlib.h>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
//设置窗口画布的画刷为透明
this->Canvas->Brush->Style=bsClear;
//设置窗口客户区的大小为图片大小
this->ClientWidth=Image1->Width;
this->ClientHeight=Image1->Height;
//设置定时器为30毫秒
Timer1->Interval=30;
//初始化雪花
InitSnows();
//初始化两个内存图片
ImgBK=new Graphics::TBitmap();
ImgBK->Assign(Image1->Picture->Graphic);
SrcImg=new Graphics::TBitmap();
SrcImg->Assign(Image1->Picture->Graphic);
//初始化字幕
StringList = new TStringList();
StringList->Add("★★★★★★★★★★★★★★★★");
StringList->Add("★★★要想人爱我必先我爱人★★★");
StringList->Add("★ copyright codehunter 2001 ★");
StringList->Add("★★★★★★★★★★★★★★★★");
StringList->Add("");
StringList->Add("可爱的丽丽");
StringList->Add("看到这个程序你开心吗");
StringList->Add("我想你一定很开心");
StringList->Add("因为这是我爱你的具体行动呀");
StringList->Add("虽然我没有什么美丽的玫瑰送给你");
StringList->Add("也没有精美的礼物送给你");
StringList->Add("我只能敲击键盘敲出漂亮的代码");
StringList->Add("敲出美丽的程序");
StringList->Add("用心去敲击");
StringList->Add("用心去做那似乎平淡的东西");
StringList->Add("但是其中却包含着最珍贵的东西");
StringList->Add("那就是");
StringList->Add("爱你");
StringList->Add("");
StringList->Add("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆");
StringList->Add("");
StringList->Add("不知道你想怎么补偿我对你所做的一切");
StringList->Add("也许你会说声谢谢你杨华");
StringList->Add("也许你会说杨华我喜欢你");
StringList->Add("但是这些我都不要");
StringList->Add("我只要你真心给我一个吻");
StringList->Add("心甘情愿的给我");
StringList->Add("");
StringList->Add("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆");
StringList->Add("");
StringList->Add("之所以选择雪");
StringList->Add("是因为洁白无暇的雪象征着");
StringList->Add("我和你纯洁的爱和真挚的友谊");
StringList->Add("难道不是吗丽丽");
StringList->Add("真的希望有一天");
StringList->Add("丽丽能像图片上那个女孩那样");
StringList->Add("依偎在心爱的人怀里");
StringList->Add("而那个人就是我");
StringList->Add("");
StringList->Add("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆");
StringList->Add("");
StringList->Add("但是现实总是残酷");
StringList->Add("我和你可能会因为种种原因");
StringList->Add("不能在一起");
StringList->Add("但是我不怕");
StringList->Add("我想我一定能吻你");
StringList->Add("而且我一定要吻你");
StringList->Add("并且要吻你250分钟");
StringList->Add("因为我定义的雪花总共有250朵");
StringList->Add("丽丽请答应我吻你的请求");
StringList->Add("完");
StringList->Add("");
StringList->Add("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆");
}
//---------------------------------------------------------------------------
//初始化雪花的函数
void TForm1::InitSnows()
{
randomize();
int temp;
for(int i=0;i<MAXSNOWS;i++)
{
snows.sp.x=rand()%this->Width;
snows.sp.y=-rand()%this->Height;
snows.ssize=rand()%MAXSNOWSIZE;
temp=rand()%255;
if(temp<230) temp=255;
snows.scolor=(TColor)RGB(temp,temp,temp);
}
}
//---------------------------------------------------------------------------
//画雪花的函数
void __fastcall TForm1::DrawSnows(TCanvas *DCanvas,snow p)
{
DCanvas->Brush->Color=p.scolor;
DCanvas->Pen->Style=psClear ;
DCanvas->Ellipse(p.sp.x,p.sp.y,p.sp.x+p.ssize,p.sp.y+p.ssize);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
this->Canvas->Draw(0,0,SrcImg);//将画好的帧画到窗口上
SrcImg->Canvas->Draw(0,0,ImgBK);//用背景重画帧
static int y=this->Height;
if(y<-750) y=this->Height;//字幕行数决定750这个值
y--;
DrawText(SrcImg->Canvas,SrcImg->Width,y);//将文本画在新的帧上
randomize();
int temp;
for(int i=0;i<MAXSNOWS;i++)
{
if(snows.sp.y>this->Height)
{
snows.sp.y=0;
snows.sp.x=rand()%this->Width;
}
snows.sp.y+=4;
temp=rand()%100;
if(temp<50)
snows.sp.x++;
else
snows.sp.x--;
DrawSnows(SrcImg->Canvas,snows);
}
}
//---------------------------------------------------------------------------
//显示字幕的函数
void __fastcall TForm1::DrawText(TCanvas *DCanvas,int x,int y)
{
DCanvas->Brush->Style =bsClear;
DCanvas->Font->Name="宋体";
DCanvas->Font->Size=9;
DCanvas->Font->Color=clWhite;
int dx;
x/=2;
TEXTMETRIC ReturnResults;
GetTextMetrics(DCanvas->Handle,&amp;ReturnResults);
for(int i=0;i< StringList->Count;i++)
{
y+=15;
if(y>40&amp;&amp;y<240)
{
dx=x-(ReturnResults.tmAveCharWidth*StringList->Strings.Length())/2;
DCanvas->TextOutA(dx,y,StringList->Strings);
}
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
//最后将申请的资源释放
delete ImgBK;
delete SrcImg;
delete StringList;
}
//end.
 
应该可以结束了
delphi自己的Thread例子。
 
后退
顶部