hoffstadt / DearPyGui

Dear PyGui: A fast and powerful Graphical User Interface Toolkit for Python with minimal dependencies
https://dearpygui.readthedocs.io/en/latest/
MIT License
12.6k stars 668 forks source link

Support for font awesome and similar unicode based icon library #2334

Open szokejokepu opened 1 month ago

szokejokepu commented 1 month ago

Is your feature request related to a problem? Please describe. I'm trying to build a more modern-looking GUI, where it is a must to give some hints with icons on buttons, like a play button or stop button. Although as I see in the documentation the DearPyGUI supports custom fonts. When I import the downloaded otf file of FontAwesome, the icons included do not work. I don't know if this is a bug, or just flat-out not supported behavior. From all the examples I found online, it gave me the impression that not many people use icons with buttons wiht DPG, so I suppose it is not supported. If it IS supported I would be happy if there were a simple example in docs of how to do it, because following the current docs, I cannot display special characters.

Describe the solution you'd like I want to be able to specify simply display icons from fontawesome and/or other icon font libraries in the UI elements.

Describe alternatives you've considered I don't know how to circumvent this.

Additional context Based on the docs, at least one of these attempts should show an icon, and it doesn't.

import dearpygui.dearpygui as dpg
import fontawesome as fa

dpg.create_context()

fontawesome_tag = "font_tag"
fontawesome_tag2 = "font_tag2"
# add a font registry
with dpg.font_registry():
    # first argument ids the path to the .ttf or .otf file
    # based on my understanding, at least one of these examples should be able to generate special characters
    second_font = dpg.add_font("../fonts/fontawesome-free-5.15.4-desktop/otfs/Font Awesome 5 Free-Regular-400.otf", 10,
                               tag=fontawesome_tag)

    with dpg.font("../fonts/fontawesome-free-5.15.4-desktop/otfs/Font Awesome 5 Free-Regular-400.otf", 10,
                  tag=fontawesome_tag2) as font2:
        dpg.add_font_range(0x0000, 0xffff)

with dpg.window(label="Font Example", height=200, width=200):
    dpg.add_button(label=f'\uf164 {fa.icons["thumbs-up"]} Default font')
    b2 = dpg.add_button(label=f'\uf164 {fa.icons["thumbs-up"]} Secondary font')
    b3 = dpg.add_button(label=f'\uf164 {fa.icons["thumbs-up"]} Third font')
    dpg.add_button(label="default")

    # set font of specific widget
    dpg.bind_item_font(b2, second_font)
    dpg.bind_item_font(b3, fontawesome_tag2)

   # in the commandline it plots the special characters
    print("This works", '\uf164')
    print(fa.icons["thumbs-up"])

dpg.show_font_manager()

dpg.create_viewport(title='Custom Title', width=800, height=600)
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.start_dearpygui()
dpg.destroy_context()
v-ein commented 1 month ago

As discussed earlier on Discord, add_font_range has an internal limitation that the start of the range must not be zero. This is hardcoded into Dear ImGui - it uses zero to designate the end of the list, and therefore add_font_range(0, something) effectively gives ImGui what it thinks is an empty list :zany_face:.

