Using the OnPaint() method - c#

I am using this library to generate QRcode into a WinForm application, but I don't really know how to take use of the OnPaint() method.
So I have this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs e)
{
QrEncoder encoder = new QrEncoder(ErrorCorrectionLevel.M);
QrCode qrCode;
encoder.TryEncode("link to some website", out qrCode);
new GraphicsRenderer(new FixedCodeSize(200, QuietZoneModules.Two))
.Draw(e.Graphics, qrCode.Matrix);
base.OnPaint(e);
}
private void Form1_Load(object sender, EventArgs e)
{
this.Invalidate();
}
}
I have a simple pictureBox in the form and I just want to generate the QRcode image in there (if it is possible to generate it in a picturebox).

If you're putting your image in a picturebox and you're only producing your image once, then you don't need to worry about the paint method (you're not doing an animation etc, it's just a QR code)
Just do this in your form load (or where ever you produce your image)
mypicturebox.Image = qrCodeImage;
Update - additional code to facilitate your library
var bmp = new Bitmap(200, 200);
using (var g = Graphics.FromImage(bmp))
{
new GraphicsRenderer(
new FixedCodeSize(200, QuietZoneModules.Two)).Draw(g, qrCode.Matrix);
}
pictureBox1.Image = bmp;

This is what I eventually did:
public partial class Form1 : Form
{
public event PaintEventHandler Paint;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.Paint += new System.Windows.Forms.PaintEventHandler(this.pictureBox_Paint);
this.Controls.Add(pictureBox1);
}
private void pictureBox_Paint(object sender, PaintEventArgs e)
{
QrEncoder encoder = new QrEncoder(ErrorCorrectionLevel.M);
QrCode qrCode;
encoder.TryEncode("www.abix.dk", out qrCode);
new GraphicsRenderer(
new FixedCodeSize(200, QuietZoneModules.Two)).Draw(e.Graphics, qrCode.Matrix);
}
}

Related

Graphics DrawImage - ArgumentException: 'Parameter is not valid.'

