Skip to main content

Python wrapper for Rust Iced

Project description

IcedPyGui (IPG)

Python wrapper for Rust Iced Gui

Python Examples

Features

  • Supported Iced widgets
    • Button
    • Checkbox
    • Canvas - Can add canvas widgets but dynamic drawing to follow
    • Column - a container holding widgets or other container in with horizontal positioning
    • ComboBox - Needs modification to work in IPG, but PicKList good substitute
    • Container - container, holds a single container or widget, used for alignment purposes
    • Events - keyboard, mouse, timer, and window
    • Fonts - Future release
    • Image - svg and png types
    • Modal - discontinued for now, use stack or open a small window
    • MouseArea - holds a widget and detect mouse movement and mouse button presses
    • PaneGrid - maybe a future release, will need to be modified for IPG
    • PickList - essentially a combobox
    • ProgressBar - a bar used to show progression of some action
    • QRCodes - future release
    • Radio buttons - multiple radios can be grouped, multiple groups allowed
    • Row - a container holding widgets or other containers with vertical positioning.
    • Rule - A widget line divider for readability
    • Scrollable - container which allows scrolling items
    • Slider - A widget for creating values by sliding a bar
    • Space - a widget for helping align content
    • Stack - a container that allows one to stack other containers
    • Styling - All widget now have styling
    • SVG - image type
    • TextEditor - Future release
    • TextInput - Allows one to input any text, numerical ones coming soon
    • Text - a text widget
    • Toggler - a widget for setting conditions like true/false on/off, etc
    • Tooltip - Only widget now, container ability future release
    • Windows multiple - many windows enabled
  • Iced_aw widgets - are moved into IPG due to version conflicts
    • Card - a container with a header and footer
    • ColorPicker - future release
    • Menu - Dropdown menu items
    • Tabs - future release
  • IPG widgets
    • DatePicker - compact and resizable
    • SelectableText - all mouse buttons supported
    • Table - Easily loaded with a list of py dictionaries, supports adding buttons, checkboxes, and togglers, continually updating code

Future Enhancements to the program

  • Since upgrading to iced 0.13.1, I can now dispense with using a mutex to store some data. These work fine but a mutex cannot use anything with a lifetime since it is static. This will clear up some issues when trying to incorporated widgets such as the Editor, etc.
  • Some optimization might be possible by not rebuilding the widgets unless they change. Not tested yet but hopefully it can happen.
  • More widgets will be added see those mentioned above, along with any other I can find.
  • Fonts is on the list for an upcoming release.

Python issues to be addressed

  • Need to incorporate using the 'with' statement in python. Using with would allow one to not have to supply the window or parent id if those follow closely. For example:

        with window(...):
            with container(...):
                add_widget(...)
    
  • @dataclass can be used but no IPG code in it until a later release

  • @staticmethod future release

  • Better error messages during callbacks. Currently an error in python code during the callback trigger a rust error which captures the python error but doesn't say where in the callback it happens.

Pyo3 Enhancements

  • There are a number of future possible enhancements related to parallelism and async.

Installation (PiPy)

  • Create and activate a virtual environment in your favorite IDE
pip install IcedPyGui

Installation (Rust)

  • Install Rust
  • Clone the repository and open in your favorite IDE
  • Create and activate a virtual environment - The venv for this take a couple of minutes to create, be patient, sometimes a restart of vs code needed to recognize the venv
  • Install maturin and compile the rust code
  • Use maturin develop (~10 sec compile time on AMD Rizen 7700, stored in local venv)
  • maturin build --release (~1.5 min compile time stored in target/wheels)
  • Copy over one of the python examples (link above), use the below code, or the demo in the demo folder.
pip install maturin
maturin develop
  • Open and run one of the python examples

Overview

  • IcedPyGui is based on Rust Iced v0.12.1.
  • Widgets for Iced_aw v0.8.0 are used too .
  • Pyo3 is used as the python wrapper.
  • Maturin is used to build and publish the module .
  • The syntax and the design of the callbacks were inspired by the python wrapper of Dear ImGui, DearPyGui(DPG).
  • The icon above was a merge of Python and Iced icons by Deep Dream Generator

Intro

Iced is a great GUI for Rust but it's still early in the development cycle, more good things will follow.

This project is the first I have published and so I expect I'll learn a lot and hopefully you can bare with me.

Rust's strict typing is mostly shielded from the python user but if you venture too far, you'll get burned with an error, so behave yourselves :)

