An object-oriented interface for Dear PyGui.
Dear PyGui is an excellent Python GUI framework built on top of the Dear ImGui immediate-mode lightweight graphical interface library for C++. Dear PyGui itself is mostly a C++/CPython library with a thin scripting layer as it's primary interface.
This project aims to implement a pure-Python interface to Dear PyGui that takes full advantage of the Python language to provide a concise and ergonomic API.
Documentation (on ReadTheDocs) can be found here.
DearPyGui-Obj makes using DPG more concise and intuitive by allowing you to get and set widget properties using attributes. Setting the callback for a
widget is easy using the callback
decorator.
If you've used Dear PyGui, using the object library should be familiar.
from dearpygui_obj import start_gui
from dearpygui_obj import colors
from dearpygui_obj.widgets import *
with Window('Example'):
text = Text('Edit me using the controls below!', color=colors.salmon)
Separator()
text_input = InputText('text content', text.value)
text_color = ColorEdit('text color', text.color)
@text_input.callback
def callback():
text.value = text_input.value
@text_color.callback
def callback():
text.color = text_color.value
start_gui()
from dearpygui_obj import start_gui
from dearpygui_obj.widgets import *
from dearpygui_obj.plots.dataseries import *
with Window('Example') as win:
data = [ (-1, -9), (1, -4), (3, 11), (4, 5), (9, 7) ]
lineseries = LineSeries('example', data)
## plot data series support indexing and all other MutableSequence methods
p1, p2 = lineseries[-2], lineseries[-1]
print('slope:', (p2.y - p1.y)/(p2.x - p1.x)) # elements are named tuples
lineseries.append((10, 2)) # but methods will accept any compatible sequence
## you can also access and modify data as individual 1D sequences,
## as long as the length does not change
print(*lineseries.y[0:3]) # prints -9 -4 11
lineseries.y[3] += 1
lineseries.y[0:3] = (-4, 7, -2)
lineseries.x[:] = [1, 2, 3, 4, 5, 6]
#lineseries.x = [1, 2, 3] # TypeError: cannot change length of individual DataSeries field
plot = Plot()
plot.add_dataseries(lineseries)
start_gui()
from dearpygui_obj import start_gui
from dearpygui_obj.widgets import *
with Window('Example') as win:
table = Table(['col 1', 'col 2', 'col 3', 'col 4'])
table[:, :] = [
['a', 'b', 'c', 'd'],
['e', 'f', 'g', 'h'],
['i', 'j', 'k', 'l'],
['m', 'n', 'o', 'p'],
]
btn = Button('Select Checkerboard')
@btn.callback
def callback():
table.selected[::2, ::2] = True
table.selected[1::2, 1::2] = True
start_gui()
from dataclasses import dataclass
from dearpygui_obj import start_gui
from dearpygui_obj.widgets import *
@dataclass
class Person:
firstname: str
lastname: str
class PersonInfo(UserWidget):
def __setup_content__(self, person: Person):
Separator()
with group_horizontal():
self.selected_chk = Checkbox()
Button(arrow=ButtonArrow.Up, callback=self.move_up)
Button(arrow=ButtonArrow.Down, callback=self.move_down)
Text(f'First name: {person.firstname}')
Text(f'Last name: {person.lastname}')
@property
def selected(self) -> bool:
return self.selected_chk.value
with Window('Person List Example'):
with Group() as container:
pass
Separator()
remove_btn = Button('Remove Selected')
add_btn = Button('Add Person')
fname_inp = InputText('First name')
lname_inp = InputText('Last name')
@remove_btn.callback
def callback():
for child in container.iter_children():
if child.selected:
child.delete()
@add_btn.callback
def callback():
person = Person(fname_inp.value, lname_inp.value)
PersonInfo.add_to(container, person)
fname_inp.value = ''
lname_inp.value = ''
start_gui()
This is the same dynamic drawing example given in the DPG Wiki. You can compare it with the original code.
from dearpygui_obj import start_gui
from dearpygui_obj import colors
from dearpygui_obj.widgets import *
counter = 0
modifier = 2
with Window("Tutorial", size=(800, 800)):
canvas = Drawing(size=(700, 700))
circle = canvas.draw_circle((0, 0), 5, colors.from_rgba8(255, 255, 255))
@dearpygui_obj.set_render_callback
def on_render():
global counter, modifier
counter += 1
if counter < 300:
modifier += 1
elif counter < 600:
modifier -= 1
else:
counter = 0
modifier = 2
circle.center = (15 + modifier*1.25, 15 + modifier*1.25)
circle.color = colors.from_rgba8(
255 - modifier*.8, 255 - modifier*.8, 255 - modifier*.3,
)
circle.radius = 15 + modifier/2
circle.segments = round(35-modifier/10)
start_gui()
from dearpygui_obj import start_gui
from dearpygui_obj import colors
from dearpygui_obj.widgets import *
with Window('Example') as win:
## See what config properties a widget has in the REPL
Button.get_config_properties() # Returns ['arrow', 'enabled', 'height', ...]
## There are many small ergonomic improvements to the API of various widgets
## For example, setting arrow buttons is just an Enum instead of two
## separate properties
btn = Button(arrow=ButtonArrow.Right)
@btn.callback
def callback():
if btn.arrow:
btn.arrow = None
btn.label = 'Not an arrow button anymore!'
## Colors
red = Text('This text is red.', color=colors.red) # preset HTML colors
green = Text('This text is green.', color=colors.from_hex('#00FF00'))
## Radio buttons, combo boxes, and list widgets are mutable sequences
radio = RadioButtons(['Apple', 'Orange'])
radio[0] = 'Banana'
radio.remove('Orange')
radio.extend(['Pear', 'Grape'])
del radio[-1]
## You can add widgets after creating the GUI using methods instead of keywords
add_text = Button.add_to(win, 'Add Label') # add to the end of a container
@add_text.callback
def callback():
Text.insert_before(add_text, 'Insert before.') # insert before a widget
start_gui()
DearPyGui-Obj aims to be fully backwards compatible with Dear PyGui. This means that you can freely mix code that uses both DearPyGui and DearPyGui-Obj without issues. Wherever possible, widget classes are designed to draw all of their state from DPG so that there is no possibility of invalidation. You can even create object instances for existing widgets that were created in vanilla DearPyGui.
This project is currently in the early implementation stage, and a lot of features still need to be implemented. Even the current name for the project is provisional and may change.
Requirements
- Python 3.8 64-bit
- dearpygui 0.6.x
You can install from TestPyPI:
pip install -i https://test.pypi.org/simple/ dearpygui-obj
Or you can simply copy the dearpygui_obj
package somewhere where Python can find it.
DearPyGui-Obj will be available on PyPI proper once it has reached a fuller level of feature-completeness.
DearPyGui-Obj is licensed under the MIT License.