I have timer which adds new image on the panel every second. First i create my global variable Graphics g, create timer in the construcor and start timer there. In my Panel method i create Graphics object (g = e.Graphics) and then in my timer method i use that g object to draw new image. Can't find what's the problem, here's the core code (program stops when on the first call - g.DrawImage()):
public partial class MyClass: Form
{
private Timer addImage;
private Image img;
private Graphics g;
private Point pos;
public MyClass()
{
InitializeComponent();
img = Image.FromFile("C:/image.png");
pos = new Point(100, 100);
addImage = new Timer()
{
Enabled = true,
Interval = 3000,
};
addImage.Tick += new EventHandler(AddImage);
addImage.Start();
}
private void MyPanel_Paint(object sender, PaintEventArgs e)
{
g = e.Graphics;
}
private void AddImage(Object myObject, EventArgs myEventArgs)
{
g.DrawImage(img, pos); // ArgumentException: 'Parameter is not valid.'
MyPanel.Invalidate();
}
}
You have to draw your image in the OnPaint override because the Graphics object will be disposed. To redraw the form you can call Refresh. Also look that your that your path to the image is correct.
public partial class MyClass : Form
{
private readonly Image _image;
private readonly Point _position;
private bool _isImageVisible;
public MyClass()
{
InitializeComponent();
_image = Image.FromFile(#"C:\img.png");
_position = new Point(100, 100);
var addImageCountdown = new Timer
{
Enabled = true,
Interval = 3000,
};
addImageCountdown.Tick += new EventHandler(AddImage);
addImageCountdown.Start();
}
private void AddImage(Object myObject, EventArgs myEventArgs)
{
_isImageVisible = true;
Refresh();
}
protected override void OnPaint(PaintEventArgs e)
{
if(_isImageVisible)
{
e.Graphics.DrawImage(_image, _position);
}
base.OnPaint(e);
}
}

Passing and getting data from class

I have 2 forms, form1 and form2. In form1 I call form2, where I input 2 numbers, one for height and for width of a picturebox. Then I want to pass that data from form2 to form1, where I create picturebox with said size.
Then I want to store height and width to class and then access that info from form1.
Here is my code:
Form1
namespace NPA_projekt
{
public partial class Form1 : Form
{
private Form2 f2 = new Form2();
image img = new image();
public Form1()
{
InitializeComponent();
}
private void newToolStripMenuItem_Click(object sender, EventArgs e)
{
f2.ShowDialog();
}
private void btnTest_Click(object sender, EventArgs e)
{
pbMainArea.Width = img.width;
pbMainArea.Height = img.length;
}
}
}
Form2
namespace NPA_projekt
{
public partial class Form2 : Form
{
image img = new image();
public Form2()
{
InitializeComponent();
}
//reset btn
private void button1_Click(object sender, EventArgs e)
{
nudWidth.Value = 640;
nudLength.Value = 400;
}
//cancel btn
private void button3_Click(object sender, EventArgs e)
{
this.Close();
}
//ok btn
private void btnOK_Click(object sender, EventArgs e)
{
img.width = Convert.ToInt32(nudWidth.Value);
img.length = Convert.ToInt32(nudLength.Value);
this.Close();
}
}
}
Class image
namespace NPA_projekt
{
class image
{
public int width = 0;
public int length = 0;
}
}
Values, that are stored in form2, are set to their original values, when I want to use them in form1. Could someone please elaborate what's happening.
Thank you all!
img is declared twice. Once in Form1 and again in Form2. When you are setting the width and height of img in Form2 you are setting it for the image instance you declared in Form2 not Form1. You need to make the img in Form1 visible to Form2 and perform the operation on that.
So, make img in Form1 public:
public image img {get; set;}
public Form1()
{
InitializeComponent();
img = new image();
}
Then you need to access it in Form2 (one way should be the Parent property of the form):
private void btnOK_Click(object sender, EventArgs e)
{
var form1 = (Form1)this.Parent
form1.img.width = Convert.ToInt32(nudWidth.Value);
form1.img.length = Convert.ToInt32(nudLength.Value);
this.Close();
}
I haven't tested this all out, but the approach is valid. The key to eliminating the confusion is getting rid of the img declaration in Form2 and realizing that you need to get access to Form1 from Form2

C# paint graphics from class in picturebox with mouse click

I want to paint a graphics object from a method (paint) I created in a separate class (Paintball). I want it to paint in a picturebox only when I left-click with my mouse and I want the point where I shoot to be stored in a List. When I try the code below, it doesn't shoot. Below is the class Paintball.
{
private List<Point> myClick;
public Paintball()
{
myClick = new List<Point>();
}
public void add(Point location)
{
myClick.Add(location);
}
public void paint(Graphics g, Point point)
{
g.FillEllipse(Brushes.Blue, point.X, point.Y, 20, 20);
}
}
}
This is form1 below.
namespace AmazingPaintball
{
public partial class Form1 : Form
{
Random positionX = new Random();
Random positionY = new Random();
Target einstein;
int count;
List<Point> ballList = new List<Point>();
Paintball gun;
public Form1()
{
InitializeComponent();
Point point = new Point(positionX.Next(0, 638), positionY.Next(0, 404));
einstein = new Target(point);
ptrEinstein.Location = point;
gun = new Paintball();
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
ptrEinstein.Location = einstein.Move(e.KeyData);
pictureBox1.Update();
pictureBox1.Refresh();
}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
count++;
gun.add(e.Location);
pictureBox1.Refresh();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
foreach (var Paintball in ballList)
{
gun.paint(e.Graphics, this.PointToClient(Cursor.Position));
pictureBox1.Refresh();
}
}
private void Form1_Load(object sender, EventArgs e)
{
timer1.Start();
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
pictureBox1.Refresh();
}
}
}
Please let me know if you know what has to be edited/created. Thank You
Your original code has many mistakes. Let's try to simplify what you are doing and tackle simply storing a list of points and drawing them to the picturebox.
public partial class Form1 : Form
{
List<Point> ballList = new List<Point>();
public Form1()
{
InitializeComponent();
}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
ballList.Add(e.Location);
pictureBox1.Refresh();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
foreach (Point pBall in ballList)
{
e.Graphics.FillEllipse(Brushes.Blue, pBall.X, pBall.Y, 20, 20);
}
}
}
Here we have a list, we add the click points to it in the click handler and paint them in the paint handler. Once you get comfortable with this, perhaps move to the next task in your program and ask a new question if you get stuck with the next feature.
Ok, I've got a bit of time, so let's look at your paintball class. I've renamed it Paintballs since it contains many of them and this name is more appropriate. If you want to keep the list of points private that's ok. You are trying to implement a Paint method in the class, but it takes a Point as argument and does not operate on any of the class's instance state - this probably isn't what you want. Consider now :
public class Paintballs
{
private List<Point> myClick;
public Paintballs()
{
myClick = new List<Point>();
}
public void Add(Point location)
{
myClick.Add(location);
}
public void Paint(Graphics g)
{
foreach (Point p in myClick)
{
g.FillEllipse(Brushes.Blue, p.X, p.Y, 20, 20);
}
}
}
Here we have a public Paint method that will draw all of the paintballs in the class to any graphics instance you pass to it. Now your form code would look like :
public partial class Form1 : Form
{
Paintballs pBalls = new Paintballs();
public Form1()
{
InitializeComponent();
}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
pBalls.Add(e.Location);
pictureBox1.Refresh();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
pBalls.Paint(e.Graphics);
}
}
So we've simplified the form code by pushing the painting method into the paintballs class itself. This makes the class responsible for knowing what the paintballs look like, how many there are, where they are, and how to draw them to a Graphics object. This is step 1 in encapsulating responsibility.
You're drawing from a list of points stored in that ballList variable. However, you've never added any points to that list.
Make the myClick list in Paintball public and, in the pictureBox1_Paint method, iterate through that list instead of ballList.