Iced uses a messaging system which acts like a callback and no widget ids are used except for the containers and windows. This posed a bit of a problem in IPG but in most cases it was solved by mapping an id to the widget. In cases where this was not possible, the code was pull into IPG and an id was added in with fairly simple changes so it shouldn't be hard to keep those few items updated.

Iced doesn't use the concept of user data being passed around but when using DPG, sometimes the ability to send user data was very helpful. Therefore, this concept was added to IPG.

Each widget in IPG has a used data parameter which passes any additional information needed by the callback. The user data is special because it is only passed through to rust and back out as a PyObject or PyAny. Therefore any python data can be used since it is never extracted into a rust type.

Important rules

  • Import IPG as indicated below in the demo code and any parameter class needed for the widgets.

  • Instantiate the Rust structure then add your containers and widgets.

  • The last line of code to execute must be ipg.start_session(). Any code after that will not be executed because Iced is now running. You can place it anywhere, just make sure its last executed. If you start your program and nothing happens, it might mean that you aren't executing start_session() or you forgot to add it in, been there, done that.

  • Every widget needs to have a parent container previously defined and every container needs to have a window and optionally a parent container defined. If the container is placed into a window then no parent_id is required.

  • Therefore at least one window needs to be added first and at least one container needs to be added to the window before any widgets are added. As long as you have defined a parent, you can add a widget.

Let's get started with out first program

Further below you'll find the full code to be tested in your IDE. Sometimes the these code snippets don't paste properly into the IDE if the parameter names are in them. But since these snippets are for learning, they need to be there for better understanding. So look further down for the full code to copy and paste.

First we import IPG from icedpygui. This is a Rust structure to be instantiated. We will be using a container and a column, these have alignment parameters so we need to import the parameters classes so that we don't have to type in strings which result in irritating typos. We'll also be updating a text widget to show some results, therefore the text parameter class is needed.

from icedpygui import IPG
from icedpygui import IpgAlignment, IpgTextParam

Let's instantiate the Rust structure and add some containers. Since this is a short program, we'll dispense with using a class. See the examples for cases where we used a class but nothing special pertains to IPG when they are used, except for a @dataclass and @staticmethod which will be supported in the near future.

ipg = IPG()

ipg.add_window(window_id="main", title="Demo Window",
               width=600, height=500,
               pos_centered=True)

# alignment defaults to centering
ipg.add_container("main", container_id="cont",
                  width_fill=True, height_fill=True)

# The column width will shrink to the size of the largest widget by default.
# If you were to use width_fill and height_fill here, the contents would be center
# vertically but placed on the left of the window.  Essentially, the container
# alignment would not be effective because they both would use all of the window space.
ipg.add_column(window_id="main", container_id="col", 
                parent_id="cont",
                align_items=IpgAlignment.Center)

So, the window was added using an window_id, title, size and position, followed by a container and column. The ids are a key part of IPG and can be consider the glue that holds everything together. Each time there is an add command, a corresponding structure is initialized and stored in a Mutex using a HashMap with an integer id. Once Iced is started, a recursive routine is called to create the nested tree for all of the containers and widgets which is used by Iced to display them. Therefore, widgets can only be added during the add or construct phase. This might seem restrictive but if you have a widget that you need later, just add it with the show parameter as false. When the time comes for it's use, just change the parameter show to true and you now have it. You can modify all of the widgets during a callback procedure where the command update_item() is used. You can also move widgets from container to container very easily. You will see some of this in the demo code below.

Note how the ids are used. A container must have a window_id because Iced is a multi-window GUI, we need to know which window to put it in. In addition, if a container goes into another container, then the parent_id is needed.

A quick word on width_fill parameter. Almost all containers and widgets have a width and height. The parameter width and height take a float number. The width_fill and height_fill is bool and overrides the float. The fill parameters will cause the width of the container or widget to fill the available space. This works pretty good in most cases but there are some cases where there is a conflict as you'll see in some of the examples.

The column was added because the container holds only one widget and we need a container that holds more. We could have not used a container but only a column but then we would need to add spaces to get the column centered horizontally since a column only centers vertically. So the container made it easier.

To make things a little bit more exciting, let's add 3 widgets in a Column container.

Adding widgets

ipg.add_button(parent_id="col", label="Press Me!", on_press=button_pressed)

ipg.add_checkbox(parent_id="col", label="Check Me!!!", on_toggle=checked)

checked_text_id = ipg.add_text(parent_id="col",
                               content="This will change when I'm checked")

