graphics - city university of new yorknatacha/teachspring_12/csc330/... · graphics gdi+ is the...
TRANSCRIPT
GraphicsGDI+ is the .NET Framework class library for graphical
programming.
It provides:
– Drawing surfaces—windows, bitmaps, printers
– Tools for 2-D drawing—shapes, polygons, curves, brushes, pens
– Text-drawing features
– Image and bitmap support—read, draw onto any surface, draw into image
– Print and print preview
– Ability to work with any kind of .NET application—WinFormor WebForm
Graphics
In order to draw on a surface, we need an object of type Graphics associated with the surface.
The Graphics object:
– "Encapsulates" the surface
– Provides the "device context" for the surface
– Preserves graphics state for the surface
– Provides methods for 2D drawing
Some methods of the Graphics object:
Clear DrawArc
DrawBezier DrawCurve
DrawPolygon DrawRectangle
DrawString FillClosedCurve
DrawElipse DrawIcon
FillElipse FillPath
DrawImage DrawLine
DrawPath DrawPie
FillPie FillPolygon
FillRectangle FillRegion
• To draw on a surface, we need the Graphics object for the surface.
• Graphics are not persistent, so we need to redraw the image if the surface becomes invalid.
• To redraw our picture, we can handle the Paint event of the form, OR
• To redraw our picture, we can override the virtual function OnPaint, which Form inherits from Control
• An ArrayList is a convenient place to store items that need to be redrawn.
Graphics
If your form contains controls such as buttons, textboxes, and labels:
The controls are redrawn Automatically when the form receives a Paint event.
In your Graphics program, you are only responsible for drawing symbol.
Graphics Examples
Graphics1Graphics2Graphics3Graphics4
Graphics1
Graphics1private void button1_Click(object sender, EventArgs e)
{
Graphics g = this.CreateGraphics();
Pen p = new Pen(Color.Blue, 5);
g.DrawRectangle(p, 10, 10, 250, 250);
p.Dispose(); //We should call Dispose since we created the Pen
g.Dispose(); //Graphics object
}
private void button2_Click(object sender, EventArgs e)
{
//Invalidate();
Invalidate(new Rectangle(0, 0, 100, 100));
}
Graphics1
Click button1 Click button2
Minimize & Maximize
Graphics2
Graphics2private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;//We don't create this so we won't call Dispose on it
Brush br = new LinearGradientBrush(new Point(10, 10), new Point(250, 250),
Color.Blue, Color.Red);
g.FillRectangle(br, 10, 10, 240, 240);
br.Dispose();
}
private void InitializeComponent()
{
…
this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);
}
Graphics2
load Click button1
Minimize & Maximize
Paint event
Conclusion:
Paint event is raised every time the form is redrawn.
Note:
This event is derived from class Control. So all controls has this event.
Add global variable and increment it in the paint event-handler.
Graphics3
Graphics3protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
Pen p = new Pen(Color.Red, 5);
g.DrawRectangle(p, 10, 10, 240, 240);
p.Dispose();
nPaints++;//Field (global variable)
textBox1.Text = nPaints.ToString();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
Pen p = new Pen(Color.Purple);
g.DrawRectangle(p, 1, 1, 100, 100);
p.Dispose();
}
What does this tells you?
Graphics3
load Maximize the form size
Minimize the form size
Graphics3
Load
• Comment the following line (in the OnPaintmethod):
// base.OnPaint(e);
OnPaint method
Conclusion:
Raises the Paint event.
So, it is called every time the control needs to be redrawn.
Note:
This method is derived from class Control. So all controls has this event.
Graphics
In the examples shown in class, there were two ways to get the form repainted:
• Write a handler for the Paint event and register for the event
• Override the OnPaint method that is inherited from the class Control
The second approach is the suggested one. It avoids creating a delegate and adding it to the handler. But your code should do this:
protected override void OnPaint (PaintEventArgs e){
base.OnPaint(e);...
}This guarantees that any registereddelegates receive the event.
Graphics
Question: what do you do when you need to redraw the screen?
Answer: force a Paint event.
Invalidate();Update();
Causes an immediatecall to OnPaint.
Causes a paint messageto be sent to the control
The Invalidate method governs what gets painted or repainted. The Updatemethod governs when the painting or repainting occurs. If you use the Invalidate and Update methods together rather than calling Refresh, what gets repainted depends on which overload of Invalidate you use. The Updatemethod just forces the control to be painted immediately, but the Invalidatemethod governs what gets painted when you call the Update method.
Graphics
To read a bitmap from a file, use the static method FromFile of the Image class:
Image myImage = Image.FromFile(filename);
string
Graphics
To read a bitmap from a file, use the static method FromFile of the Image class:
Image myImage = Image.FromFile(filename);
If you have a Graphics object g, you can draw the image at location x, y with:
g.DrawImage(myImage, x, y);
How do you get a Graphics object?
• When you override the OnPaint method or install a handler for the Paint event, you will receive a PaintEventArgs object that has a Graphics property.
• To paint on a form (or control) at other times, you can call the form's CreateGraphics method. You should call Dispose on Graphicsobjects that you create.
• To draw on a bitmap in memory, you can obtain a Graphics object from the static method. Again you would call Dispose.
Dragging Image on the Form• The example shows how to drag an image in the screen
• This is a Model/View/Controller example
• Model
– Maintains the position of the card on the screen
• View
– Display the card on the screen with the background image.
• Controller
– Get mouse input, inform the model of changes in position of the card, and adds to the background when a menu item is selected.
class Model
{
private Image cardImage;
private Point location;
public event System.EventHandler OnCardLocChanged;
public Model(){...}
public Point CardPos
{
get {return location;}
set
{
if (location != value)
{
location.X = value.X;
location.Y = value.Y;
OnCardLocChanged(this, new EventArgs()); //Fire the event if a new position is set.
}
}
}
public Image CardImage
{
get {return cardImage;}
}
}
class View
{
private Point currentLocation, newLocation;
private Model model;
private Form form;
private Graphics g;
public View(Model model, Form form)
{
this.model = model;
this.form = form;
g = form.CreateGraphics();
model.OnCardLocChanged += new EventHandler(drawView);
}
public void drawView(object sender, EventArgs e)
{
Bitmap newImage = (Bitmap) form.BackgroundImage.Clone();
Graphics niG = Graphics.FromImage(newImage);
Image image = model.CardImage;
newLocation = model.CardPos;
niG.DrawImage(image, newLocation.X, newLocation.Y);
g.DrawImage(newImage, 0, 0);
newImage.Dispose();
niG.Dispose();
}
}
public class Form1 : System.Windows.Forms.Form
{
private System.ComponentModel.Container components = null;
private System.Windows.Forms.MainMenu mainMenu1;
private System.Windows.Forms.MenuItem menuItem1;
private System.Windows.Forms.MenuItem AddToBackground;
private Model model;
private View view;
private bool dragging;
private Random r = new Random();
...
}
public class Form1 : System.Windows.Forms.Form
{
...
public Form1()
{
InitializeComponent();
model = new Model();
view = new View(model, this); //The view knows about the model and the form
dragging = false;
//We create a bitmap for the background, start with one rectangle,
//and set it as the background image for the form.
Bitmap bckgnd = new Bitmap(this.ClientSize.Width,
this.ClientSize.Height);
Graphics g = Graphics.FromImage(bckgnd);
SolidBrush br = new SolidBrush(Form1.DefaultBackColor);
g.FillRectangle(br, 0, 0, this.ClientSize.Width,
this.ClientSize.Height);
g.DrawRectangle(new Pen(Color.Black), 100,100,20,20);
this.BackgroundImage = bckgnd;
br.Dispose();
g.Dispose();
}
...
}
//The paint event handler just asks the view to draw the form.
private void Form1_Paint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
view.drawView(this, new EventArgs());
}
//When the mouse goes down, we get the position of the card from the model
//and if the mouse is inside, then we start dragging.
private void Form1_MouseDown(object sender,
System.Windows.Forms.MouseEventArgs e)
{
Rectangle rect = new Rectangle(model.CardPos.X, model.CardPos.Y,
model.CardImage.Width, model.CardImage.Height);
if (rect.Contains(e.X, e.Y))
dragging = true;
}
//If the mouse moves when we are dragging, we update the model to indicate
//a new position for the card. The model will let the view know.
private void Form1_MouseMove(object sender,
System.Windows.Forms.MouseEventArgs e)
{
if (dragging)
model.CardPos = new Point(e.X, e.Y);
}
//It's possible to drag the card off the form. If that happens, we
//put it back.
private void Form1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
Point pt = model.CardPos;
dragging = false;
if (pt.X < 0)
pt.X = 0;
if (pt.X > this.ClientSize.Width - model.CardImage.Width)
pt.X = this.ClientSize.Width - model.CardImage.Width;
if (pt.Y < 0)
pt.Y = 0;
if (pt.Y > this.ClientSize.Height - model.CardImage.Height)
pt.Y = this.ClientSize.Height - model.CardImage.Height;
model.CardPos = pt;
}
//This lets us add to the background, just to be sure everything works.
//The model is not aware of the background.
private void addToBackgroundMenuItem_Click(object sender,
System.EventArgs e)
{
Graphics g = Graphics.FromImage(this.BackgroundImage);
int x = r.Next(this.ClientSize.Width - 20);
int y = r.Next(this.ClientSize.Height - 20);
Pen p = new Pen(Color.Black);
g.DrawRectangle(p, x, y, 20, 20);
p.Dispose();
g.Dispose();
}
}