Very simple attempt of using DrawLine failing

I know this is trivial, but I don't understand why nothing is drawn on the Form1 after I click the button:
namespace GeometryTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, PaintEventArgs e)
{
System.Drawing.Graphics gr = this.CreateGraphics();
gr.Clear(Color.White);
Pen pen = new Pen(System.Drawing.Color.Red,3);
gr.DrawLine(pen, 20, 20, 200, 250);
}
}
}
Problem : you are using PaintEventArgs as parameter in Button Click event.
i even doubt that this will compile if you subscribe the button1_Click Event Handler to Click event of the Button.
Solution 1:
You need to Subscribe/Register to Button Click event as below:
button1.Click += new System.EventHandler(button1_Click);
and EventHandler should be as below:
private void button1_Click(object sender, EventArgs e)
{
//event handling code here
}
Complete Code:
namespace GeometryTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
button1.Click += new System.EventHandler(button1_Click);
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
System.Drawing.Graphics gr = this.CreateGraphics();
gr.Clear(Color.White);
Pen pen = new Pen(System.Drawing.Color.Red,3);
gr.DrawLine(pen, 20, 20, 200, 250);
}
}
}
Solution 2: if you want to draw the line on Form_Paint event you can do subscribe to Form_Paint Event as below:
You need to Subscribe/Register to Form Paint event as below:
this.Paint += new System.Windows.Forms.PaintEventHandler(Form1_Paint);
and EventHandler should be as below:
private void Form1_Paint(object sender, PaintEventArgs e)
{
//event handling code here
}
Complete Code:
namespace GeometryTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Paint += new System.Windows.Forms.PaintEventHandler(Form1_Paint);
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
System.Drawing.Graphics gr = this.CreateGraphics();
gr.Clear(Color.White);
Pen pen = new Pen(System.Drawing.Color.Red, 3);
gr.DrawLine(pen, 20, 20, 200, 250);
}
}
}

Controlling a PictureBox from a class

I have a little project in C#, (Windows Forms Application). I have on the form 77 PictureBoxes (pictureBox1, pictureBox2, pictureBox3, ...) and I want to control them but from a new class (Access.cs), by declaring a new one picturebox in the class to control all the pictures.
Because it would be too long if I pass through each pictureBox and add a click method and Copy + Paste the code and change the pictureBox number each time.
I've set the pictures as public and tried the following code:
Access.cs:
using System.Windows.Forms;
public class Access
{
PictureBox picBox = new PictureBox();
public void PictureClicked()
{
picBox.Image = Properties.Resources.apple;
}
}
Form1.cs:
private void pictureBox1_Click(object sender, EventArgs e)
{
Access ac = new Access();
ac.PictureClicked();
}
but the code didn't work!!
I dont really get what you want to do but you could try to send the object to your Access class:
private void pictureBox1_Click(object sender, EventArgs e)
{
Access ac = new Access();
ac.PictureClicked(sender);
}
public void PictureClicked(Object Sender)
{
picBox = (PictureBox)Sender;
picBox.Image = Properties.Resources.apple;
}
Access.Cs
public void pictureBox1_Click(object sender, EventArgs e)
{
PictureBox pi = (PictureBox)sender;
pi.Image = Properties.Resources.alert__2_;
}
Form1.Cs
private void pictureBox2_Click(object sender, EventArgs e)
{
Form1 c =new Form1();
c.pictureBox1_Click(sender, e);
}
Here pictureBox2_Click this event for all picturebox

Categories

Resources