The button and checkbox widgets were next added and given a parent_id, which is the container_id that you want to put the widget in. The callbacks are functions you want to execute when, for example, a button is pressed. So in the case above, we have callback functions, button_pressed and checked. Note, some IDE's automatically insert a () after a function name is typed in. This will give you an error because these are references to the function and are not to be executed at this time. So make sure the () is not present.

As you may have noted, widgets don't get an id but are assigned an id during the construction of the Rust structure which returns an integer. The text widget which was added last is an example where the id of the widget is needed for updating the text widget with some new content.

Defining callbacks

Below we defined two callbacks, button_pressed and checked, All callbacks have from 1 to 3 parameters based on the output of the widget. The button has only one (2 if user_data used) and the checkbox has a minimum of 2, id and a bool to indicate if checked or not and a 3rd if user_data used. You can look at the docs to determine the returning values, but they are mostly obvious based on what the widget does.

def button_pressed(btn_id):
    print(btn_id)

def checked(_chk_id: int, checked: bool):
    if checked:
        ipg.update_item(wid=checked_text_id,
                        param=IpgTextParam.Content,
                        value="I'm checked")

    else:
        ipg.update_item(wid=checked_text_id,
                        param=IpgTextParam.Content,
                        value="I'm not checked")

The button is simple because it only returns the id of itself. So in most cases, you'll be doing something else like processing some data or changing some other widget. In this case, we'll just print out the id number.

We have used the term btn_id above versus id because id is used by python and it's good to indicate what the id is coming from so that you can remember which id to use in your function, like in the checkbox callback. You are not using the checkbox id but the text id.

Another note on naming the callback parameters. They can be named anything, order is most important.

For the checkbox callback, we could just print the checked status but that really never happens in a real programs so let's display the info in a text widget by using the command update_item().

The update_item is going to be your goto function to change the way the gui looks and to process your data while Iced is running. The update_item function takes 3 arguments, an integer id of the widget you want to update, the class name of the parameter you want to change, and the value you want to set it too. Unless you are updating the calling widget, you'll need the id of the widget you want to update. The class name is the same as the parameter name of the widget so you can look at the docs for which to select.

So in the checked function, we do an if else statement for the boolean and change the text accordingly. The user_data is not covered here but the are many in the examples and they are straight forward to use.

Finally, we're ready to start the engine on the gui with one last line of code, the magic.

ipg.start_session()

Let's put it all together to cut down on the cutting a pasting.

from icedpygui import IPG
from icedpygui import IpgAlignment, IpgTextParam


def button_pressed(btn_id):
    print(btn_id)


def checked(_chk_id: int, checked: bool):
    if checked:
        ipg.update_item(checked_text_id,
                        IpgTextParam.Content,
                        "I'm checked")

    else:
        ipg.update_item(checked_text_id,
                        IpgTextParam.Content,
                        "I'm not checked")


ipg = IPG()

ipg.add_window(window_id="main", title="Demo Window",
               width=600, height=500,
               pos_centered=True)

# container alignment defaults to centering
ipg.add_container("main", container_id="cont",
                  width_fill=True, height_fill=True)

# The column width will shrink to the size of the largest widget by default.
ipg.add_column(window_id="main", container_id="col", parent_id="cont",
               align_items=IpgAlignment.Center)

ipg.add_button(parent_id="col", label="Press Me!", on_press=button_pressed)

ipg.add_checkbox(parent_id="col", label="Check Me!!!", on_toggle=checked)

checked_text_id = ipg.add_text(parent_id="col",
                               content="This will change when I'm checked")

ipg.start_session()

Hopefully you were able to run the program successfully. If not, try one of the examples and see if it will work. All of the examples are run before publishing to make sure the code works.

The examples are found in a separate repository as indicated above and here https://github.com/icedpygui/IcedPyGui-Python-Examples

Issues / Questions / Feedback / Contributing

Feedback/Discussions/Questions are welcomed! You can come chat in the Discord server.

If you have errors not cleared up in questions, click on the issues tab and create a new one. Follow the template.

Code contributions are welcomed. See guidelines

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

IcedPyGui-0.3.1-cp312-none-win_amd64.whl (5.9 MB view details)

Uploaded CPython 3.12 Windows x86-64

IcedPyGui-0.3.1-cp312-none-win32.whl (5.5 MB view details)

Uploaded CPython 3.12 Windows x86

IcedPyGui-0.3.1-cp312-cp312-macosx_11_0_arm64.whl (4.3 MB view details)

Uploaded CPython 3.12 macOS 11.0+ ARM64

IcedPyGui-0.3.1-cp312-cp312-macosx_10_12_x86_64.whl (4.7 MB view details)

