הערה
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות להיכנס או לשנות מדריכי כתובות.
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות לשנות מדריכי כתובות.
Question
Monday, July 4, 2016 3:47 AM
How can I move a control, such as a Picturebox, smoothly from its location to another specified location on the form using a Timer? Is there a simpler way to make this transition visible than to experiment with PictureBox.Top, PictureBox.Left, and others? I want to be able to see the control moving across the form for at least a second.
Bgeo25
All replies (6)
Monday, July 4, 2016 5:34 AM ✅Answered | 1 vote
Well if the PictureBox was at point(500, 500) then depending on how you determine the next point to move the PictureBox too you could set a global variable for that.
Dim PboxPoint as Point
In some code PBoxPoint = New Point(10, 600)
In Timer sub with interval set to 1 or 10 or whatever you will either need to subtract or add 1 I suppose to the PictureBoxes Location values until the values in PBoxPoints x and y coordinates are reached.
However that will not work real well since the new x and y coordinates to move the PictureBox too could have a great difference between them so the PictureBox may not move linearly. It may move up 10 and left 300 which would cause a strange issue since it would be up 10 and left 10 then just left to 300.
Since a controls location is a point using integer then pointf using single can not be used.
I can provide some code, I will update this post, for doing what you desire but there's probably simpler code for performing that. Be a few minutes.
Update: You can see in the animated .Gif that the control can not move directly from point A to point B since a Point uses integers which have no decimal type capability so that an accurate direction can occur. Somebody else may be able to provide other math which can perform for integer values better I suppose.
One thing you could do is make the PictureBox visible to false at the start of the move. Place the PictureBox at the new location. Draw the image in the PictureBox onto the Form moving the drawing until it gets to the new PictureBox location then quit drawing the image and set the PictureBox visible to true. That way PointF can be used for drawing the image on the Form and the image will move nicely and the code would obviously need to be altered to do that.
You can see in the bottom animated .Gif that the PictureBox's movement towards the end is erratic due to not being able to use singles for its x and y coordinates.
Option Strict On
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.DoubleBuffered = True
Me.Location = New Point(CInt((Screen.PrimaryScreen.WorkingArea.Width / 2) - (Me.Width / 2)), CInt((Screen.PrimaryScreen.WorkingArea.Height / 2) - (Me.Height / 2)))
Timer1.Interval = 10
End Sub
Dim PBoxMoving As Boolean = False
Dim PBoxOldLocation As Point
Dim PBoxNewLocation As Point
Dim Rect As Rectangle
Dim DistanceToUse As Single = 2
Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
If PBoxMoving = False Then
PBoxOldLocation = PictureBox1.Location
PBoxNewLocation = e.Location
Rect = New Rectangle(New Point(PBoxNewLocation.X - CInt(Math.Ceiling(CDec(DistanceToUse))), PBoxNewLocation.Y - CInt(Math.Ceiling(CDec(DistanceToUse)))), New Size(CInt(Math.Ceiling(CDec(DistanceToUse * 2))), CInt(Math.Ceiling(CDec(DistanceToUse * 2)))))
PBoxMoving = True
Timer1.Start()
End If
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Dim PBL As PointF = MathHelp.GetPointToward(New PointF(PBoxOldLocation.X, PBoxOldLocation.Y), New PointF(PBoxNewLocation.X, PBoxNewLocation.Y), DistanceToUse)
PictureBox1.Location = New Point(CInt(PBL.X), CInt(PBL.Y))
Me.Update()
PBoxOldLocation = PictureBox1.Location
If Rect.Contains(PictureBox1.Location) Then
Timer1.Stop()
PictureBox1.Location = PBoxNewLocation
PBoxMoving = False
End If
End Sub
' Below class was created by Reed Kimble for a game in one of this forums threads a while ago.
Public NotInheritable Class MathHelp
Public Const TWO_PI As Single = Math.PI * 2
Protected Sub New()
End Sub
Public Shared Function GetDistance(ByVal source As PointF, ByVal target As PointF) As Single
Dim squareX As Double = CDbl(target.X - source.X)
squareX *= squareX
Dim squareY As Double = CDbl(target.Y - source.Y)
squareY *= squareY
Return CSng(Math.Sqrt(squareX + squareY))
End Function
Public Shared Function GetRadiansTo(ByVal source As PointF, ByVal target As PointF) As Single
Return WrapAngle(CSng(Math.Atan2(target.Y - source.Y, target.X - source.X)))
End Function
Public Shared Function GetPointToward(ByVal source As PointF, ByVal target As PointF, ByVal distance As Single) As PointF
Dim angle As Single = GetRadiansTo(source, target)
Return source + New SizeF(CSng(Math.Cos(angle) * distance), CSng(Math.Sin(angle) * distance))
End Function
Public Shared Function WrapAngle(ByVal radians As Single) As Single
While radians < -Math.PI
radians += TWO_PI
End While
While radians > Math.PI
radians -= TWO_PI
End While
Return radians
End Function
End Class
End Class
La vida loca
Monday, July 4, 2016 4:11 AM
The Forms double buffered property may need to be set to true to stop flickering.
You don't explain how you determine where to move the PictureBox to on the Form.
The below thread may have some code in timer events that is relevant to what you want to do.
Make the contents of a panel fade
La vida loca
Monday, July 4, 2016 4:27 AM
The Forms double buffered property may need to be set to true to stop flickering.
You don't explain how you determine where to move the PictureBox to on the Form.
The below thread may have some code in timer events that is relevant to what you want to do.
Make the contents of a panel fade
La vida loca
I'll be more specific with an example. If I have a PictureBox with location (62, 62) on a form, I want to accomplish moving the PictureBox to new location (100, 200). In every case, I will already know the destination point. I could change the location by
PictureBox1.Location = New Point(100, 200)
but that will move the PictureBox instantaneously. I want to be able to see the control gradually moving from the (62, 62) to (100, 200). I assume a Timer would help in this case, but is there a faster/more efficient way than using PictureBox.Left += (something) or PictureBox.Top += (something) in a Timer?
Bgeo25
Monday, July 4, 2016 5:25 AM | 1 vote
If you are interested in alternatives, then consider another kind of VB.NET applications: WPF or UWP. There are a series of embedded animation effects, which do not need explicit timers (https://msdn.microsoft.com/en-us/library/ms752312(v=vs.100).aspx).
Monday, July 4, 2016 5:32 AM | 1 vote
If I have a PictureBox with location (62, 62) on a form, I want to accomplish moving the PictureBox to new location (100, 200). In every case, I will already know the destination point.
You need to calculate the x distance and the Y distance that you need to move - a simple subtract of the respective values of the two positions will give that.
Then you need to come up with a figure for the number of steps that you want to take and the time interval between each step. For instance, ten steps at 100ms each will take one second to do the move.
Divide your X and Y distances by ten to get the number of pixels to move in each step. Set the timer interval to 100ms, and start the timer. At each timer tick, move the picturebox by the calculated number of pixels, calculated separately for X and Y. When ten ticks have occurred (you should use a counter, position information may not be exact) stop the timer and position the control at the destination exactly.
Tuesday, July 5, 2016 6:55 AM
Using acceleration and decelleration on moving objects provides a better look. A 'snap' movement requires a uniform acceleration for most of the movement, then a severe decelleration to bring the object to a stop.
Experiment with writing code to produce a list of whole number steps, which increase and decrease in magnitude. The 'sum of' all the individual steps make up the total movement.
For example: Say you want to move an object 100 pixels. 5 + 10 + 15 + 20 + 25 + 15 + 10 = 100
BumperSticker: Amateurs built the Ark, Professionals built the Titanic