绘图-API

DPG有一个低级的绘图API,非常适合于原始绘图、自定义窗口小部件甚至动态绘图。

绘图命令可以添加到DrawList、VIEPORT_DrawList或窗口等容器中。

通过调用以下方法创建一个绘图列表项 add_drawlist 然后,可以通过调用它们各自的绘制命令来添加项。图形的原点位于左上角,y轴指向下方。

坐标系是右手坐标系,x轴指向左侧,y轴指向下方,z轴指向屏幕。

Code

import dearpygui.dearpygui as dpg

dpg.create_context()

with dpg.window(label="Tutorial"):

    with dpg.drawlist(width=300, height=300):  # or you could use dpg.add_drawlist and set parents manually

        dpg.draw_line((10, 10), (100, 100), color=(255, 0, 0, 255), thickness=1)
        dpg.draw_text((0, 0), "Origin", color=(250, 250, 250, 255), size=15)
        dpg.draw_arrow((50, 70), (100, 65), color=(0, 200, 255), thickness=1, size=10)

dpg.create_viewport(title='Custom Title', width=800, height=600)
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.start_dearpygui()
dpg.destroy_context()

Results

https://raw.githubusercontent.com/hoffstadt/DearPyGui/assets/examples_wiki_0.8.x/draw_items.PNG

图层

图纸列表也可以包含层。层是对图形项进行分组以更好地控制隐藏、Z排序等的有效方法。

1.1中的新功能 。层可用于辅助执行某些3D操作。请参阅下面的“3D操作”部分。

Code

import dearpygui.dearpygui as dpg

dpg.create_context()

def toggle_layer2(sender):
    show_value = dpg.get_value(sender)
    dpg.configure_item("layer2", show=show_value)

with dpg.window(label="Tutorial"):
    dpg.add_checkbox(label="show layer", callback=toggle_layer2, default_value=True)

    with dpg.drawlist(width=300, height=300):

        with dpg.draw_layer():
            dpg.draw_line((10, 10), (100, 100), color=(255, 0, 0, 255), thickness=1)
            dpg.draw_text((0, 0), "Origin", color=(250, 250, 250, 255), size=15)
            dpg.draw_arrow((50, 70), (100, 65), color=(0, 200, 255), thickness=1, size=10)

        with dpg.draw_layer(tag="layer2"):
            dpg.draw_line((10, 60), (100, 160), color=(255, 0, 0, 255), thickness=1)
            dpg.draw_arrow((50, 120), (100, 115), color=(0, 200, 255), thickness=1, size=10)

dpg.create_viewport(title='Custom Title', width=800, height=600)
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.start_dearpygui()
dpg.destroy_context()

图像

绘图列表可以显示PNG、JPEG或BMP类型的图像(请参见 纹理和图像 以了解更多详细信息)。使用DRAW_IMAGE添加图像。

使用关键字 pminpmax 我们可以定义矩形的左上角和右下角区域,图像将绘制到画布上。图像将缩放以适合指定区域。

使用关键字 uv_minuv_max 我们可以指定规格化的纹理坐标,以仅使用图像上区域的一部分。默认为uv_min= [0,0] 和UV_max= [1,1] 将在UV_MIN=时显示整个图像 [0,0] UV_max= [0.5,0.5] 将仅显示绘图的第一个四分之一。

为了能够演示这些功能,您必须将目录更新为计算机上的映像目录,例如 SpriteMapExample.png

Code

import dearpygui.dearpygui as dpg

dpg.create_context()

width, height, channels, data = dpg.load_image('SpriteMapExample.png') # 0: width, 1: height, 2: channels, 3: data

with dpg.texture_registry():
    dpg.add_static_texture(width, height, data, tag="image_id")

with dpg.window(label="Tutorial"):

    with dpg.drawlist(width=700, height=700):

        dpg.draw_image("image_id", (0, 400), (200, 600), uv_min=(0, 0), uv_max=(1, 1))
        dpg.draw_image("image_id", (400, 300), (600, 500), uv_min=(0, 0), uv_max=(0.5, 0.5))
        dpg.draw_image("image_id", (0, 0), (300, 300), uv_min=(0, 0), uv_max=(2.5, 2.5))

