Skip to main content

Python wrapper for Rust Iced

Project description

IcedPyGui (IPG)

Python wrapper for Rust Iced Gui

Revisions

  • Current version 0.4.0

Features

  • Supported Iced widgets
    • Button
    • Canvas - Can add canvas widgets and dynamic drawing
    • CanvasTimer - timed events for cnavas actions
    • Card - Widget with a header and body text
    • Checkbox
    • ColorPicker - Widget for selecting a color
    • Column - a container holding widgets or other container in with horizontal positioning
    • Container - container, holds a single container or widget, used for alignment purposes
    • DatePicker - Widget for selecting a date
    • Divider - Widget for resizing adjacent containers, columns, or rows
    • Events - keyboard, mouse, timer, and window
    • Fonts - Future release (just basic one now)
    • Image - svg and png types
    • Menu - Dropdown menu for various actions, includes adding widgets into menu items
    • MouseArea - holds a widget and detect mouse movement and mouse button presses
    • 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
    • SelectableText - text widget that has mouse interaction
    • Separator - Widget for separating items using lines of different types
    • 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 into
    • Styling - All widget now have styling
    • SVG - image type
    • Tabs - future release
    • Table - table for data and widgets, header body, and footer, uses Polars Dataframe
    • TextEditor - possible future release
    • TextInput - Allows one to input any text, numerical ones coming soon
    • Text - a text widget, RichText in future release
    • Timer - clocked event for dynamically controlling widgets or other timed events
    • Toggler - a widget for setting conditions like true/false on/off, etc
    • Tooltip - Widget for proping with info when mouse hovered over a widget
    • Windows multiple - many windows enabled

Future Enhancements to the program

  • More widgets will be added as iced and other developers create widgets.
  • Reduce compile times during development by creating independent widget files or other method.

Python issues to be addressed(next version)

  • 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

Pyo3 Enhancements

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

Installation (PiPy)

  • Open one of the examples using your favorite IDE.
  • Create and activate a virtual environment