Try add_font_range(0x0001, 0xffff) instead. Or even better, use as narrow range as you can (because all those 65K characters will need to be loaded into a texture, and reloaded each time you add a new font - that's yet another quirk of DPG).

szokejokepu commented 3 weeks ago

As discussed earlier on Discord, add_font_range has an internal limitation that the start of the range must not be zero. This is hardcoded into Dear ImGui - it uses zero to designate the end of the list, and therefore add_font_range(0, something) effectively gives ImGui what it thinks is an empty list 🤪.

Try add_font_range(0x0001, 0xffff) instead. Or even better, use as narrow range as you can (because all those 65K characters will need to be loaded into a texture, and reloaded each time you add a new font - that's yet another quirk of DPG).

Thanks for the answer. These minor hacks and quirks would be nice to be reflected in the docs. It is a big ask from a new adopter to read a discord forum for any potential solution, especially since it is not indexed by google, so it is impossible to find. Anyway, the solution you gave me only partially solves my issue. TBH I'm not sure if this is a quirk from Fontawesome or one of DPG, but from the 4 .otf fonts that I loaded, it only succesfully displays the special character from one of them. I'll try to look into this more, but I am in no way a font usage expert, so I have no idea how to really get to the bottom of this.

Also, if I have your attention, I have another question tied to this one. Since I only want to use the special characters which are in the higher range of the font index (like \uF000 and higher), I would wish to load two fonts at the same time. Use the lower range of ASCII characters from the default font, and use the special characters from FontAwesome. Based on the current docs, I don't know how to do this, or if it is even possible.

Thanks for the response!

v-ein commented 3 weeks ago

These minor hacks and quirks would be nice to be reflected in the docs.

Totally agree, but unfortunately doc updates require some time/resources, and therefore don't happen often.

I would wish to load two fonts at the same time. Use the lower range of ASCII characters from the default font, and use the special characters from FontAwesome.

As long as you're not using both icons and text in the same widget (add_button or add_text), you can simply keep two fonts separate, and bind the necessary font to your widget. To include both icons and text in the same caption, you'd need to merge two fonts into one. Dear ImGui supports merging fonts on-the-fly, but DearPyGui does not.

You can probably merge fonts manually in the font editor, or try to use third-party packages to merge them on-the-fly. Somebody mentioned fonttools on Discord (yep, Discord again :joy:).

Also, it should be possible to add support for font merging into DPG (open a pull request), but that would need some experience with DPG, that's for sure.

szokejokepu commented 3 weeks ago

Thanks! I don't think I have the qualifications to do such a pull request, but thank you for the answer nonetheless. I think I'm in the fortunate position where I can use what you suggested, as I don't need to merge two fonts at the same time in one caption. I'll give it try. But as a general feature, I still think it is a good idea to have better support for icons, through fontawesome, or anything else. Modern GUIs are largely controlled by textless buttons using only icons, it would be nice if DPG could make that leap. While it would make it possible to create nicer/more elegant looking and more practical GUIs, I think it might lead to wider adoption as well.

v-ein commented 3 weeks ago

Just curious, what do you mean by saying "to have better support for icons"? Icon fonts are already supported by DPG; so maybe it's something else you have in mind?

szokejokepu commented 3 weeks ago

I don't have much experience with desktop application GUI-s, but I have with web, applications. There, including an icon is as simple as importing a font library up top and then including a tag in a element. It is one import and can be used everywhere, anyone can do it, without knowledge of fonts, and you don't have to manually change styles per elements that use icons vs ones that don't. Preferably, I would like something similarly simple in DPG. The fact that in the showcase gallery, there is a single example that uses buttons with icons (which icons also look manually drawn, and not from a standardized library) I think is proof that using icons in DPG is not very simple and/or intuitive to implement. Maybe I'm missing something, in which case, I would recommend updating the docs with some idiot-proof simple explanations and examples of how to use icons (for example in some buttons), because it doesn't seem easy/intuitive to me. If there is a specific feature to be implemented, to simplify the usage of icons, I would welcome it, but I only see the symptom, I don't know the solution, I'm not knowledgeable enough in this area.

v-ein commented 3 weeks ago
with dpg.font_registry():
    with dpg.font("resources/fonts/microns.ttf", 16, tag="font-icons"):
        dpg.add_font_range(0xe700, 0xe7ff)

...

# Could be anything else, it just demonstrates one possible approach
class Icon():
    COG = "\ue736"
    FLAG = "\ue72e"

...

with dpg.window(...):
    dpg.add_button(label=Icon.COG, callback=show_options)
    dpg.bind_item_font(dpg.last_item(), "font-icons")

All of the above is pretty much "standard" code for DPG, nothing unusual, and looks quite simple to me. You load a font, you bind it to a widget, and you use characters from it. Not much different from what you describe for web apps.

v-ein commented 3 weeks ago

The fact that in the showcase gallery, there is a single example that uses buttons with icons (which icons also look manually drawn, and not from a standardized library)

... is only a proof that nobody has cared enough to add icon-rich apps to the gallery :joy:. Moreover, not every app needs icons. I've created a couple of apps with DPG where I didn't need icons, and yet another app where I did use icons and had no problems with them.

szokejokepu commented 3 weeks ago

Thanks for the example, I'll make sure to try it out.

szokejokepu commented 3 weeks ago

Also maybe include this example in the docs ;)