やりたいこと
ドキュメントのギャラリーにあるような、データをドラッグしてグラフを表示してみたい

demoを参考にしながら方法を調べてみました

環境
Mac OS
Python 3.10.1
dearpygui 1.3.1
numpy 1.22.1
pip install dearpygui numpy
詳細
ドラッグ&ドロップの実装
まずは簡単なドラッグの実装から
ドラッグ側
ドラッグしたいアイテムにdpg.add_drag_payload()
を設定
引数は
-
parent
: ドラッグしたいアイテムのタグ -
drag_data
: ドラッグして渡したいデータ -
payload_type
: ドラッグ元とドラッグ先の合言葉?のようなもの. 双方に同じ文字列を入力
ドロップ側
アイテム作成時にdrop_callback
, payload_type
引数を入力. それぞれ
-
drop_callback
: ドロップされたときに実行する関数 -
payload_type
: ドラッグ元と同じ文字列
下は10と表示してあるボタンをドラッグして、input_int
アイテムに値を入れています

from typing import Any, Union
import dearpygui.dearpygui as dpg
# ドラッグされたときに呼び出す関数
def input_drop_int(sender: Union[int, str], app_data: Any, user_data) -> None:
"""ドロップされた整数を入力する
Parameters
-----
sender: Union[int, str]
送信元のタグ
app_data: Any
ドロップされたデータ
user_data
"""
dpg.set_value(sender, app_data)
# ##################### 描画設定 #####################
dpg.create_context()
dpg.create_viewport(title='Plot view port', width=800, height=500)
with dpg.window(label='Drag&Drop Window', width=250, height=50):
with dpg.group(horizontal=True):
button = dpg.add_button(label=str(10))
# drag_data: ドラッグ先に渡すデータ, payload_type: ドラッグ元とドラッグ先の合言葉?のようなもの, strを指定
dpg.add_drag_payload(parent=button, drag_data=10, payload_type='Drag&Drop')
input_int = dpg.add_input_int(label='drop', drop_callback=input_drop_int, payload_type='Drag&Drop')
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.start_dearpygui()
dpg.destroy_context()
with dpg.drag_payload()
だとドラッグ中に表示さあれるウィンドウの編集ができます。

with dpg.window(label='Drag&Drop Window', width=250, height=50):
with dpg.group(horizontal=True):
button = dpg.add_button(label=str(10))
# drag_data: ドラッグ先に渡すデータ, payload_type: ドラッグ元とドラッグ先の合言葉?のようなもの, strを指定
with dpg.drag_payload(parent=button, drag_data=10, payload_type='Drag&Drop'):
dpg.add_text(default_value='value:10')
input_int = dpg.add_input_int(label='drop', drop_callback=input_drop_int, payload_type='Drag&Drop')
グラフでやってみる

"""Drag&Dropでグラフをかく
参考
https://github.com/hoffstadt/DearPyGui/blob/master/DearPyGui/dearpygui/demo.py
2205 ~ 2245行目
"""
from typing import Any, Union
import dearpygui.dearpygui as dpg
import numpy as np
# ################# プロットデータ作成 #################
data_len: int = 100
x_data: np.ndarray = np.linspace(-np.pi, np.pi, data_len)
sin_data = np.sin(x_data)
# ドラッグされたときに呼び出す関数
def plot_drag_data(sender: Union[int, str], app_data: Any, user_data) -> None:
"""ドラックされたデータをプロットする
Parameters
-----
sender: Union[int, str]
送信元のタグ
app_data: Any
ドラッグされたデータ
user_data
"""
dpg.add_line_series(app_data[0], app_data[1], label=app_data[2], parent=sender)
# 軸の範囲をデータに合わせる
dpg.fit_axis_data('xaxis')
dpg.fit_axis_data(sender)
# 凡例を右クリックすると追加した線を削除できるボタンを追加
dpg.add_button(label='delete', user_data=dpg.last_item(), parent=dpg.last_item(),
callback=lambda s, a, u: dpg.delete_item(u))
# ##################### 描画設定 #####################
dpg.create_context()
dpg.create_viewport(title='Plot view port', width=800, height=500)
with dpg.window(label='Drag&Drop Window', width=-1, height=-1):
# グループ内のアイテムを横に並べる
with dpg.group(horizontal=True):
# グループ内のアイテムを縦に並べる
with dpg.group():
dpg.add_text(default_value='sources:')
# button追加&ボタンをドラッグしたときの情報追加
dpg.add_button(label='sin', tag='sin_src')
# drag_data: ドラッグ先に渡すデータ, payload_type: ドラッグ元とドラッグ先の合言葉?のようなもの, strを指定
with dpg.drag_payload(parent='sin_src', drag_data=(x_data, sin_data, 'sin'), payload_type='plotting'):
dpg.add_text('sin')
dpg.add_simple_plot(default_value=sin_data)
with dpg.plot(label='Drag&Drop Plot', width=700, height=440):
# 凡例, x軸
dpg.add_plot_legend()
dpg.add_plot_axis(dpg.mvXAxis, label='x', tag='xaxis')
# y軸作成、dropされた時のコールバックを設定、payload_typeはドラッグ元と同じ文字列を指定
dpg.add_plot_axis(dpg.mvYAxis, label='y1', drop_callback=plot_drag_data, payload_type='plotting')
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.start_dearpygui()
dpg.destroy_context()
y2, y3, plot, legendにもドラッグできるように変更
(Demo.py
を参考にしています)

