So I basically have have a picturebox set to a certain location (61, 361) and I have the below code in a timer, so whenever it is enabled it will increment the location of the x and y axis with a certain amount. I just need help to code it so it will trace a path preferably like a dotted line if possible. Thanks in advance for the help. It moves in a parabolic shape btw.
private void SimulationTimer_Tick(object sender, EventArgs e)
{
Ball.Location = new Point(Ball.Location.X + x, Ball.Location.Y - y);
}
Hope this helps:
private void SimulationTimer_Tick(object sender, EventArgs e)
{
System.Drawing.Point current =new System.Drawing.Point();
current = Ball.Location;
Ball.Location = new Point(Ball.Location.X + x, Ball.Location.Y - y);
PictureBox dot = new PictureBox();
dot.BackColor = Color.Red;
dot.Location = current;
dot.Height= 5;
dot.Width = 5;
this.Controls.Add(dot);
}
you can just modify the dot above to what you need
To achieve a path following the changes you have applied to your picturebox you
save each point in a List
NOTE: As you wrote "pictureBox" i assumed you are using Forms and not WPF
public partial class Form1 : Form
{
private List<Point> _points; // List of Points
private Timer _timer; // The Timer
private Graphics _g; // The Graphics object which is responsible for drawing the anything onto the Form
public Form1()
{
_points = new List<Point>();
_timer = new Timer();
_timer.Tick += Timer_Tick;
InitializeComponent();
_g = CreateGraphics();
}
private void Form1_Load(object sender, EventArgs e)
{
_timer.Start();
}
private void Timer_Tick(object sender, EventArgs e)
{
_points.Add(pictureBox1.Location); // Add the current location to the List
// Invoke the GUI Thread to avoid Exceptions
pictureBox1.Invoke(new Action(() =>
{
pictureBox1.Location = new Point(pictureBox1.Location.X + 2, pictureBox1.Location.Y + 2);
}));
Pen blackPen = new Pen(Color.Black, 3);
Invoke(new Action(() =>
{
for (int i = 1; i < _points.Count; i++) // Start at 1 so if you hav less than 2 points it doesnt draw anything
{
_g.DrawLine(blackPen, _points[i - 1], _points[i]);
}
}));
}
}
For a dotted Line you could only draw every second segment of the Line, but that's something you can figure out yourself.
Preview:
Related
Ok so please keep answers very direct and i must say i am very new to C#, i don't know a lot of stuff. Without further adieu my problem.
I am trying to move a picture box horizontally across the screen on a timer.The timer must go infinitely. I have tried all i currently know in C# and searched around quite a lot but nothing answered my exact question which is what i need because of my lesser knowledge of C#. For the last two weeks i worked on graphics mostly and the rest of that was trying to get this to work, So i have no code in my game. This is because for anything to work i need this part to be working. My game is 2D topdown. Any and all help is appreciated.
Thank you for taking the time to read.
Edit
No more answers needed, Thank you Odrai for the answer, it helped me a lot.
Use pictureBox.Location = new Point(x, y) or set pictureBox.Left/Top/Right. You can define x and y as variabels and initialize them with a default value. Increment x on timer tick.
Sample 1:
public partial class Form1 : Form
{
private Random _random
public Form1()
{
InitializeComponent();
_random = new Random();
}
private void timer1_Tick(object sender, EventArgs e)
{
int x = _random.Next(0, 500);
int y = _random.Next(0, 500);
pictureBox1.Top += y;
pictureBox1.Left += x;
}
}
Sample 2:
private void timer1_Tick(object sender, EventArgs e)
{
this.SuspendLayout();
pictureBox.Location = new Point(picust.Location.X + 10, picust.Location.Y);
this.ResumeLayout();
}
Add two buttons with title LEFT and RIGHT to a form and write the following code.
It might give you an idea, how to do simple moving animations.
public partial class Form1 : Form
{
int difference = 0;
Timer timer = new Timer();
public Form1()
{
InitializeComponent();
timer.Interval = 15;
timer.Tick += timer_Tick;
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
pictureBox1.Left += difference;
}
private void btnLeft_Click(object sender, EventArgs e)
{
difference = -2;
}
private void btnRight_Click(object sender, EventArgs e)
{
difference = 2;
}
}
Try This Code it will work :
private void timer1_Tick(object sender, EventArgs e)
{
int width = this.Width; // get the width of Form.
if(pictureBox1.Location.X > width - pictureBox1.Width) //to check condition if pic box is touch the boundroy of form width
{
pictureBox1.Location = new Point(1, pictureBox1.Location.Y); // pic box is set to the new point. here 1 is indicate of X coordinate.
}
else
{
pictureBox1.Location = new Point(pictureBox1.Location.X + 100, pictureBox1.Location.Y); // to move picture box from x coordinate by 100 Point.
}
}
//Try This //
picturebox1.Location = 0,0;
I have a windows form application with a PictureBox control containing an image. I want to move the PictureBox control to the right in a slow movement. Here is my code:
Point currentPoint = pictureBox_Logo.Location;
for (int i = 0; i < 25; i++)
{
pictureBox_Logo.Location = new Point(pictureBox_Logo.Location.X + 1, pictureBox_Logo.Location.Y);
Thread.Sleep(30);
}
The problem here is that when the code executes instead of seeing the picture move, I see a white picture move and the moving stops until the picture appears.
What am I missing and what can I do about it?
Code:
public partial class Form1 : Form
{
void timer_Tick(object sender, EventArgs e)
{
int x = pictureBox1.Location.X;
int y = pictureBox1.Location.Y;
pictureBox1.Location = new Point(x+25, y);
if (x > this.Width)
timer1.Stop();
}
public Form1()
{
InitializeComponent();
timer1.Interval = 10;
timer1.Tick += new EventHandler(timer_Tick);
}
private void button1_Click(object sender, EventArgs e)
{
pictureBox1.Show();
timer1.Start();
}
}
original thread is here Move images in C#
Try to use pictureBox_Logo.Refresh() after Thread.Sleep(30);
Or look for standard Timer control.
My code is good written, but what I did wrong was putting the code in an event:
private void Form1_Shown(object sender, EventArgs e);
But when I put my code in a button it works without any problems.
I have loaded an image in my panel.I want to erase the parts of that image by using the mouse(dragging on the panel).Here is my code to load my image:
private void drawP_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(myImage, new Point(0, 0));
}
How can I do it?
Thanks in advance.
Updated:
sorry not to say earlier,I have set another image(image2) as background of the panel and I want it to be seen after erasing myImage(image loaded with the code above).
Hi I'm going to assume that you want this feature to work like the eraser on paint.
there are 3 events you are going to need
1.mousedown - to call the first erase and open up the mousemove event method.
2.mouseup - to stop the mousemove event method
3.mousemove - just to call the erase method
Code: //part pseudo as im not in visual studio right now :(
//global vars
bool enable = false;
void erase(Point mousepoint)
{
Point f = (mousepoint.X - yourpanel.left?, mousepoint.Y - yourpanel.top?);
//gets mouse position on accual picture;
yourImageGraphics.fillreactangle( f.X - 10, f.Y+10, 20,20 ,Color.White)
// int X , int Y, width , height, color
}
void mousedown(?)
{
enable=true;
erase(Cursor.Position //but you get this from e?);
}
void mouseup(?);
{
enable=false;
}
void mousemove(?)
{
if (enable)
erase(e.Position?);
}
Also it looks like you are going to have to make a graphics object for your panel :(
I hope this helps because question was a bit vague.
Here I created simple example. Of course it can be done better, but I just wondering how to do it... so sharing my results.
public partial class mainForm : Form
{
private Bitmap image;
private Rectangle imgRect;
public mainForm()
{
InitializeComponent();
BackColor = Color.Chartreuse;
image = new Bitmap(#"C:\image.jpg");
imgRect = new Rectangle(0,0,image.Width, image.Height);
}
private void main_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(image, 0, 0);
}
private void main_MouseMove(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left && e.X < image.Width && e.Y < image.Height)
{
image.SetPixel(e.X, e.Y, Color.Magenta);//change pixel color;
image.MakeTransparent(Color.Magenta);//Make image transparent
Invalidate(imgRect);
}
}
}
...and lets test
Ha! scared that I deleted his eye :)
A TextureBrush on a pen can be used for erasing.
Working example (image1 and image2 are the same size images):
Bitmap bmp1;
TextureBrush tb;
Point _LastPoint;
public Form1()
{
InitializeComponent();
this.DoubleBuffered = true;
bmp1 = new Bitmap(#"c:\image1.png");
tb = new TextureBrush(new Bitmap(#"c:\image2.png"));
}
private void Form1_MouseMove(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
if (!_LastPoint.IsEmpty) {
using (Graphics g = Graphics.FromImage(bmp1))
using (Pen p = new Pen(tb, 15)) {
p.StartCap = LineCap.Round;
p.EndCap = LineCap.Round;
g.DrawLine(p, _LastPoint, e.Location);
}
}
_LastPoint = e.Location;
this.Invalidate();
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e) {
_LastPoint = Point.Empty;
}
private void Form1_Paint(object sender, PaintEventArgs e) {
e.Graphics.DrawImage(bmp1, new Point(0, 0));
}
I am trying to move a drawn line by grabbing it with the mouse.
The line have already been drawn with Graphics.DrawLine(Pen P, Point A, Point B).
There is absolutely no problems with creating the Line and drawing it on the form.
I've tried:
Adding the line to a GraphicsPath - This does not even draw the line OnPaint.
Checking if MouseEventArgs e.Location is on the line with some basic algebra (calculations which I have thrown away as of now)
So to sum it up: I want to grab the line and drag it somewhere but I can't even check if e.Location even is on the Line, how do I do this?
EDIT: This is how the code looks when I'm using the GraphicsPath.
When I don't use the GraphicsPath I have:
if (s.thisShape == ShapeType.Line) {
g.DrawLine(pen, s.p1, s.p2);
} else { ... }`
in the drawingShapes method.
From the drawStuff : Usercontrol class:
private void drawStuff_MouseDown(object sender, MouseEventArgs e)
{
pointRegion = e.Location;
for (int i = 0; i < Shapes.Count; i++)
{
if (Shapes[i].Region.IsVisible(pointRegion))
{
isDragging = true;
count = i;
break;
}
}
}
private void drawStuff_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging)
{
Shapes[count].moveWithDiff(pointRegion, e.Location);
pointRegion = e.Location;
Refresh();
}
}
private void drawStuff_MouseUp(object sender, MouseEventArgs e)
{
isDragging = false;
Refresh();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
drawShapes(e.Graphics);
}
private void drawShapes(Graphics g)
{
temporaryPen = pennaLeft;
foreach (Shape s in Shapes)
{
g.FillRegion(temporaryPen, s.Region);
}
}
From the Shape : Usercontrol class:
public void moveWithDiff(Point pr, Point mp)
{
Point p = new Point();
if (this.thisShape == ShapeType.Line)
{
p.X = mp.X - pr.X;
p.Y = mp.Y - pr.Y;
this.p1.X += p.X;
this.p1.Y += p.Y;
this.p2.X += p.X;
this.p2.Y += p.Y;
}
RefreshPath();
}
private void RefreshPath()
{
gPath = new GraphicsPath();
switch (thisShape)
{
case ShapeType.Line:
gPath.AddLine(this.p1, this.p2);
break;
}
this.Region = new Region(gPath);
}
Now this doesn't even draw the line, however with said if statement in drawingShapes() It draws perfectly but I can not drag it somewhere else.
Let's start with the basics, getting a line on the screen. I created a custom class to handle some of the functions I want available to me for this process:
public class MyLine
{
public Pen pen { get; set; }
public Point Start { get; set; }
public Point End { get; set; }
public MyLine(Pen p, Point p1, Point p2)
{
pen = p;
Start = p1;
End = p2;
}
public float slope
{
get
{
return (((float)End.Y - (float)Start.Y) / ((float)End.X - (float)Start.X));
}
}
public float YIntercept
{
get
{
return Start.Y - slope*Start.X;
}
}
public bool IsPointOnLine(Point p, int cushion)
{
float temp = (slope * p.X + YIntercept);
if (temp >= (p.Y-cushion) && temp <=(p.Y+cushion))
{
return true;
}
else
{
return false;
}
}
}
This class provides a few helper functions that will make our life easier. We have properties that return the slope and the Y-intercept, so we can determine if a certain point is on the line. We then provide a helper function IsPointOnLine() that takes a point and a cushion. The cushion is used to simply allow for a user to click close enough to the line to get it to return true.
Next I am going to instantiate the line and draw it in the Form's paint event:
MyLine m;
private void Form1_Load(object sender, EventArgs e)
{
m= new MyLine(Pens.Black, new Point(20, 20), new Point(40, 40));
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawLine(m.pen, m.Start, m.End);
}
Now you should be able to run your application and see a line that goes from 20,20 to 40,40 on the screen.
Now I want to handle the mouse interaction with the line, so on MouseDown, we will see if the click point intersects the line and if it is set a flag and keep our deltas from the endpoints. On the MouseMove event, we will see if the line has been clicked but not released and reset the coordinates appropriately. In the MouseUp event, we simple reset our flag:
Point deltaStart;
Point deltaEnd;
bool dragging = false;
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left && m.IsPointOnLine(e.Location, 5))
{
dragging = true;
deltaStart = new Point(m.Start.X - e.Location.X, m.Start.Y - e.Location.Y);
deltaEnd = new Point(m.End.X - e.Location.X, m.End.Y - e.Location.Y);
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (dragging && deltaStart != null && deltaEnd != null )
{
m.Start = new Point(deltaStart.X + e.Location.X, deltaStart.Y + e.Location.Y);
m.End = new Point(deltaEnd.X + e.Location.X, deltaEnd.Y + e.Location.Y);
this.Refresh();
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
dragging = false;
}
Now you should be able to click within 5 pixels of the line and have it move with your mouse.
Note, there are some spots in the code that need additional error handling, especially to handle division by 0 errors.
I suggest you create a rectangle that is the width of the line and the length of the line, then you can use
if(rectangle.Contains(Point p))
{
// do your move
}
You can also inflate the rectangle to make it easier to grab with:
rectangle.Inflate(1, 1);
So I've been putting this graphics transformation program together and suddenly some change I can't figure out has made the app unresponsive. The menus no longer function, and it's supposed to draw axes and a grid on one of the panels... nothing. Any ideas?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace Transformer
{
public partial class Transformer : Form
{
/* Initialize parameters */
private bool drawAxes = true;
private bool drawGrid = true;
private List<ObjectSettings> dispObjects = new List<ObjectSettings>();
/* Initialize form */
public Transformer()
{
InitializeComponent();
}
private void Transformer_Load(object sender, EventArgs e)
{
// Populate available objects listbox
string currentDir = Directory.GetCurrentDirectory();
string[] fileEntries = Directory.GetFiles(currentDir + #"\Objects");
foreach (string s in fileEntries) {
int start = s.LastIndexOf(#"\");
int end = s.LastIndexOf(#".");
availObjectsListBox.Items.Add(s.Substring(start + 1, end - start - 1));
} // end foreach
}
/* Paint graphics */
// Paint main form
private void Transformer_Paint(object sender, PaintEventArgs e)
{
}
// Paint graphics panel
private void splitContainer2_Panel1_Paint(object sender, PaintEventArgs e)
{
Rectangle r = splitContainer2.Panel1.ClientRectangle;
Graphics g = splitContainer2.Panel1.CreateGraphics();
Pen axisPen = new Pen(Color.Gray, 2.0f);
Pen gridPen = new Pen(Color.Gray, 1.0f);
g.Clear(Color.White);
if (drawAxes) {
g.DrawLine(axisPen, r.Left + 0.5f * r.Width, r.Top, r.Left + 0.5f * r.Width, r.Bottom);
g.DrawLine(axisPen, r.Left, r.Top + 0.5f * r.Height, r.Right, r.Top + 0.5f * r.Height);
}
if (drawGrid) {
// Vertical lines
int xVal = 0;
int xCenter = r.Width / 2;
g.DrawLine(gridPen, xCenter, r.Top, xCenter, r.Bottom);
for (int i = 0; i < 10; i++) {
xVal += r.Width / 20;
g.DrawLine(gridPen, xCenter + xVal, r.Top, xCenter + xVal, r.Bottom);
g.DrawLine(gridPen, xCenter - xVal, r.Top, xCenter - xVal, r.Bottom);
}
// Horizontal lines
int yVal = 0;
int yCenter = r.Height / 2;
g.DrawLine(gridPen, r.Left, yCenter, r.Right, yCenter);
for (int i = 0; i < 10; i++) {
yVal += r.Height / 20;
g.DrawLine(gridPen, r.Left, yCenter + yVal, r.Right, yCenter + yVal);
g.DrawLine(gridPen, r.Left, yCenter - yVal, r.Right, yCenter - yVal);
}
}
// foreach object in displayed objects
// keep list of displayed objects and their settings (make struct)
g.Dispose();
axisPen.Dispose();
gridPen.Dispose();
}
/* File menu */
private void saveImageToolStripMenuItem_Click(object sender, EventArgs e)
{
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Close();
}
/* Options menu */
private void axesOnoffToolStripMenuItem_Click(object sender, EventArgs e)
{
if (drawAxes == true)
drawAxes = false;
else
drawAxes = true;
}
private void gridOnoffToolStripMenuItem_Click(object sender, EventArgs e)
{
if (drawGrid == true)
drawGrid = false;
else
drawGrid = true;
}
/* Help menu */
private void helpToolStripMenuItem_Click(object sender, EventArgs e)
{
AboutBox dlg = new AboutBox();
dlg.ShowDialog();
}
/* Other stuff */
private void timer1_Tick(object sender, EventArgs e)
{
Invalidate();
}
// ">>" button
private void availToDispButton_Click(object sender, EventArgs e)
{
dispObjectsListBox.Items.Add(availObjectsListBox.SelectedItem);
}
// "<<" button
private void dispToAvailButton_Click(object sender, EventArgs e)
{
availObjectsListBox.Items.Add(dispObjectsListBox.SelectedItem);
dispObjectsListBox.Items.Remove(dispObjectsListBox.SelectedItem);
}
// Clear all button
private void clearAllButton_Click(object sender, EventArgs e)
{
}
// Update preview box
private void availObjectsListBox_SelectedIndexChanged(object sender, EventArgs e)
{
}
}
}
Thanks!
Try commenting out (separately) the "load" and "paint" code, see which is the problem.
If the problem is the paint... I wonder - rather than creating your own Graphics, use the one given to you? Namely, e.Graphics. Note that you didn't create this, so it isn't your job to Dispose() it (so don't do that). I would also cache the Pen etc in fields rather than create them each time. Note that if you do create a Pen (etc) in a method, then using is a better way to Dispose() it.
There is also a foreach comment in the paint code that suggests something has been removed - this may be relevant to the problem...
If this is happening when loading then obviously the amount of files in the directory could be causing the GUI thread to hang.
Other then that my quick look through only makes me think to check the bools you are using to control drawing and to make sure that the panel you are using the paint event for is actually visible.
You should also check that your timer is actually ticking, and check its interval.
I would also look at using the using statement, or at least a finally block for your dispose. But that isn't what your question is about.
Most of those are obvious and you might have already checked them all before posting here, but I thought I would put up something in case you had missed it. Hopefully I will get a chance to look through in more detail and spot something else.