Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/marczellm/tkpf
A GUI library for python/tkinter with two-way data binding
https://github.com/marczellm/tkpf
components databinding gui python tkinter
Last synced: about 1 month ago
JSON representation
A GUI library for python/tkinter with two-way data binding
- Host: GitHub
- URL: https://github.com/marczellm/tkpf
- Owner: marczellm
- License: lgpl-3.0
- Created: 2017-07-07T07:31:46.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2018-11-05T16:59:20.000Z (about 6 years ago)
- Last Synced: 2024-08-01T22:55:50.711Z (4 months ago)
- Topics: components, databinding, gui, python, tkinter
- Language: Python
- Size: 65.4 KB
- Stars: 59
- Watchers: 10
- Forks: 5
- Open Issues: 5
-
Metadata Files:
- Readme: readme.md
- License: LICENSE
Awesome Lists containing this project
- starred-awesome - tkpf - A GUI library for python/tkinter with two-way data binding (Python)
README
`tkpf` is a library for building Tkinter GUIs in a paradigm
influenced by WPF (Windows Presentation Foundation) and Angular.Main features are:
- Declarative view hierarchy and layout in XML or YAML
- One-way and two-way data binding
- Componentization support![tkpf](https://user-images.githubusercontent.com/6771275/28272256-3ddb29a4-6b0b-11e7-8072-c962235d58d8.png)
![x1](https://user-images.githubusercontent.com/6771275/28181423-d9c4bfd4-6808-11e7-955a-c0e18219e609.PNG)
![mac](https://user-images.githubusercontent.com/6771275/48013133-e82a6e80-e123-11e8-92c0-b0a13467dc7e.png)# Tutorial
## The layout template
You specify the GUI in XML or YAML format. Here is a simple example, `ExampleWindow.xml`:```xml
Option 1
Option 2
Do stuff
```
As you can see, the XML tag names correspond to Tkinter widget class names,
while XML attributes to their arguments.
`tkpf` is opinionated in that it always uses the better looking `ttk` themed widgets
when available.Options such as `pack-anchor="nw"` or `grid-row="0"` specify the layout and will be passed to the appropriate
Tkinter layout manager method, in this case `.pack(anchor='nw')`.On how to specify a GUI in YAML format, see `example/ExampleWindow.yaml`.
## The view class
You display the GUI by creating a class derived from `Window` and showing it.
You have to supply the viewmodel in the constructor.```python
class ExampleWindow(Window):
template_path = 'ExampleWindow.xml' # 'ExampleWindow.yaml' works tooExampleWindow(ExampleModel()).show()
```
If you want to keep the layout XML in this file inline, you can do that too:```python
class ExampleWindow(Window):
template = 'Some text'
```or
```python
class ExampleWindow(Window):
template_yaml = '''
Label:
text: Some text
'''
```Setting the window title:
```python
def __init__(self, model):
super().__init__(model)
self.title = 'My application'
```In the view class you can write event handlers. Make that button work for example:
```python
def do_stuff(self):
self.combobox.config(state='disabled')
```This also shows how you can access widgets by name in methods of the view class. But if you prefer you can access them dynamically like this:
```python
self.named_widgets['combobox']
```## The viewmodel class
```pythonclass ExampleModel(ViewModel):
choice = Bindable(AutoProperty(1))
available_suboptions = Bindable(AutoProperty())
selected_suboption = Bindable(AutoProperty())
def __init__(self):
super().__init__()
self.available_suboptions = ('suboption1', 'suboption2')
````AutoProperty` is similar to a C# autogenerated property. By default its datatype is `str`.
You can supply either a default value or a type to its constructor.`Bindable` is a decorator that you can use on any property to return a bindable property.
It has to know the data type of the wrapped property, so please specify its return type with a type annotation:
```python
@Bindable
@property
def foo() -> int:
return 1
````AutoProperty` takes care of that for you.
Only `int`, `bool`, `float` and `str` types are supported for Tkinter bindings, though for the combobox
values, you can assign a Python tuple.
If an event handler is not found on the view class, it will be looked up on the viewmodel as well.
## Data binding syntax
In the XML you specify the direction of data binding with a syntax similar to that of Angular:```
values="[available_suboptions]"
```
is a one-way binding from data source to view target,
```
textvariable="(selected_suboption)"
```
is a one-way binding from view target to data source, and
```
variable="[(choice)]"
```
is a two-way binding.## Using custom widgets
You can use custom widgets derived from Tkinter widget classes.
The only thing you have to do is call```python
Directive.Registry.register(YourCustomWidgetClass)
```before loading a template that uses it.
## Components
`tkpf` supports breaking up your GUI into components.
Here's an example of a progressbar component with its own viewmodel:```python
class ProgressbarModel(ViewModel):
value = BindableProperty(0)
target = BindableProperty(100)
class CustomProgressbar(Component):
template = ''
```and you can use it like this:
```xml```
where `progressbar_model` is an attribute or property on your main viewmodel.
On Python 3.5 you have to register your component before using it. On Python 3.6+ that is automatic.
```python
Directive.Registry.register(CustomProgressbar)
```It is planned that you will be able to add add custom, bindable attributes to components, like this:
```python
class ExampleComponent(Component):
template = 'Example component text'def config(self, **kwargs):
self.thelabel.config(text=kwargs['custom-text'])
```and then use them like this:
```xml```
The only requirement is that the attribute name contains a hyphen.
## Caveats
`tkpf` only supports Python 3.5+.This is a work in progress. Also my first attempt at creating a library. Look at the project issues to see what's not supported yet.