Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > VB .NET > Порядок рисования


Автор: kobalt 7.10.2008, 14:57
Элементарное рисование. Из учебника взял пример с рисованием. Все рисует, но только после какого нибудь события (нажатие кнопки).
Пробовал вставить код в Form1_Load - ничего не получается (да и в книге об этом говорится).  В какую часть вставить код по рисованию графики, чтобы она рисовалась сразу после запуска программы, но до нажатий кнопок?

Автор: diadiavova 7.10.2008, 15:02
Если нужно, чтобы графика была устойчивой, то прорисовывать её надо постоянно, то есть код прорисовки надо вставлять либо в обработчик события Paint, либо переопределив метод OnPaint в производном классе.

Автор: kobalt 7.10.2008, 16:22
Задам вопрос подругому.
Есть код, по которому при нажатии Button1 рисуется линия.

Код

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

        Dim graf As Graphics = Me.CreateGraphics
        graf.DrawLine(Pens.Red, 1, 1, 100, 100)

    End Sub


Как сделать так, чтобы линия рисовалась до нажатия  Button1.

Автор: diadiavova 7.10.2008, 20:14
Код

Public Class Form1

    Sub Draw()
        Dim graf As Graphics = Me.CreateGraphics
        graf.DrawLine(Pens.Red, 1, 1, 100, 100)
    End Sub
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)
        Draw()
    End Sub
End Class


Когда ты ставишь код в обработчик Load, линии нет не потому, что она не прорисовалась, а потому, что после появления формы она была перерисована. Если тебе надо, чтобы линия была видна, делай так.

А ещё лучше так

Код

Public Class Form1

    Sub Draw(ByVal g As Graphics)
         g.DrawLine(Pens.Red, 1, 1, 100, 100)
    End Sub
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)
        Draw(e.Graphics)
    End Sub
End Class


или вообще так
Код

Public Class Form1
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)
        e.Graphics.DrawLine(Pens.Red, 1, 1, 100, 100)
    End Sub
End Class

хотя эффект один. 

А вот, если ты однократно прорисуешь(хоть по клику, хоть как) то при следующей перерисовке формы линия пропадёт. 

Кроме того, если перерисовываться будет не вся форма, а только её часть(например если на переднем плане другая форма закроет часть твоей) то та часть, которая перерисуется сотрёт твой рисунок, а остальное останется. Поэтому надо либо переопределять метод(как показано), либо делать это в обработчике события Paint(в случае, когда нет доступа к Protected методам). 


Автор: kobalt 28.10.2008, 10:18
Вставлял примеры в VB - работает , но как - до конца не разобрался...

Пытался изменить координаты рисуемых линий - ничего не получается.

Переделал вопрос:

Код

  Dim x As Integer = 100
    Dim y As Integer = 100

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

        ' процедура расчета координат точек
        Rashet_koord()

        ' процедура рисования линий
        Ris_line()
    End Sub

    Sub Rashet_koord()
        x = x + 10
    End Sub

    Sub Ris_line()
        Dim graf As Graphics = Me.CreateGraphics
        graf.Clear(System.Drawing.Color.Gray)       ' стираю все старое изображение
        graf.DrawLine(Pens.Black, 10, 0, 10, 100)   ' рисую ось 
        graf.DrawLine(Pens.Red, 10, 0, x, y)        ' рисую график
    End Sub



задача все та же - рисование линии до нажатия кнопки.
вопрос по моей процедуре Ris_line() - нужно ли в ней объявлять каждый раз перед рисаванием  Dim graf As Graphics = Me.CreateGraphics?
может это где то раньше надо сделать 1 раз?
Как сделать правильно?


Автор: diadiavova 28.10.2008, 13:38
Вот честно говоря, даже не знаю что и ответить. Вроде всё написал, думал, что понятно. Нужно, чтобы рисовалось всё надо завязать на методе OnPaint. Нужно из своего метода прорисовать - вызывай свой метод из OnPaint. Нужно работать с Graphics - передай всё что надо в качестве аргумента
Код

Public Class Form1
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)
            Ris_line(e.Graphics)
    End Sub

      Sub Ris_line(ByVal g As Graphics)
        g.Clear(System.Drawing.Color.Gray)       ' стираю все старое изображение
        g.DrawLine(Pens.Black, 10, 0, 10, 100)   ' рисую ось 
        g.DrawLine(Pens.Red, 10, 0, x, y)        ' рисую график
    End Sub
End Class

Свою процедуру расчёта можешь вызывать при прорисовке из метода, который её выполняет.

Автор: kipelovets 28.10.2008, 14:46
попробую объяснить понятнее.
в определенные моменты времени: при запуске приложения, когда твоя форма изменяет размер, восстанавливается из свернутого состояния, когда ее перекрывают другие формы, - происходит перерисовка содержимого формы. при этом ей плевать на линии, которые ты там раньше нарисовал, и они конечно стираются. для того, чтобы избежать этого - чтобы линии оставались после перерисовки, которую инициирует Windows, - нужно самому рисовать свои линии каждый раз когда происходит событие OnPaint. тоесть нужно вставить вызов методов, которые рисуют линии в обработчик OnPaint, что и показал diadiavova