dpg.create_viewport(title='Custom Title', width=800, height=600)
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.start_dearpygui()
dpg.destroy_context()

Results

https://raw.githubusercontent.com/hoffstadt/DearPyGui/assets/examples_wiki_0.8.x/draw_images.PNG

视窗和视窗

还可以将所有相同的DRAW_*绘图命令与作为父窗口的窗口一起使用。同样,您可以使用viewport_Drawlist绘制到视区前景或背景。

Code

import dearpygui.dearpygui as dpg

dpg.create_context()

# creating font and back viewport drawlists
with dpg.viewport_drawlist():
    dpg.draw_circle((100, 100), 25, color=(255, 255, 255, 255))

dpg.add_viewport_drawlist(front=False, tag="viewport_back")

dpg.draw_circle((200, 200), 25, color=(255, 255, 255, 255), parent="viewport_back")

with dpg.window(label="Tutorial", width=300, height=300):
    dpg.add_text("Move the window over the drawings to see the effects.", wrap=300)
    dpg.draw_circle((100, 100), 25, color=(255, 255, 255, 255))

dpg.create_viewport(title='Custom Title', width=800, height=600)
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.start_dearpygui()
dpg.destroy_context()

Results

https://raw.githubusercontent.com/hoffstadt/DearPyGui/assets/examples_wiki_0.8.x/draw_viewport.gif

场景图

1.1中的新功能 。对于更复杂的绘图,您可以使用 draw_node 项目。绘制节点用于将变换矩阵与一组绘制项相关联。您可以使用 apply_transform 若要将变换矩阵应用于节点,请执行以下操作。这个矩阵将被用来乘以每个子绘图项目的点数。如果一个子节点是另一个绘制节点,则矩阵将连接在一起。

Code

import dearpygui.dearpygui as dpg
import math

dpg.create_context()
dpg.create_viewport()
dpg.setup_dearpygui()

with dpg.window(label="tutorial", width=550, height=550):

    with dpg.drawlist(width=500, height=500):

        with dpg.draw_node(tag="root node"):
            dpg.draw_circle([0, 0], 150, color=[0, 255, 0])                      # inner planet orbit
            dpg.draw_circle([0, 0], 200, color=[0, 255, 255])                    # outer planet orbit
            dpg.draw_circle([0, 0], 15, color=[255, 255, 0], fill=[255, 255, 0]) # sun

            with dpg.draw_node(tag="planet node 1"):
                dpg.draw_circle([0, 0], 10, color=[0, 255, 0], fill=[0, 255, 0]) # inner planet
                dpg.draw_circle([0, 0], 25, color=[255, 0, 255])                 # moon orbit path

                with dpg.draw_node(tag="planet 1, moon node"):
                    dpg.draw_circle([0, 0], 5, color=[255, 0, 255], fill=[255, 0, 255]) # moon

            with dpg.draw_node(tag="planet node 2"):
                dpg.draw_circle([0, 0], 10, color=[0, 255, 255], fill=[0, 255, 255]) # outer planet
                dpg.draw_circle([0, 0], 25, color=[255, 0, 255])                     # moon 1 orbit path
                dpg.draw_circle([0, 0], 45, color=[255, 255, 255])                   # moon 2 orbit path

                with dpg.draw_node(tag="planet 2, moon 1 node"):
                    dpg.draw_circle([0, 0], 5, color=[255, 0, 255], fill=[255, 0, 255]) # moon 1

                with dpg.draw_node(tag="planet 2, moon 2 node"):
                    dpg.draw_circle([0, 0], 5, color=[255, 255, 255], fill=[255, 255, 255]) # moon 2

planet1_distance = 150
planet1_angle = 45.0
planet1_moondistance = 25
planet1_moonangle = 45