Uploaded CPython 3.12 macOS 10.12+ x86-64

IcedPyGui-0.3.1-cp311-none-win_amd64.whl (5.9 MB view details)

Uploaded CPython 3.11 Windows x86-64

IcedPyGui-0.3.1-cp311-none-win32.whl (5.5 MB view details)

Uploaded CPython 3.11 Windows x86

IcedPyGui-0.3.1-cp311-cp311-macosx_11_0_arm64.whl (4.3 MB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

IcedPyGui-0.3.1-cp311-cp311-macosx_10_12_x86_64.whl (4.6 MB view details)

Uploaded CPython 3.11 macOS 10.12+ x86-64

IcedPyGui-0.3.1-cp310-none-win_amd64.whl (5.9 MB view details)

Uploaded CPython 3.10 Windows x86-64

IcedPyGui-0.3.1-cp310-none-win32.whl (5.5 MB view details)

Uploaded CPython 3.10 Windows x86

IcedPyGui-0.3.1-cp310-cp310-manylinux_2_35_x86_64.whl (6.3 MB view details)

Uploaded CPython 3.10 manylinux: glibc 2.35+ x86-64

IcedPyGui-0.3.1-cp310-cp310-macosx_11_0_arm64.whl (4.3 MB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

IcedPyGui-0.3.1-cp310-cp310-macosx_10_12_x86_64.whl (4.6 MB view details)

Uploaded CPython 3.10 macOS 10.12+ x86-64

File details

Details for the file IcedPyGui-0.3.1-cp312-none-win_amd64.whl.

File metadata

  • Download URL: IcedPyGui-0.3.1-cp312-none-win_amd64.whl
  • Upload date:
  • Size: 5.9 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.10.12

File hashes

Hashes for IcedPyGui-0.3.1-cp312-none-win_amd64.whl
Algorithm Hash digest
SHA256 329f6b65bcb66c16ee5fe977e52a3df63c5f02c07766b8b98820ee516386034b
MD5 e1b456d2ca4a564f3dca13cd4fc33658
BLAKE2b-256 42d958e0c5f88d5be828cab7ecfd258b08759a832efa3825cfcfb6109b21fdb4

See more details on using hashes here.

File details

Details for the file IcedPyGui-0.3.1-cp312-none-win32.whl.

File metadata

  • Download URL: IcedPyGui-0.3.1-cp312-none-win32.whl
  • Upload date:
  • Size: 5.5 MB
  • Tags: CPython 3.12, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.10.12

File hashes

Hashes for IcedPyGui-0.3.1-cp312-none-win32.whl
Algorithm Hash digest
SHA256 e7d072972ff112e73f0512243ea32bd17278b6311db95f657abf500f4ad60c8a
MD5 a6f13f42763dd1b438d480a959b016c2
BLAKE2b-256 ae5b7c5ccff0f306939b6fd376643e25db3485faa7d5f7cd5af0be3dcbe600c4

See more details on using hashes here.

File details

Details for the file IcedPyGui-0.3.1-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for IcedPyGui-0.3.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 076cc2787798d3674ac7e5774802505cdeefe91df77d010fedbbe77769bce40e
MD5 b1bfe44ba7231ecb9c3fe4d47e790a7d
BLAKE2b-256 1c3e3e0b268fbc1324c6df2ef9c836e0706e3181850caa06b1158686eb72dfee

See more details on using hashes here.

File details

Details for the file IcedPyGui-0.3.1-cp312-cp312-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for IcedPyGui-0.3.1-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 393ca8dc1478cc91d92c6f9373626d6f0b1c8597c818ae7b0094cd16a2e708e1
MD5 6d98944a20c08a2657528c476ebe9d0f
BLAKE2b-256 44452be7b7a9ee1e095ebeb1f7f6f9d13bec40992a1f5fa42f991215c329b593

See more details on using hashes here.

File details

Details for the file IcedPyGui-0.3.1-cp311-none-win_amd64.whl.

File metadata

  • Download URL: IcedPyGui-0.3.1-cp311-none-win_amd64.whl
  • Upload date:
  • Size: 5.9 MB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.10.12

File hashes

Hashes for IcedPyGui-0.3.1-cp311-none-win_amd64.whl
Algorithm Hash digest
SHA256 dce144b6e46f06c977d1a31015b8bbbcf50fb0ed6f41495f984c43da86290921
MD5 ac52d50334f79a1d2afd281c9105b346
BLAKE2b-256 289eadcbe5b4cdbfb7095cc86a851266e37876a4ff6b54f1b6ae5a3a4dafdea0

See more details on using hashes here.

File details

Details for the file IcedPyGui-0.3.1-cp311-none-win32.whl.

File metadata

  • Download URL: IcedPyGui-0.3.1-cp311-none-win32.whl
  • Upload date:
  • Size: 5.5 MB
  • Tags: CPython 3.11, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.10.12

File hashes

Hashes for IcedPyGui-0.3.1-cp311-none-win32.whl
Algorithm Hash digest
SHA256 d4b94407d8e8161a66dbc002560d9d194e20c696ffc45fc3ee1f1c0af4346143
MD5 69c45b76d88ff40f848189aabbb48052
BLAKE2b-256 2ff2693dd81220c80d4d3b3dda41204dcdb84339a1750cf5fa8cd9bc1e157620

See more details on using hashes here.

File details

Details for the file IcedPyGui-0.3.1-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for IcedPyGui-0.3.1-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6e737cd82588a975d139ef89b4769c48186d56efd1bedc63a1d5d60860d55887
MD5 bcc9b28a4123b035e3198df0bc42ecd2
BLAKE2b-256 e67cca60fde74243d77dcbdd8d07b51540ab810b6c0b956bd9c50d2bd22c2588

See more details on using hashes here.

File details

Details for the file IcedPyGui-0.3.1-cp311-cp311-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for IcedPyGui-0.3.1-cp311-cp311-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 e0c7d34740494d288826110292c3c24cf5665b99b78cf00083ef18b7d1fbc0df
MD5 1c0f55fc92a51d5bbfe97c9b21504993
BLAKE2b-256 545abf1536e09b71b1a180e9c1ac83fb5d176252eed35e8e8f25c74b64b76129

See more details on using hashes here.

File details

Details for the file IcedPyGui-0.3.1-cp310-none-win_amd64.whl.

File metadata

  • Download URL: IcedPyGui-0.3.1-cp310-none-win_amd64.whl
  • Upload date:
  • Size: 5.9 MB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.10.12

File hashes

Hashes for IcedPyGui-0.3.1-cp310-none-win_amd64.whl
Algorithm Hash digest
SHA256 b32c0ed716ae6d10d68f6f956102f8b7f8f5d2666f74d54d6aa7aa585487357b
MD5 b6c91d365e44451dba5524b70b149b73
BLAKE2b-256 04cfbbf80e75a1bf10f264a852f0a89e3eaba9f7e689ee9799d575aea16b3cc0

See more details on using hashes here.

File details

Details for the file IcedPyGui-0.3.1-cp310-none-win32.whl.

File metadata

  • Download URL: IcedPyGui-0.3.1-cp310-none-win32.whl
  • Upload date:
  • Size: 5.5 MB
  • Tags: CPython 3.10, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.10.12

File hashes

Hashes for IcedPyGui-0.3.1-cp310-none-win32.whl
Algorithm Hash digest
SHA256 35355dc05e4da5e1ee7e34d2eb4417ca6a9c285e90ab36feed7ae030d43b62cc
MD5 38bdb0fb9e5e27250921359ace8135cf
BLAKE2b-256 d67f1ef6fc449f9383a762f27c839020525ba44e9f1f56290c0275e29a37cac0

See more details on using hashes here.

File details

Details for the file IcedPyGui-0.3.1-cp310-cp310-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for IcedPyGui-0.3.1-cp310-cp310-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 b1339d39f6e5c3628fea040702e7afbeda6af3b985d68f92166985ffa3e11189
MD5 150d588699547d60498399e248ebff48
BLAKE2b-256 f38a863897b381a80be484ee69226c46ce0b9056fd9939ed092e7499d17a2f73

See more details on using hashes here.

File details

Details for the file IcedPyGui-0.3.1-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for IcedPyGui-0.3.1-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4408685939cfb6fba5e4c7dd629b282b1606a4b401488421b9b07db7851033fe
MD5 93b93af1b235bf6ebe24a3a0673b3192
BLAKE2b-256 fbd77ae8b5af6c7814090cd2e80f65d49665aeca750fd0d2bde78ce8faceeef9

See more details on using hashes here.

File details

Details for the file IcedPyGui-0.3.1-cp310-cp310-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for IcedPyGui-0.3.1-cp310-cp310-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 2dcffa38c9689680d5743c55f0fa44cd7bfa1b96388c910ebe791cff56bbd2a1
MD5 8f842fed484ae7018d158da60eed964c
BLAKE2b-256 1fee760bea6e578b6ba0e95307c7936ca0cba04a1acf741cc58cd3e9033ae9bc

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page