Автор: kobalt 28.10.2008, 15:18
Вопрос: Где можно почитать (лучше в книжках -  автор, название) о методе OnPaint

Методом тыка пытался подставить предложенный выше вариант в свою программу. Не получается  smile . 

Хочу чтобы при нажатии кнопки перерисовывалась линия, но уже с новыми значениями точек.
Код

 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        x = x + 10
        ...........

    End Sub



 smile 

Автор: diadiavova 28.10.2008, 15:45
Если при перерисовке учтены новые значения точек, то для вызова перерисовки по нажатию кнопки просто надо вызвать метод Invalidate.

Добавлено через 1 минуту и 3 секунды
Код

 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        x = x + 10
        Me.Invalidate()
    End Sub

Автор: kobalt 28.10.2008, 15:50
Суперррр!

Похоже на шаманство  smile !

Подставил строчку и все заработало!

А все же - что это было?

Спасибо!

Автор: VK_Techno 28.10.2008, 19:18
Метод Invalidate() принудительно перерисовывает форму. Без него новая линия появилась бы только при первой перерисовке формы, например, при перекрытии её  другим окном.

Автор: diadiavova 28.10.2008, 19:46
Цитата(kobalt @  28.10.2008,  15:50 Найти цитируемый пост)
Похоже на шаманство  smile !

Подставил строчку и все заработало!

А все же - что это было?

Никакого шаманства, просто метод Invalidate, внутренне вызывает метод OnPaint, кроме того, как тут уже говорилось этот метод вызывается при каждой прорисовке формы. Кстати аргумент е содержит и другую полезную информацию, например: перерисовываемую область, так что совсем не обязательно перерисовывать всё, особенно когда надо рисовать много, да и Invalidate - тоже перегружен. И касается всё это не только форм, но и всех контролов вообще. А если нужно рисовать в другом контроле (когда нет доступа к Protected членам, то надо использовать событие Paint.

Автор: kobalt 29.10.2008, 09:51
Спасибо за помощь!

Еще вопрос.
На форме есть 2 элемента Panel.
Вчера попытался размножить готовое решение - ничего не получилось.

нужно чтобы :
1. считаю координаты (знаю как)
2. рисую первый график на Panel1 (не знаю как)
3. считаю другие координаты (знаю как)
4. рисую другой график на Panel2 (не знаю как)

5. элементом TrackBar1 изменяю начальные значения и повторяю п.1 - 5


Автор: diadiavova 29.10.2008, 13:01
Я ведь написал об этом

Цитата(diadiavova @  28.10.2008,  19:46 Найти цитируемый пост)
А если нужно рисовать в другом контроле (когда нет доступа к Protected членам, то надо использовать событие Paint. 

Чтобы нарисовать в другом контроле делать это нужно в обработчике события Paint
то есть вместо 
Код

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)
            Ris_line(e.Graphics)
    End Sub

Надо писать
Код

    Private Sub Panel2_Paint((ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Panel2.Paint
         Ris_line(e.Graphics)
    End Sub

и картинка прорисуется в Panel2. 
PS
Сейчас точно не помню, но если картинка на прорисуется, то после кода прорисовки вызови Refresh
Код

e.Graphics.Refresh()

Автор: kobalt 29.10.2008, 15:17
Спасибо diadiavova за активную помощь.

Всем кому интересно привожу результат - учебный пример показывающий как рисовать в VB.NET

На форму нужно разместить 2 элемента Panel и 1 кнопку.
Перейти на form1.vb  (код  form1) и скопировать туда следующий код:
Код

   Dim x As Integer = 100

    Private Sub Panel1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Panel1.Paint
        Ris_na_panel1(e.Graphics)
    End Sub

    Private Sub Panel2_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Panel2.Paint
        Ris_na_panel2(e.Graphics)
    End Sub

    ' рисование на panel1
    Sub Ris_na_panel1(ByVal g As Graphics)
        g.Clear(System.Drawing.Color.Gray)       ' стираю все старое изображение
        g.DrawLine(Pens.Black, 10, 0, 10, 100)   ' рисую ось 
        g.DrawLine(Pens.Red, 10, 0, x, 100)      ' рисую график 1
    End Sub

    ' рисование на panel2
    Sub Ris_na_panel2(ByVal g As Graphics)
        g.Clear(System.Drawing.Color.Gray)       ' стираю все старое изображение
        g.DrawLine(Pens.Blue, 10, 0, 10, 100)    ' рисую ось 
        g.DrawLine(Pens.Green, 10, 100, x, 1)    ' рисую график 2
    End Sub

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

    ' процедура расчета координат точек и рисования линий
    Sub Rashet_koord_i_Risovanie()
        x = x + 5
        Me.Invalidate()
        Me.Refresh()
    End Sub


При запуске программы в окне в двух панелях выводятся 2 графика
При нажатии кнопки идет расчет новых координат, очищаются  панели и рисуются новые графики.

 smile  smile  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)