planet2_distance = 200
planet2_angle = 0.0
planet2_moon1distance = 25
planet2_moon1angle = 45
planet2_moon2distance = 45
planet2_moon2angle = 120

dpg.apply_transform("root node", dpg.create_translation_matrix([250, 250]))
dpg.apply_transform("planet node 1", dpg.create_rotation_matrix(math.pi*planet1_angle/180.0 , [0, 0, -1])*dpg.create_translation_matrix([planet1_distance, 0]))
dpg.apply_transform("planet 1, moon node", dpg.create_rotation_matrix(math.pi*planet1_moonangle/180.0 , [0, 0, -1])*dpg.create_translation_matrix([planet1_moondistance, 0]))
dpg.apply_transform("planet node 2", dpg.create_rotation_matrix(math.pi*planet2_angle/180.0 , [0, 0, -1])*dpg.create_translation_matrix([planet2_distance, 0]))
dpg.apply_transform("planet 2, moon 1 node", dpg.create_rotation_matrix(math.pi*planet2_moon1distance/180.0 , [0, 0, -1])*dpg.create_translation_matrix([planet2_moon1distance, 0]))
dpg.apply_transform("planet 2, moon 2 node", dpg.create_rotation_matrix(math.pi*planet2_moon2angle/180.0 , [0, 0, -1])*dpg.create_translation_matrix([planet2_moon2distance, 0]))

dpg.show_viewport()
while dpg.is_dearpygui_running():
    dpg.render_dearpygui_frame()

dpg.destroy_context()

3D操作

1.1中的新功能 。版本 1.1 向层添加了3个新选项, perspective_dividedepth_clipping ,以及 cull_mode

当透视分割设置为 True ,每个点的x、y和z分量除以变换后的w分量。

当深度剪裁设置为 True ,当点在使用以下设置的剪辑空间集之外时将被剪裁 set_clip_space 。设置剪辑空间将缩放和变换点。缩放基于规格化坐标(使用透视矩阵或地形图矩阵)。

消隐模式用于激活正面/背面消隐。

矩阵是列主数。后乘法用于缩放,然后旋转,然后使用变换:Transform=Translate 旋转 比例。

提供以下矩阵帮助器函数: create_rotation_matrix - create_translation_matrix - create_scale_matrix - create_lookat_matrix - create_perspective_matrix - create_orthographic_matrix - create_fps_matrix

Code

import dearpygui.dearpygui as dpg
import math

dpg.create_context()
dpg.create_viewport()
dpg.setup_dearpygui()

size = 5
verticies = [
        [-size, -size, -size],  # 0 near side
        [ size, -size, -size],  # 1
        [-size,  size, -size],  # 2
        [ size,  size, -size],  # 3
        [-size, -size,  size],  # 4 far side
        [ size, -size,  size],  # 5
        [-size,  size,  size],  # 6
        [ size,  size,  size],  # 7
        [-size, -size, -size],  # 8 left side
        [-size,  size, -size],  # 9
        [-size, -size,  size],  # 10
        [-size,  size,  size],  # 11
        [ size, -size, -size],  # 12 right side
        [ size,  size, -size],  # 13
        [ size, -size,  size],  # 14
        [ size,  size,  size],  # 15
        [-size, -size, -size],  # 16 bottom side
        [ size, -size, -size],  # 17
        [-size, -size,  size],  # 18
        [ size, -size,  size],  # 19
        [-size,  size, -size],  # 20 top side
        [ size,  size, -size],  # 21
        [-size,  size,  size],  # 22
        [ size,  size,  size],  # 23
    ]

colors = [
        [255,   0,   0, 150],
        [255, 255,   0, 150],
        [255, 255, 255, 150],
        [255,   0, 255, 150],
        [  0, 255,   0, 150],
        [  0, 255, 255, 150],
        [  0,   0, 255, 150],
        [  0, 125,   0, 150],
        [128,   0,   0, 150],
        [128,  70,   0, 150],
        [128, 255, 255, 150],
        [128,   0, 128, 150]
    ]