pip install icedpygui
# or if already installed previously
pip install --force-reinstall 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
  • Depending on your linux system setup, you may get some compile erros about missing libraries. Just add those as needed.
  • Use maturin develop (~20 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, so I expect I'll learn a lot, and hopefully, you can bear 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 that 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 pulled into IPG, and an ID was added 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. This 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 it's the last to be 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 or use the readme_code.py file in the examples folder.

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 but added for info
ipg.add_container(
        window_id="main", 
        container_id="cont",
        width_fill=True, 
        height_fill=True,
        centered=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=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, the mutext is copied over to the gui app and a recursive routine is called to create the nested tree for all of the containers and widgets which is used by Iced to display. If your program needs additional widgets later, you can either create them initially and hide them (revealing during a callback) or create new ones during a callback. 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. Ids have to be unigue in a window but not between windows. To avoid confusion though it's best to try and keep them unique. If you use a class for your probram, the ids can be predefined and a variable name can be used in the id field. This helps prevent typos since you get a hint list.

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 items centered horizontally since a column only centers vertically. So the container just made it easier. Aligning can be troublesome but if you use the debug=Ture feature for the window, you'll be able to see the container outlines. This helps a lot in troubleshooting the alignment issues.

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. If using a class, just make a self variable that's initialize to 0 then assign during hte widget creation.

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 function 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(
              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")


ipg = IPG()

#  add the window centered on the screen
ipg.add_window(
      window_id="main", 
      title="Demo Window",
      width=600,
      height=500,
      pos_centered=True)

# container alignment defaults to centering
ipg.add_container(
      window_id="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=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. There's also the readme_code.py file available.

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 ask 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

If you're not sure about the file name format, learn more about wheel file names.

IcedPyGui-0.4.0-cp312-cp312-win_amd64.whl (10.5 MB view details)

Uploaded CPython 3.12Windows x86-64

IcedPyGui-0.4.0-cp312-cp312-win32.whl (9.8 MB view details)

Uploaded CPython 3.12Windows x86

IcedPyGui-0.4.0-cp312-cp312-manylinux_2_35_x86_64.whl (10.4 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.35+ x86-64

IcedPyGui-0.4.0-cp311-cp311-win_amd64.whl (10.5 MB view details)

Uploaded CPython 3.11Windows x86-64

IcedPyGui-0.4.0-cp311-cp311-win32.whl (9.8 MB view details)

Uploaded CPython 3.11Windows x86

IcedPyGui-0.4.0-cp311-cp311-manylinux_2_35_x86_64.whl (10.4 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.35+ x86-64

IcedPyGui-0.4.0-cp310-none-win_amd64.whl (10.3 MB view details)

Uploaded CPython 3.10Windows x86-64

IcedPyGui-0.4.0-cp310-cp310-win_amd64.whl (10.5 MB view details)

Uploaded CPython 3.10Windows x86-64

IcedPyGui-0.4.0-cp310-cp310-win32.whl (9.8 MB view details)

Uploaded CPython 3.10Windows x86

IcedPyGui-0.4.0-cp310-cp310-manylinux_2_35_x86_64.whl (10.4 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.35+ x86-64

File details

Details for the file IcedPyGui-0.4.0-cp312-cp312-win_amd64.whl.

File metadata

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

File hashes

Hashes for IcedPyGui-0.4.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 2a066988e3abd43d7504405ba036d2bd9e8b95a978832ec3c9420ed04685a550
MD5 bf30a6afb21a7a04717364bac399b3fd
BLAKE2b-256 fed525a6312ab2ab46bffb36f85a05dd646ab033b23671db25f32e16054b1f6d

See more details on using hashes here.

File details

Details for the file IcedPyGui-0.4.0-cp312-cp312-win32.whl.

File metadata

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

File hashes

Hashes for IcedPyGui-0.4.0-cp312-cp312-win32.whl
Algorithm Hash digest
SHA256 c47b01e7b1740d8496e648181a1d38def7b9058d2e7ddc4ed4acec5ace541c34
MD5 5b3791b893aec4591c08d03e574d938d
BLAKE2b-256 6e3d2b0a50da26c2867c68715c72bf55f7e2b8132c32b483d6e97e3ec21b391e

See more details on using hashes here.

File details

Details for the file IcedPyGui-0.4.0-cp312-cp312-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for IcedPyGui-0.4.0-cp312-cp312-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 0aff7f40f6e81ffce9bd1740e7a00fa9711d72c8469f285d4fa45be3ac25205e
MD5 8aff399f505fab49ec884ae70916fbd3
BLAKE2b-256 052ad794d8fee675e144b9a77a487f6215ecd81858e2191a62bd87e48b52228c

See more details on using hashes here.

File details

Details for the file IcedPyGui-0.4.0-cp311-cp311-win_amd64.whl.

File metadata

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

File hashes

Hashes for IcedPyGui-0.4.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 05fc53c1737cad9a9a045a5a1eea3adca45388bb50ed50f35bdcfa5fa0283685
MD5 d07e9b86574f9fa0c633ac7164904ef5
BLAKE2b-256 1312108fea07573a169f875791919c2ecf44dba10aae74f9b756277b7bbe2ccb

See more details on using hashes here.

File details

Details for the file IcedPyGui-0.4.0-cp311-cp311-win32.whl.

File metadata

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

File hashes

Hashes for IcedPyGui-0.4.0-cp311-cp311-win32.whl
Algorithm Hash digest
SHA256 977c296835892dca46d3fc63ab0cb9da49330ac9a8d21de9b8410354270b5f8a
MD5 ba1ba00a8c0c8f20e433e125d6e29c31
BLAKE2b-256 20c068b753c7ba8a823a299e6daa920b2f9e6eb1c0058d2fa08ac97c58812c8a

See more details on using hashes here.

File details

Details for the file IcedPyGui-0.4.0-cp311-cp311-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for IcedPyGui-0.4.0-cp311-cp311-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 29045264a77241c494eb34418bd32281e149cf0ab681e9ac88e09e7925348a09
MD5 c5db1c7589d34deac4cb09c7050adf43
BLAKE2b-256 c381fe7985d99fc4374c8ad4b5a9137f224fbff8fcd4149bd58b4b3217e71636

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for IcedPyGui-0.4.0-cp310-none-win_amd64.whl
Algorithm Hash digest
SHA256 5993bcea83e97acd05c251faa5fd1435adbf4a9fc583dfc574bcdde94413d4ac
MD5 7d8454bb68a8d83eb235ec18a4f2e246
BLAKE2b-256 e7e9e9688501d1235e0e713ccdad5c46ab2e9ab4543fd7e57c5bf514d62df151

See more details on using hashes here.

File details

Details for the file IcedPyGui-0.4.0-cp310-cp310-win_amd64.whl.

File metadata

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

File hashes

Hashes for IcedPyGui-0.4.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 358e6f26fc8c694163359e2b429b983dc76d310889e2bb1f6800c076e4de65e1
MD5 959e453f0ad50f1888d845c42111d049
BLAKE2b-256 90b41f444e5f17c88d175502335a85458745543615cc99620b95b7440b492870

See more details on using hashes here.

File details

Details for the file IcedPyGui-0.4.0-cp310-cp310-win32.whl.

File metadata

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

File hashes

Hashes for IcedPyGui-0.4.0-cp310-cp310-win32.whl
Algorithm Hash digest
SHA256 6558e00cbff47d3fdc1c05c951063d9b91fcf66da69184e248e7e3cd7892d7cc
MD5 2fa6e3bfc779d7a16a740f6b25be6e20
BLAKE2b-256 f05fac4250b27ddb078f58af89b35d7d4868b2d2eac63f7ba1df1971484f8606

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for IcedPyGui-0.4.0-cp310-cp310-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 e52d380f5b5dd9249b3b3f5e404f639f8ad4bfb6dca68fbdd17212a64879c49d
MD5 717f4f1bdb73fe2a27927b4c99e0d6b3
BLAKE2b-256 6d043e3d398526f05ed7c6b043e26150b2bb6b2b8d7f733da050a225ed6856fe

See more details on using hashes here.

Supported by

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