Skip to main content

Python wrapper for Rust Iced

Project description

IcedPyGui (IPG)

Python wrapper for Rust Iced Gui

Revisions

  • Current version 0.3.0

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)

  • Code not published to PiPy yet. Download one of the wheels attached to the release page, code also in wheels folder or see below for installation via rust
  • Open one of the example using your favorite IDE.
  • Create and activate a virtual environment
pip install path to wheel
# or if already installed previously
pip install --force-reinstall path to wheel

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

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.0-cp312-none-win_amd64.whl (5.9 MB view details)

Uploaded CPython 3.12 Windows x86-64

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

Uploaded CPython 3.12 Windows x86

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

Uploaded CPython 3.12 macOS 11.0+ ARM64

IcedPyGui-0.3.0-cp312-cp312-macosx_10_12_x86_64.whl (4.6 MB view details)

Uploaded CPython 3.12 macOS 10.12+ x86-64

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

Uploaded CPython 3.11 Windows x86-64

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

Uploaded CPython 3.11 Windows x86

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

Uploaded CPython 3.11 macOS 11.0+ ARM64

IcedPyGui-0.3.0-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.0-cp310-none-win_amd64.whl (5.9 MB view details)

Uploaded CPython 3.10 Windows x86-64

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

Uploaded CPython 3.10 Windows x86

IcedPyGui-0.3.0-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.0-cp310-cp310-macosx_11_0_arm64.whl (4.3 MB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

IcedPyGui-0.3.0-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.0-cp312-none-win_amd64.whl.

File metadata

  • Download URL: IcedPyGui-0.3.0-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.0-cp312-none-win_amd64.whl
Algorithm Hash digest
SHA256 1b1d8f8c4d9918e1468365193a0de65166f02b19ea0d79c664ed755f098042e2
MD5 88cb6c1e53f7356264b3a51c890576b5
BLAKE2b-256 29713fe831e2c691a23c19da89e0fb540ec6c47ca333e941883e65ccce933796

See more details on using hashes here.

File details

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

File metadata

  • Download URL: IcedPyGui-0.3.0-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.0-cp312-none-win32.whl
Algorithm Hash digest
SHA256 b551be96bb25847917109684b08920a60deaa491281bdf175402ddea207612e2
MD5 33c6efc91dae829c5e687572c7145835
BLAKE2b-256 ebbe8ebfd32bd00de30bb770179f4a3be80f84b4e2f937f073fecf4c9cdac4db

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for IcedPyGui-0.3.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 19d25eee0883e46fedb24a65bc850d66b66d730984ffbe8734de223558488a1f
MD5 b40c4989f32c45a4a68f8551551a6d0d
BLAKE2b-256 1ea59f24a9adaac7c34e4725b42b7ba34fca2b6c2bf73626f94d9d36d66387fc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for IcedPyGui-0.3.0-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 94ff10c3fdade07c9ca158416e9bbfb3557bde6e8c6e42a2619c9839d4bee68d
MD5 0ec70f612a22ab5958a7edcde6f267ee
BLAKE2b-256 40adb6823471056216fd351932c228fa1bb85a2c30eb7d16dfcd9ac918c00c14

See more details on using hashes here.

File details

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

File metadata

  • Download URL: IcedPyGui-0.3.0-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.0-cp311-none-win_amd64.whl
Algorithm Hash digest
SHA256 dfd738cda0475ca15255a202124ac255750e69e853df8ee41d6da407a7ef2a11
MD5 6e9754c9588533fdcfe15217ca846eef
BLAKE2b-256 7caafbbd55492ce8efa8eae9b1a6f48c9532547125e8eb1f3934d17a94116091

See more details on using hashes here.

File details

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

File metadata

  • Download URL: IcedPyGui-0.3.0-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.0-cp311-none-win32.whl
Algorithm Hash digest
SHA256 15a0bbabcea353266e9f20c5434effb9dba37a945a9f438838d38a2e8a9b5337
MD5 5d218eb210c29719bd3ef640b59d31fa
BLAKE2b-256 b75fcde4a22f581b7c86c2985451325a28d3025c85e757375b9dbecb720f35ce

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for IcedPyGui-0.3.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 548b1de973481dc60b70da040fa7f9b2b53a820c931276555f361ed3a194bfb5
MD5 5b80f45a753652937e590ea5092532b5
BLAKE2b-256 9ae1ae8b309e1816ac4e438d775529c1ef54d843d3d92f6484abe46319fcb241

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for IcedPyGui-0.3.0-cp311-cp311-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 d598438392e04b7e6c763f5b5edfa3d6b9104d7db37d0484d5c5c0424e1781ed
MD5 074db6535dc6c2287cfef2875a352975
BLAKE2b-256 62d93314395c5b775100f4ace5ccae8b1fa79dace4a1b86ecd1c2f55c840f37b

See more details on using hashes here.

File details

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

File metadata

  • Download URL: IcedPyGui-0.3.0-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.0-cp310-none-win_amd64.whl
Algorithm Hash digest
SHA256 0b2e4fcbc97b860c12968f93d5726f2459b66c1690614b2cdec0a11fdccba436
MD5 a8c6defbf87d4f9a68166a6bb0fa004a
BLAKE2b-256 12f0af4a23b0c27da827d17b222300f7cb43ecb0fcf56f1406a33d2ecf559804

See more details on using hashes here.

File details

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

File metadata

  • Download URL: IcedPyGui-0.3.0-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.0-cp310-none-win32.whl
Algorithm Hash digest
SHA256 822ab6611cb400742005d677cdabe47e4a62ec95c6e13fd49262440ad398ea33
MD5 4704a3035351b46754c2842f05853659
BLAKE2b-256 3283ed80dfa9c295b44209c32ac36a163e5deff3265d095b707ef24be2aa0b62

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for IcedPyGui-0.3.0-cp310-cp310-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 3a564709d874a25043bcac5788659d80595d6c15c28c7640ee2d7e95e56e6b6c
MD5 60da0d60e34b18b929dbb40309c28109
BLAKE2b-256 4981917c887387ee447cf007b51da72a2bde32566e8c1291574a5bb0c4103afc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for IcedPyGui-0.3.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 908b315bd6085e6f7e42bf464747ca57bf707b22202c5487851a07af29dea0b0
MD5 9da064f7eae85af8c4140b5bbec50297
BLAKE2b-256 68b0b86ff45483b8b8e730a8b6f19efee5799e2ed74913817cbc8d8b03699205

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for IcedPyGui-0.3.0-cp310-cp310-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 27e1570cf4e6fcf0c08b9c1bd14d67de825a645c9e34c7f5023648634ebf6632
MD5 93e4002b1c58f61a49779e67c53b9512
BLAKE2b-256 fd4977ebcdb9e497cc778f94577b2cb48fdcbe9921b288a9e7e998ed032317ab

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