PDA

View Full Version : ترسیم مجدد خطوط در picturebox



vb study
یک شنبه 12 شهریور 1391, 23:50 عصر
با عرض سلام خدمت تمامی دوستان

من در یک picturebox تعدادی خط ترسیم کرده ام ( به عنوان مثال شکل یک ستاره) و با یک کلیک یک دکمه اندازه شکل ترسیم شده را بزرگ می کنم
الان با دو مشکل مواجه شده ام
1- بعد از ترسیم مجدد شکل که بزرگتر شده است شکل کوچکتر قبلی هنوز وجود دارد ( می بایست خطوط ترسیم شده قبلی در picturebox با ترسیم مجدد پاک شوند)
2- با Minimize کردن فرم و دوباره Maximize کردن آن خطوط ترسیم شده در picturebox پاک می شوند.

Hybrid
دوشنبه 13 شهریور 1391, 00:40 صبح
2- با Minimize کردن فرم و دوباره Maximize کردن آن خطوط ترسیم شده در picturebox پاک می شوند.
اشکالی که میخواین ترسیم کنید در رویداد PictureBox ، Paint رسم کنید مثلا به این قطعه کد توجه کن :


Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
Dim objPen As Pen
Dim objPicGraphics As Graphics = e.Graphics
objPen = New Pen(Drawing.Color.Red, 5)
objPen.DashStyle = Drawing2D.DashStyle.Solid
objPicGraphics.DrawLine(objPen, 20, 20, 400, 400)
End Sub


1- بعد از ترسیم مجدد شکل که بزرگتر شده است شکل کوچکتر قبلی هنوز وجود دارد ( می بایست خطوط ترسیم شده قبلی در picturebox با ترسیم مجدد پاک شوند)
میتونین از قطعه کد زیر استفاده کنید :

Me.PictureBox1.Refresh()

vb study
دوشنبه 13 شهریور 1391, 03:26 صبح
مشکل اولم با راهنمایی شما حل شد و تشکر می کنم
اما برای مشکل دوم کدهایی رو که نوشتین رو چطور فراخوانی کنم دستور call PictureBox1_Paint() خطا میده

Hybrid
دوشنبه 13 شهریور 1391, 03:39 صبح
مشکل اولم با راهنمایی شما حل شد و تشکر می کنم
اما برای مشکل دوم کدهایی رو که نوشتین رو چطور فراخوانی کنم دستور call PictureBox1_Paint() خطا میده

کدهایی که واسه ترسیم یک شکل مثلا دایره به کار میبرید رو در رویداد Paint کنترل PictureBox قرار بدین تا درست بشه(به نمونه کدی که واستون نوشتم دقت کنید).

لازم به فراخوانی نداره این رویداد ، هنگامی که فرم Minimize بشه و دوباره به حالت اول برگرده این رویداد به طور اتوماتیک اجرا میشه و اشکال رو دوباره رسم میکنه

vb study
دوشنبه 13 شهریور 1391, 16:36 عصر
با سلام مجدد
مشکل اینجاست که من یه سری دکمه دارم که هر کدوم رو بزنی شکل رو ترسیم میکنه به عنوان مثال یه دکمه شکل رو چند برابر می کنه و یه دکمه دیگه کوچیکترش می کنه به عبارت دیگه مختصات ترسیم رو تغییر میدن و این مستلزم اینه که رویداد تحت کنترل چند دکمه باشه و نیاز دارم که فرا خوانیش کنم

the king
دوشنبه 13 شهریور 1391, 22:09 عصر
با سلام مجدد
مشکل اینجاست که من یه سری دکمه دارم که هر کدوم رو بزنی شکل رو ترسیم میکنه به عنوان مثال یه دکمه شکل رو چند برابر می کنه و یه دکمه دیگه کوچیکترش می کنه به عبارت دیگه مختصات ترسیم رو تغییر میدن و این مستلزم اینه که رویداد تحت کنترل چند دکمه باشه و نیاز دارم که فرا خوانیش کنم

حداقل دو تا روش هست، هر کدوم معایب مزایای خاص خودش رو داره :
1) ترسیم رو فقط در رخداد Paint انجام دهید. خود رخداد Paint موقع نمایش کنترل، موقعی که چیزی رو کنترل رو بپوشونه و بعد کنار بره و ... فراخوانی میشه اما
هر زمانی که خودتان اراده کردید با متد هایی مثل ()Invalidate یا ()Refresh می توانید مجددا رخداد Paint رو فراخوانی کنید. اگر قراره ترسیم جدید با ترسیم قبلی
فرق کنه اصولا در ابتدای ترسیم زمینه رو مجددا رنگ می کنند که نتیجه اش پر پر زدن تصویره.
این روش زمانی که روال ترسیم و کوتاهه مناسبه، حداقل میزان حافظه رو هم مصرف می کنه ما اگر ترسیم پیچیده باشه موقعی که یک فرم در حال عبور از روی
کنترله هم کند میشه و هم پر پر می زنه.

