PureBasic

Руководство - Отображение графики & простых рисунков

В этом примере показано, как создать простой рисунок. Он использует команды 2D рисования , для вывода двух синусоидальных волн на разных частотах и показывает гармонику, создаваемую объединением двух волн. Он использует процедуры, которые мы обсудим более подробно позже, чтобы разбить всё рисование на три самостоятельные задачи:

Рисование осей - демонстрирует команду Line().
Рисование легенды - демонстрирует команды Box() и DrawText().
Рисование форм сигнала - демонстрирует команду LineXY() и показывает, как использовать цвет.

; Окно
Enumeration
    #WinHarmonic
EndEnumeration

; Гаджеты
Enumeration
    #txtPlot1
    #cboPlot1
    #txtPlot2
    #cboPlot2
    #imgPlot
EndEnumeration

; Изображение
Enumeration
    #drgPlot
EndEnumeration

; Размеры изображения используются в нескольких местах, поэтому определяем константы.
#imgPlotX = 8
#imgPlotY = 40
#imgPlotW = 745
#imgPlotH = 645

; Переменные событий
Define.l Event, EventWindow, EventGadget, EventType, EventMenu

; Реализация
Procedure CreateWindow()
    ; Создает окно и Гаджеты.

    If OpenWindow(#WinHarmonic, 30, 30, #imgPlotW + 20, #imgPlotH + 55, "Harmonics", #PB_Window_SystemMenu - #PB_Window_MinimizeGadget - #PB_Window_TitleBar)

        ; Это не визуальный Гаджет, используемый для рисования изображения, позже его содержимое будет отображаться в #imgPlot.
        CreateImage(#drgPlot, #imgPlotW - 5, #imgPlotH - 5, 24)

        ; Метка для точки 1 на combo.
        TextGadget(#txtPlot1, 2, 5, 50, 25, "Точка 1:")

        ; Точка 1 на combo.
        ComboBoxGadget(#cboPlot1, 55, 5, 150, 25)
        AddGadgetItem(#cboPlot1, 0, "Sin(X)")
        AddGadgetItem(#cboPlot1, 1, "Sin(X * 2)")
        AddGadgetItem(#cboPlot1, 2, "Sin(X * 3)")
        AddGadgetItem(#cboPlot1, 3, "Sin(X * 4)")
        AddGadgetItem(#cboPlot1, 4, "Sin(X * 5)")
        AddGadgetItem(#cboPlot1, 5, "Sin(X * 6)")

        ; Выбор Sin(X)
        SetGadgetState(#cboPlot1, 0)

        ; Метка для точки 2 на combo.
        TextGadget(#txtPlot2, 230, 5, 50, 25, "Точка 2:")

        ; Точка 2 на combo.
        ComboBoxGadget(#cboPlot2, 280, 5, 150, 25)
        AddGadgetItem(#cboPlot2, 0, "Sin(X)")
        AddGadgetItem(#cboPlot2, 1, "Sin(X * 2)")
        AddGadgetItem(#cboPlot2, 2, "Sin(X * 3)")
        AddGadgetItem(#cboPlot2, 3, "Sin(X * 4)")
        AddGadgetItem(#cboPlot2, 4, "Sin(X * 5)")
        AddGadgetItem(#cboPlot2, 5, "Sin(X * 6)")

        ; Выбор Sin(X * 2), в противном случае начальный дисплей немножко неинтересный.
        SetGadgetState(#cboPlot2, 1)

        ; Создание Гаджета визуального изображения в окне.
        ImageGadget(#imgPlot, #imgPlotX, #imgPlotY, #imgPlotW, #imgPlotH, 0, #PB_Image_Border)

    EndIf

EndProcedure

Procedure PlotAxes()
    ; Рисует оси на изображении #drgPlot.

    ; Направляет последующие команды рисования в #drgPlot.
    StartDrawing(ImageOutput(#drgPlot))

    ; Нарисовать белый фон.
    Box(0, 0, ImageWidth(#drgPlot), ImageHeight(#drgPlot), RGB(255, 255, 255))

    ; Нарисовать оси черным цветом.
    Line(1, 1, 1, ImageHeight(#drgPlot) - 2, RGB(0, 0, 0))
    Line(1, (ImageHeight(#drgPlot) - 2) /2, ImageWidth(#drgPlot) -2, 1, RGB(0, 0, 0))

    ; Закончить вывод команд рисования, в данном случае в #drgPlot.
    StopDrawing()
EndProcedure

Procedure PlotLegend(alngPlot1, alngPlot2)
    ; Рисует легенду изображения #drgPlot.

    Protected.s strFunc1, strFunc2, strLabel1, strLabel2, strLabel3

    ; Установить текст метки 1.
    If alngPlot1 = 0
        strFunc1 = "Sin(X)"
    Else
        strFunc1 = "Sin(X * " + StrU(alngPlot1 + 1) + ")"
    EndIf

    ; Установить текст метки 2.
    If alngPlot2 = 0
        strFunc2 = "Sin(X)"
    Else
        strFunc2 = "Sin(X * " + StrU(alngPlot2 + 1) + ")"
    EndIf

    ; Установить текст метки.
    strLabel1 = "Y = " + strFunc1
    strLabel2 = "Y = " + strFunc2
    strLabel3 = "Y = " + strFunc1 + " + " + strFunc2

    ; Рисует легенду.
    StartDrawing(ImageOutput(#drgPlot))

    ; Прямоугольник.
    DrawingMode(#PB_2DDrawing_Outlined)
    Box(20, 10, TextWidth(strLabel3) + 85, 80, RGB(0, 0, 0))

    ; Метка 1.
    Line(30, 30, 50, 1, RGB(0, 0, 255))
    DrawText(95, 22, strLabel1, RGB(0, 0, 0), RGB(255, 255, 255))

    ; Метка 2.
    Line(30, 50, 50, 1, RGB(0, 255, 200))
    DrawText(95, 42, strLabel2, RGB(0, 0, 0), RGB(255, 255, 255))

    ; Метка 3.
    Line(30, 70, 50, 1, RGB(255, 0, 0))
    DrawText(95, 62, strLabel3, RGB(0, 0, 0), RGB(255, 255, 255))

    StopDrawing()

EndProcedure

Procedure PlotFunction(alngPlot1, alngPlot2)
    ; Рисует осциллограммы на изображении #drgPlot.

    Protected.l lngSX, lngEX
    Protected.f fltRad1, fltRad2, fltSY1, fltEY1, fltSY2, fltEY2, fltSY3, fltEY3

    StartDrawing(ImageOutput(#drgPlot))

    ; Определить начальные точки старта для каждой волны.
    lngSX = 1
    fltSY1 = ImageHeight(#drgPlot) / 2
    fltSY2 = fltSY1
    fltSY3 = fltSY1

    ; Формирует волновые формы.
    For lngEX = 1 To 720
        ; Синусоидальная функция работает в радианах, поэтому конвертируем из градусов и вычисляем синус.

        ; Функция 1
        If alngPlot1 = 0
            fltRad1 = Sin(Radian(lngEX))
        Else
            ; Если функция должна иметь множитель, то учитывает это.
            fltRad1 = Sin(Radian(lngEX) * (alngPlot1 + 1))
        EndIf

        ; Функция 2
        If alngPlot2 = 0
            fltRad2 = Sin(Radian(lngEX))
        Else
            fltRad2 = Sin(Radian(lngEX) * (alngPlot2 + 1))
        EndIf

        ; Точка функции 1, синего цвета.
        ; Вычисляет конечную точку Y.
        fltEY1 = (ImageHeight(#drgPlot) / 2) + (fltRad1 * 100)
        ; Рисует линию от стартовой точки до конечной точки.
        LineXY(lngSX, fltSY1, lngEX, fltEY1, RGB(0, 0, 255))
        ; Обновить значение следующей начальной точки Y, от текущей конечной точки Y.
        fltSY1 = fltEY1

        ; Точка функции 2, зелёного цвета.
        fltEY2 = (ImageHeight(#drgPlot) / 2) + (fltRad2 * 100)
        LineXY(lngSX, fltSY2, lngEX, fltEY2, RGB(0, 255, 200))
        fltSY2 = fltEY2

        ; Точка гармоники, красного цвета.
        fltEY3 = (ImageHeight(#drgPlot) / 2) + ((fltRad1 + fltRad2) * 100)
        LineXY(lngSX, fltSY3, lngEX, fltEY3, RGB(255, 0, 0))
        fltSY3 = fltEY3

        ; Обновить значение следующей начальной точки X, от текущей конечной точки X.
        lngSX = lngEX
    Next lngEX

    StopDrawing()

EndProcedure

;- Главный код.
CreateWindow()
PlotAxes()
PlotLegend(GetGadgetState(#cboPlot1), GetGadgetState(#cboPlot2))
PlotFunction(GetGadgetState(#cboPlot1), GetGadgetState(#cboPlot2))

; Перезагрузите Гаджет изображения, теперь с завершенным рисунком.
ImageGadget(#imgPlot, #imgPlotX, #imgPlotY, #imgPlotW, #imgPlotH, ImageID(#drgPlot), #PB_Image_Border)

;- Цикл событий
Repeat
    Event = WaitWindowEvent()
    EventWindow = EventWindow()
    EventGadget = EventGadget()
    EventType = EventType()

    Select Event
        Case #PB_Event_Gadget
            If EventGadget = #txtPlot1 Or EventGadget = #txtPlot2
                ; Ничего не делать.
            ElseIf EventGadget = #imgPlot
                ; Ничего не делать.
            ElseIf EventGadget = #cboPlot1 Or EventGadget = #cboPlot2
                ; Если один из списков изменился, перерисует изображение.
                PlotAxes()
                PlotLegend(GetGadgetState(#cboPlot1), GetGadgetState(#cboPlot2))
                PlotFunction(GetGadgetState(#cboPlot1), GetGadgetState(#cboPlot2))
                ImageGadget(#imgPlot, #imgPlotX, #imgPlotY, #imgPlotW, #imgPlotH, ImageID(#drgPlot), #PB_Image_Border)
            EndIf
        Case #PB_Event_CloseWindow
            If EventWindow = #WinHarmonic
                CloseWindow(#WinHarmonic)
                Break
            EndIf
    EndSelect
ForEver

Навигация Руководства

< Создание графического интерфейса пользователя (GUI) - Обзор - Структурирование кода в Процедурах >