with dpg.window(label="tutorial", width=550, height=550):

    with dpg.drawlist(width=500, height=500):

        with dpg.draw_layer(tag="main pass", depth_clipping=True, perspective_divide=True, cull_mode=dpg.mvCullMode_Back):

            with dpg.draw_node(tag="cube"):

                dpg.draw_triangle(verticies[1],  verticies[2],  verticies[0], color=[0,0,0.0],  fill=colors[0])
                dpg.draw_triangle(verticies[1],  verticies[3],  verticies[2], color=[0,0,0.0],  fill=colors[1])
                dpg.draw_triangle(verticies[7],  verticies[5],  verticies[4], color=[0,0,0.0],  fill=colors[2])
                dpg.draw_triangle(verticies[6],  verticies[7],  verticies[4], color=[0,0,0.0],  fill=colors[3])
                dpg.draw_triangle(verticies[9],  verticies[10], verticies[8], color=[0,0,0.0],  fill=colors[4])
                dpg.draw_triangle(verticies[9],  verticies[11], verticies[10], color=[0,0,0.0], fill=colors[5])
                dpg.draw_triangle(verticies[15], verticies[13], verticies[12], color=[0,0,0.0], fill=colors[6])
                dpg.draw_triangle(verticies[14], verticies[15], verticies[12], color=[0,0,0.0], fill=colors[7])
                dpg.draw_triangle(verticies[18], verticies[17], verticies[16], color=[0,0,0.0], fill=colors[8])
                dpg.draw_triangle(verticies[19], verticies[17], verticies[18], color=[0,0,0.0], fill=colors[9])
                dpg.draw_triangle(verticies[21], verticies[23], verticies[20], color=[0,0,0.0], fill=colors[10])
                dpg.draw_triangle(verticies[23], verticies[22], verticies[20], color=[0,0,0.0], fill=colors[11])

x_rot = 10
y_rot = 45
z_rot = 0

view = dpg.create_fps_matrix([0, 0, 50], 0.0, 0.0)
proj = dpg.create_perspective_matrix(math.pi*45.0/180.0, 1.0, 0.1, 100)
model = dpg.create_rotation_matrix(math.pi*x_rot/180.0 , [1, 0, 0])*\
                        dpg.create_rotation_matrix(math.pi*y_rot/180.0 , [0, 1, 0])*\
                        dpg.create_rotation_matrix(math.pi*z_rot/180.0 , [0, 0, 1])

dpg.set_clip_space("main pass", 0, 0, 500, 500, -1.0, 1.0)
dpg.apply_transform("cube", proj*view*model)

dpg.show_viewport()
while dpg.is_dearpygui_running():
    dpg.render_dearpygui_frame()

dpg.destroy_context()

3D操作限制

1.1中的新功能 。绘图API 3D操作不是硬件加速的(这将在DearPy3D中引入)。这个API是针对‘light’3D操作的。在使用绘图API执行3D操作时,可能会遇到一些问题。

问题1:Z订购

在当前的API中,用户需要负责正确的Z排序。解决这个问题的推荐方法是使用“画家算法”。基本上,只需按适当的深度顺序对物品进行排序即可。

总的来说,这不是最好的解决方案。我们更喜欢使用适当的深度缓冲,但这需要像素级别的控制,这在此API中是不实用的。

第2期:透视纹理校正

使用DRAW_IMAGE_QUAD时,以锐角查看图像将使图像变形。这是因为纹理坐标在规格化设备坐标空间中线性内插。

目前还没有实际的解决方案,但可以尝试将四合院分成几个较小的四合院。实际的解决方案需要像素级控制,这在此API中是不实用的。

问题3:剔除

目前,仅为三角形设置消隐。

亲爱的Py3D和软件渲染器

上述所有问题都将在 亲爱的Py3D 。在此之前 亲爱的Py3D ,我们还将介绍一个软件渲染器, 亲爱的皮吉 这将解决上述问题。