570 likes | 767 Views
第 10 章 动画和图像动态显示. 【 学习内容与要点 】 本章介绍图像动画及图像动态显示的程序设计技术和技巧。重点掌握: 图像动画设计技术 图像的动态显示技术. 10.1 动画设计. 将屏幕上显示的画面或者画面的一部分,能按照一定的规则或要求在屏幕上移动的技术,称为动画技术。在屏幕上实现动画有三种方式: ( 1 ) 位置不动,形态变化。 ( 2 ) 形态不变,位置变化。 ( 3 ) 位置和形态均变化。
E N D
第10章 动画和图像动态显示 【学习内容与要点】 本章介绍图像动画及图像动态显示的程序设计技术和技巧。重点掌握: 图像动画设计技术 图像的动态显示技术
10.1 动画设计 • 将屏幕上显示的画面或者画面的一部分,能按照一定的规则或要求在屏幕上移动的技术,称为动画技术。在屏幕上实现动画有三种方式: • (1) 位置不动,形态变化。 • (2) 形态不变,位置变化。 • (3) 位置和形态均变化。 • 动画制作有许多方法, 这里使用图片对象数组,把一系列动作连续的图像保存在内存中来实现图像的快速变换。这样做有许多好处, 不必用包含多个图形框或图像控件的窗体。
10.1.1位置不动、形态变化的动画 • [例10-1] 位置不动、形态变化的动画 • 1.界面设计 • 项目界面设计如图10-1所示。在窗体上设置5个图片框PictureBox1~5,利用PictureBox的Image属性在PictureBox2~5中各输入一幅不同形态的小熊猫的图像。另外,在窗体上设置一个Button按钮和一个Timer控件。
上述设置完毕后,用鼠标缩小窗体,隐藏PictuerBox2~PictuerBox5,如图10-2所示。上述设置完毕后,用鼠标缩小窗体,隐藏PictuerBox2~PictuerBox5,如图10-2所示。
2.程序设计 • 程序设计如下: • int num; array< Bitmap^>^box; private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { • Bitmap^box2 =gcnew Bitmap(pictureBox2->Image ); • Bitmap^box3 =gcnew Bitmap(pictureBox3->Image ); • Bitmap^box4 =gcnew Bitmap(pictureBox4->Image ); • Bitmap^box5 =gcnew Bitmap(pictureBox5->Image ); • box[1]=box2; box[2]=box3;box[3]=box4;box[4]=box5; • this->timer1->Enabled=true; • this->pictureBox1->Image=box[2]; • }
private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e) { • if (num< 5) • { • this->pictureBox1->Image=box[num]; • num=num+1;} • else • num=1; • }
程序运行后,单击“动画”按钮,可以看到一个小熊猫在运动,如图10-3所示。程序运行后,单击“动画”按钮,可以看到一个小熊猫在运动,如图10-3所示。
10.1.2位置和形态变化的动画 • [例10-2] 位置和形态变化的动画 • 界面设计 • 界面设计如图10-4所示。在窗体上设置7个图片框PictureBox17,利用PictureBox的Image属性在PictureBox1PictureBox7中各输入一幅不同形态的图像。在窗体中加入一个timer控件。
程序设计 • 程序代码如下 • int num; • array< Bitmap^>^box; • private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { • Bitmap box1 =new Bitmap(pictureBox1.Image ); • Bitmap box2 =new Bitmap(pictureBox2.Image ); • Bitmap box3 =new Bitmap(pictureBox3.Image ); • Bitmap box4 =new Bitmap(pictureBox4.Image ); • Bitmap box5=new Bitmap(pictureBox5.Image ); • Bitmap box6 =nw Bitmap(pictureBox6.Image ); • Bitmape box7 =new Bitmap(pictureBox7.Image ); • box[0]=box1; box[1]=box2; box[2]=box3; box[3]=box4; • box[4]=box5; box[5]=box6; box[6]=box7; • timer1.Enabled=true; • }
private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e) { • if (num< 7) • { • pictureBox1->Image=box[num]; • num=num+1;} • else • num=0; • if (pictureBox1->Left<-100 ) • pictureBox1->Left=500; • else • pictureBox1->Left=pictureBox1->Left -10; • } • private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { • box= gcnew array<Bitmap^>(7); • }
运行结果 • 程序运行后,可以看到一个骏马在循环运动。改变Timer控件的interval属性值的大小,运动速度随值的改变而变化。如图10-5所示。
10.1.3 形态不变、位置变化的动画 • 【例10-3】建立一个形态不变、位置变化的动画项目。 • 界面设计如下。 • (1)将Timer控件加入到项目界面。 • (2)在窗体上加入一个PictureBox控件并用其Image属性加在一幅GIF图像。如图10-6所示。
Point p; • private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e) { • if( p.X > this->Location.X + 100) • { p.X = 0;} • if (p.Y > this->Location.Y + 100) { • p.Y = 0; • } • p.X = p.X + 6; • p.Y = p.Y + 10; • this->pictureBox1->Location = p; • } • }; • }
10.1.4 图形动画 • [例10-4] 小球运动 • 界面设计如图10-8所示。
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { • int i; • double pi,g; • double x,y,x1,y1; • pi=3.1415926; • g=0.98; • Graphics^ g1; • g1= this->CreateGraphics(); • Pen^ p1 =gcnew Pen(System::Drawing::Color::Red); • x=0; • y=150; • for (i=0;i<8;i++)
{ • for(pi=0;pi<8*3.13;pi=pi+0.02) • { p1->Color =Color::Red ; • p1->Width = 2.0F; • y=100*(Math::Sin(pi)); • x=pi*10; • g1->DrawEllipse (p1,x,y+100,50,50); • for(x=0;x<1000000;x+=10); • y=100*(Math::Sin (pi-0.02)); • x=pi*10; • p1->Color=this->BackColor ; • g1->DrawEllipse (p1,x,y+100,50,50); • } • y=y*0.6; • } • delete p1;delete g1; } • };
10.2 图像的动态显示 • 所谓图像的动态显示,系指图像以某种方式徐徐切入界面。实现图像的动态显示的方法很多,本节只作简单的介绍。
10.2.1 利用Graphics.DrawImage 方法 • 第3章介绍了Graphics.DrawImage 方法的基本使用方法,这里用具体实例来说明Graphics.DrawImage 方法在实现图像的动态显示方面的应用。
1.界面设计 • 如图10-10所示。 在窗体上添加两个pictureBox控件和相应几个按钮如图设计其标题属性。
2。程序设计 • (1)左到右拉伸效果 • 图片框1中输入的图像以左到右拉伸方式动态显示到图片框2中。程序设计如下。 • private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { • int x,y, pw, ph ; • Graphics^g1=pictureBox2->CreateGraphics(); • Bitmap^box1 =gcnew Bitmap(this->pictureBox1->Image); • //把图片框中的图片给一个bitmap 类型 • Bitmap^box2 =gcnew Bitmap(this->pictureBox2->Image); • pw =this->pictureBox1->Width; • ph =this->pictureBox1->Height; • for (x=0; x<=pw;x++) • { g1->DrawImage (box1,0,0,x,ph); • } }
中间向四周扩散效果 • 图片框1中输入的图像以中间向四周扩散的方式动态显示到图片框2中。程序设计如下。 • private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { • int x,y, pw, ph ; • Graphics^g1=pictureBox2->CreateGraphics(); • Bitmap^box1 =gcnew Bitmap(this->pictureBox1->Image); • Bitmap^box2 =gcnew Bitmap(this->pictureBox2->Image); pw =this->pictureBox1->Width; • ph =this->pictureBox1->Height; • for(x=0;x<120;x++) • {Rectangle destRect =Rectangle( pw/2-x,ph/2-x,2*x,2*x);//目地图像 • Rectangle srcRect =Rectangle(0,0,pw,ph );//取原图像 • GraphicsUnit units = GraphicsUnit::Pixel; • g1->DrawImage(box1, destRect, srcRect, units); • } • }
旋转效果 • 图片框1中输入的图像以旋转方式动态显示到图片框2中。程序设计如下。 • private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { int x,y, pw, ph ; • Graphics^g1=pictureBox2->CreateGraphics(); • Bitmap^box1 =gcnew Bitmap(this->pictureBox1->Image); • Bitmap^box2 =gcnew Bitmap(this->pictureBox2->Image); pw =this->pictureBox1->Width; • ph =this->pictureBox1->Height; • for(x=-100;x<120;x++) • {Rectangle destRect =Rectangle( 0,ph/2-x,pw,2*x);//目地图像 • Rectangle srcRect =Rectangle(0,0,pw,ph );//取原图像 • GraphicsUnit units = GraphicsUnit::Pixel; • g1->DrawImage(box1, destRect, srcRect, units); • } }
(5)中间向两边拉伸效果 • 图片框1中输入的图像以中间向两边拉伸的方式动态显示到图片框2中。程序设计如下。 • private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { int x,y, pw, ph ; • Graphics^g1=pictureBox2->CreateGraphics(); • Bitmap^box1 =gcnew Bitmap(this->pictureBox1->Image); • Bitmap^box2 =gcnew Bitmap(this->pictureBox2->Image); • pw =this->pictureBox1->Width; • ph =this->pictureBox1->Height; • for(x=0;x<110;x++) • {Rectangle destRect =Rectangle( 0,ph/2-x,pw,2*x); • Rectangle srcRect =Rectangle(0,0,pw,ph ); • GraphicsUnit units = GraphicsUnit::Pixel; • g1->DrawImage(box1, destRect, srcRect, units); • } }
[例10-4]幻灯片切换效果 • 项目界面设计 • 建立一新窗体,在窗体上添加5个pictureBox控件用image属性加载图像,设pictureBox2~pictureBox5的visible属性False,添加Button控件并将其Caption属性改为“动态显示”。窗体如图10-11所示。
2 程序设计 • private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { int x,i, pw, ph ; • Graphics^g1=pictureBox1->CreateGraphics(); • Color^c=gcnew Color (); • Bitmap^box1 =gcnew Bitmap(this->pictureBox1->Image); //把图片框中的图片给一个bitmap 类型 • array< Bitmap^>^bit= gcnew array<Bitmap^>(5);//建立一图片数组 • bit[0]=gcnew Bitmap( pictureBox1->Image) ; //以下为图片数组存入图片 • bit[1]=gcnew Bitmap (pictureBox2->Image) ; • bit[2]=gcnew Bitmap (pictureBox3->Image) ; • bit[3]=gcnew Bitmap (pictureBox4->Image) ; • bit[4]=gcnew Bitmap (pictureBox5->Image) ;
pw =this->pictureBox1->Width+50 ; • ph =this->pictureBox1->Height+50 ; • for (i=1;i<5;i++) • { • for (x=0; x<=ph;x++) • { • g1->DrawImage (bit[i-1],x,x,pw-x,ph-x); //用DrawImage把图片缩小 • g1->DrawImage (bit[i],0,0,x,x);//用DrawImage把图片放大 • } • } • }
10.2.2 像素编程法 • [例10-4] 图像动态显示 • 1.界面设计 • 本例界面设计如图10-13所示。在窗体上设置两个PictureBox、一个打开文件通用对话框和两个命令按钮。两个命令按钮中一个用于在PictureBox1内输入图像,一个为切换动作按钮。在PictuerBox2中预先输入一幅图像。
(1)输入图像 • 在PictureBox1输入一幅图像。程序设计如下: • private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { • OpenFileDialog^ openFileDialog1 = gcnew OpenFileDialog; • openFileDialog1->FilterIndex = 2; • openFileDialog1->RestoreDirectory = true; • openFileDialog1->Filter= "Bmp File(*.bmp)|*.bmp"; • if ( openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK && openFileDialog1->FileName->Length > 0 ) • { • pictureBox1->Load(openFileDialog1->FileName); • } • }
(2)上下对接 • 图片框1中输入的图像从图片框2的上部和下部进入进行对接并显示在图片框2中。程序设计如下: • private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { Color^c=gcnew Color (); Bitmap^box1 =gcnew Bitmap(this->pictureBox1->Image); Bitmap^box2 =gcnew Bitmap(this->pictureBox2->Image); • int r,g,b,x,i; x = 0; • while(x <= pictureBox1->Height /2) • { • for (i=0 ; i<=pictureBox1->Width - 1;i+=1) • { • c=box1->GetPixel(i,x); • r=c->R; • g=c->G; • b=c->B
Color c1= Color::FromArgb(r,g,b) ; • box2->SetPixel (i,x,c1); • } • for (i=0 ; i<=pictureBox1->Width - 1;i+=1) • {c=box1->GetPixel(i,pictureBox1->Height - 1-x); • r=c->R; • g=c->G; • b=c->B; • Color c1= Color::FromArgb(r,g,b) ; • box2->SetPixel (i,pictureBox1->Height - 1-x,c1); • } • x = x + 1; • pictureBox2->Refresh(); //刷新 • pictureBox2->Image=box2; } • }
(3) 左右对接 • 图片框1中输入的图像从图片框2的左侧和右侧进入进行对接并显示在图片框2中。程序设计如下: • private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { • Color^c=gcnew Color (); • Bitmap^box1 =gcnew Bitmap(this->pictureBox1->Image); • Bitmap^box2 =gcnew Bitmap(this->pictureBox2->Image); • int rr,gg,bb,x,i; • x = 0; • while(x <= pictureBox1->Width /2) • { • for (i=0 ; i<=pictureBox1->Height- 1;i+=1) • { • c=box1->GetPixel(x,i); • rr=c->R; • gg=c->G; • bb=c->B;
Color c1= Color::FromArgb(rr,gg,bb) ; • box2->SetPixel (x,i,c1); • } • for (i=0 ; i<=pictureBox1->Height- 1;i+=1) • { • c=box1->GetPixel(pictureBox1->Width - 1-x,i); • rr=c->R; • gg=c->G; • bb=c->B; • Color c1= Color::FromArgb(rr,gg,bb) ; • box2->SetPixel (pictureBox1->Width - 1-x,i,c1); • } • x = x + 1; • pictureBox2->Refresh(); //刷新 • pictureBox2->Image=box2; } • }
10.3 设计范例与练习题 • 【1】使用DrawImage实现动画 • 界面设计如图10-14所示。
代码设计如下. • private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { • int x,i, pw, ph ; • Graphics^g1=pictureBox1->CreateGraphics(); • Color^c=gcnew Color (); • Bitmap^box1 =gcnew Bitmap(this->pictureBox1->Image); array< Bitmap^>^bit= gcnew array<Bitmap^>(5);//建立一图片数组 • bit[0]=gcnew Bitmap( pictureBox1->Image) ; • bit[1]=gcnew Bitmap (pictureBox2->Image) ; • bit[2]=gcnew Bitmap (pictureBox3->Image) ; • bit[3]=gcnew Bitmap (pictureBox4->Image) ; • bit[4]=gcnew Bitmap (pictureBox5->Image)
pw =this->pictureBox1->Width+50 ; • ph =this->pictureBox1->Height+50 ; • for (i=1;i<5;i++) • { • for (x=0; x<=pw/2;x++) • { • RectangleF destRect =RectangleF( 0, 0, pw/2+x, ph); • RectangleF srcRect =RectangleF( pw/2-x, 0, pw, ph); • GraphicsUnit units = GraphicsUnit::Pixel; • g1->DrawImage (bit[i],destRect, srcRect, units); • } • if (i<4) • g1->Clear (Color::White); • } • } • 程序运行后,图片从左向右进入界面。
【3】图形动画 • 界面设计如图10-15所示。
程序设计如下。 • private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { • timer1->Interval = 100; • timer1->Enabled = true; • } • private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e) { • Graphics ^ g; • g = pictureBox1->CreateGraphics(); • Pen^ pen = gcnew Pen( Color::Black); • Pen^ pen1 = gcnew Pen(Color::Red); • Pen^ pen2 = gcnew Pen(Color::Blue); • Pen^ pen3 = gcnew Pen(Color::Green); • g->DrawLine(pen,0,100,600,100);
if (x>=600) • x=0; • m=n%3; • switch (m) • { • case 0: • g->Clear(Color::LightYellow); • g->DrawLine(pen,0,100,600,100); • g->DrawEllipse(pen1,x,50,50,50); • break; • case 1: • //g->Clear(Color::LightYellow); • g->DrawLine(pen,0,100,600,100); • g->DrawEllipse(pen2,x,50,50,50); • break;
case 2: • //g->Clear(Color::LightYellow); • g->DrawLine(pen,0,100,600,100); • g->DrawEllipse(pen3,x,50,50,50); • break; • } • x++; • n++; • } • }; • }
程序运行后,单击“动画”按钮,如图10-16所示,小环徐徐从左向右滚动。程序运行后,单击“动画”按钮,如图10-16所示,小环徐徐从左向右滚动。 图10-16 图形动画
【4】时钟 • 设计如图10-17所示。
private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e) { • Graphics^g; • g=this->pictureBox1->CreateGraphics(); • this->pictureBox1->Refresh(); • Pen^p1 =gcnew Pen(Color::Black); • p1->Width=8.0; • Pen^p2 =gcnew Pen(Color::Black); • p2->Width=5.0; • Pen^ p3 =gcnew Pen(Color::Red); • p3->Width=3.0; • String^ t; • double x1, x2, x3; • double ss, hh, mm; • int x, y, a1, b1, a2, b2, a3, b3; • x = pictureBox1->Width; • y = pictureBox1->Height;
label1->Text =System::DateTime::Now.ToLongTimeString(); • t = label1->Text; • ss = double::Parse(t->Substring(t->Length - 2, 2)); • mm = double::Parse(t->Substring(t->Length - 5, 2)); • if (t->Length == 7) • { • hh = double::Parse(t->Substring(0, 1)); • } • else • { • hh = double::Parse(t->Substring(0, 2)); • } • x1 = -90 + ss * 6; • x2 = -90 + ((mm + ss / 60) * 6); • x3 = -90 + ((hh + mm / 60) * 30);