2) ترسیم رو در یک Bitmap یا BufferedGraphics جداگانه انجام دهید و در رخداد Paint فقط نتیجه ترسیم رو نشان دهید.
اینطوری تا زمانی که نیازی به تغییر در ظاهر ترسیم نباشه، هیچ تغییری در اون Bitmap یا BufferedGraphics نمی دهید و بجز نمایش مجدد اش،
کاری انجام نمیشه. میزان مصرف حافظه بیشتره اما اگه ترسیم پیچیده باشه نه کند میشه و نه پر پر می زنه. برای حالت هایی که ظاهر باید مدام
تغییر کنه یا ترسیم روال پیچیده ای داره مناسبه. هر زمانی که لازم شد ظاهر تغییر کنه، دو کار باید انجام بشه، اول اینکه اون Bitmap یا BufferedGraphics
رو مجددا رسم کنید و بعد کنترل رو ()Invalidate یا ()Refresh کنید تا رخداد Paint اش اتفاق بیافته.

اصولا شما باید اطلاعات چیزی رو که به رسم اضافه میشه نگهداری کنید. اینطوری هم بعدا امکان Undo کردن رو داره و هم میشه جلو و عقب اش برد و
تغییر داد.

vb study
دوشنبه 13 شهریور 1391, 22:55 عصر
باتشکر از توجه دوستان حالا که کار به جاهای باریک داره میکشه :لبخندساده: خدمتتون عارضم که خطوط ترسیمی من حداقل چند هزار تا میشه که به عنوان مثال خیابانها و ساختمانهای موجود در یک شهر رو نشون میده و با چرخوندن کلید وسط ماوس این نقشه جلو و عقب ( بزرگ و کوچک) میشه تا اینجاشو مشکلی نداشتم و تو یک picturebox رسمش کردم ولی هموجوری که دوست عزیزمون میگن وقتی رسم مجدد به صورت اتوماتیک صورت می گیره یه مقداری پر پر میزنه این که در یک محیط BufferedGraphics رسم کنم و بعد با دستور paint بیارمش رو متاسفانه متوجه نشدم ممنون می شم یه مقداری بیشتر توضیح بدین و اگه کدی هم دارین برام بزارین:خجالت:
کلا اگه کسی برای اینجور ترسیمی پیشنهاد خوب دیگه ای داره ممنون میشم

the king
جمعه 17 شهریور 1391, 15:46 عصر
باتشکر از توجه دوستان حالا که کار به جاهای باریک داره میکشه :لبخندساده: خدمتتون عارضم که خطوط ترسیمی من حداقل چند هزار تا میشه که به عنوان مثال خیابانها و ساختمانهای موجود در یک شهر رو نشون میده و با چرخوندن کلید وسط ماوس این نقشه جلو و عقب ( بزرگ و کوچک) میشه تا اینجاشو مشکلی نداشتم و تو یک picturebox رسمش کردم ولی هموجوری که دوست عزیزمون میگن وقتی رسم مجدد به صورت اتوماتیک صورت می گیره یه مقداری پر پر میزنه این که در یک محیط BufferedGraphics رسم کنم و بعد با دستور paint بیارمش رو متاسفانه متوجه نشدم ممنون می شم یه مقداری بیشتر توضیح بدین و اگه کدی هم دارین برام بزارین:خجالت:
کلا اگه کسی برای اینجور ترسیمی پیشنهاد خوب دیگه ای داره ممنون میشم

کار با BufferedGraphics
اول برای کلاس فرم تون یک buffer بسازید :

Public Class Form1

Private buffer As BufferedGraphics

End Class


و از PictureBox تون بخواهید که همیشه اون buffer رو رسم کنه :

Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
If buffer IsNot Nothing Then
buffer.Render(e.Graphics)
End If
End Sub


و یک متدی بسازید که داخل buffer طرح تون رو رسم کنه :

Private Sub PaintBuffer()
buffer.Graphics.Clear(Color.White)
buffer.Graphics.DrawLine(Pens.Blue, 10, 10, 100, 100)
buffer.Graphics.DrawLine(Pens.Red, 10, 100, 100, 10)
PictureBox1.Invalidate()
End Sub


و اصولا اینطوری یه که اگر ابعاد PictureBox تون عوض شد، ابعاد buffer تون هم تغییر کنه و مجددا رسم بشه :

Private Sub PictureBox1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles PictureBox1.Resize
If buffer IsNot Nothing Then
buffer.Dispose()
End If
With PictureBox1
Using g As Graphics = .CreateGraphics()
buffer = BufferedGraphicsManager.Current.Allocate(g, .ClientRectangle)
End Using
PaintBuffer()
End With
End Sub


و موقعی که فرم Load میشه هم buffer رو ایجاد کنید و هم داخل رسم کنید :

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
PictureBox1_Resize(PictureBox1, EventArgs.Empty)
PaintBuffer()
End Sub


حالا هر جایی که لازمه ظاهر تغییر کنه فقط PaintBuffer رو فراخوانی کنید :

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
PaintBuffer()
End Sub