"""
参考
https://github.com/hoffstadt/DearPyGui/blob/master/DearPyGui/dearpygui/demo.py
2205 ~ 2245行目
"""
from typing import Any, Union
import dearpygui.dearpygui as dpg
import numpy as np
# ################# プロットデータ作成 #################
data_len: int = 100
x_data: np.ndarray = np.linspace(-np.pi, np.pi, data_len)
sin_data = np.sin(x_data)
def make_y_data(wave):
freq = dpg.get_value('freq')
if wave == 'sin':
y_data = np.sin(freq * x_data)
else:
y_data = np.cos(freq * x_data)
return y_data, freq
def dropped_axis(sender: Union[int, str], app_data: Any, user_data) -> None:
""""y軸にドロップされたデータを表示する
Parameters
-----
sender: Union[int, str]
送信元のタグ
app_data: Any
ドラッグされたデータ
user_data
"""
y_data, freq = make_y_data(app_data[-1])
dpg.add_line_series(app_data[0], y_data, label=f"{app_data[-1]}({freq}x)", parent=sender)
dpg.fit_axis_data('xaxis')
dpg.fit_axis_data(sender)
# 凡例を右クリックすると追加した線を削除できるボタンを追加
dpg.add_button(label='delete', user_data=dpg.last_item(), parent=dpg.last_item(),
callback=lambda s, a, u: dpg.delete_item(u))
def dropped_legend(sender, app_data, user_data):
"""legendにドロップした時の動作"""
y_data, freq = make_y_data(app_data[-1])
parent = dpg.get_item_info(sender)["parent"]
yaxis2 = dpg.get_item_info(parent)["children"][1][2]
dpg.add_line_series(app_data[0], y_data, label=f"{app_data[-1]}({freq}x)", parent=yaxis2)
dpg.fit_axis_data('xaxis')
dpg.fit_axis_data(yaxis2)
dpg.add_button(label="Delete Series", user_data=dpg.last_item(), parent=dpg.last_item(),
callback=lambda s, a, u: dpg.delete_item(u))
def dropped_plot(sender, app_data, user_data):
"""プロットにドロップした時の動作"""
y_data, freq = make_y_data(app_data[-1])
yaxis1 = dpg.get_item_info(sender)["children"][1][0]
dpg.add_line_series(app_data[0], y_data, label=f"{app_data[-1]}({freq}x)", parent=yaxis1)
dpg.fit_axis_data('xaxis')
dpg.fit_axis_data(yaxis1)
dpg.add_button(label="Delete Series", user_data=dpg.last_item(), parent=dpg.last_item(),
callback=lambda s, a, u: dpg.delete_item(u))
dpg.create_context()
dpg.create_viewport(title='DD', width=800, height=500)
with dpg.window(label='Drag&Drop Window', width=-1, height=-1):
# グループ内のアイテムを横に並べる
with dpg.group(horizontal=True):
# グループ内のアイテムを縦に並べる
with dpg.group():
dpg.add_text(default_value='sources:')
dpg.add_input_int(label='freq', width=80, default_value=1, tag='freq')
# button追加&ボタンをドラッグしたときの情報追加
dpg.add_button(label='sin', tag='sin_src')
with dpg.drag_payload(parent='sin_src', drag_data=(x_data, 'sin'), payload_type='plotting'):
dpg.add_text('sin')
dpg.add_button(label='cos', tag='cos_src')
with dpg.drag_payload(parent='cos_src', drag_data=(x_data, 'cos'), payload_type='plotting'):
dpg.add_text('cos')
with dpg.plot(label='Drag&Drop Plot', width=600, height=375, drop_callback=dropped_plot,
payload_type='plotting'):
# 凡例, x軸
dpg.add_plot_legend(drop_callback=dropped_legend, payload_type='plotting')
dpg.add_plot_axis(dpg.mvXAxis, label='x', tag='xaxis')
# y軸作成、dropされた時のコールバックを設定、payload_typeはドラッグ元と同じ文字列を指定
dpg.add_plot_axis(dpg.mvYAxis, label='y1', drop_callback=dropped_axis, payload_type='plotting')
dpg.add_plot_axis(dpg.mvYAxis, label='y2', drop_callback=dropped_axis, payload_type='plotting')
dpg.add_plot_axis(dpg.mvYAxis, label='y3', drop_callback=dropped_axis, payload_type='plotting')
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.start_dearpygui()
dpg.destroy_context()