Code Monkey home page Code Monkey logo

remi's Introduction

Build Status

GUI library for your Python applications

Remi is a GUI library for Python applications that gets rendered in web browsers. This allows you to access your interface locally and remotely.

Proud to be sponsored by

Do you need support?

Reddit - (subreddit RemiGUI)

There is also a drag n drop GUI Editor. Look at the Editor subfolder to download your copy.

A demonstrative video from the great REVVEN labs

Getting Started

For a stable version:

pip install remi

For the most updated experimental version Download or check out Remi from git and install

python setup.py install

or install directly using pip

pip install git+https://github.com/rawpython/remi.git

Then start the test script (download it from github https://github.com/rawpython/remi/blob/master/examples/widgets_overview_app.py):

python widgets_overview_app.py

Remi

Platform independent Python GUI library. In less than 100 Kbytes of source code, perfect for your diet.

Remi enables developers to create platform independent GUI with Python. The entire GUI is rendered in your browser. No HTML is required, Remi automatically translates your Python code into HTML. When your app starts, it starts a web server that will be accessible on your network.

A basic application appears like this:

import remi.gui as gui
from remi import start, App

class MyApp(App):
    def __init__(self, *args):
        super(MyApp, self).__init__(*args)

    def main(self):
        container = gui.VBox(width=120, height=100)
        self.lbl = gui.Label('Hello world!')
        self.bt = gui.Button('Press me!')

        # setting the listener for the onclick event of the button
        self.bt.onclick.do(self.on_button_pressed)

        # appending a widget to another, the first argument is a string key
        container.append(self.lbl)
        container.append(self.bt)

        # returning the root widget
        return container

    # listener function
    def on_button_pressed(self, widget):
        self.lbl.set_text('Button pressed!')
        self.bt.set_text('Hi!')

# starts the web server
start(MyApp, port=8081)

In order to see the user interface, open your preferred browser and type "http://127.0.0.1:8081". You can change the URL address by specific **kwargs at start function call. This will be discussed later.

Tested on Android, Linux, Windows. Useful on Raspberry Pi for Python script development. It allows interacting with your Raspberry Pi remotely from your mobile device.

FAQ

  • Why another GUI lib? Kivy, PyQT, and PyGObject all require native code for the host operating system, which means installing or compiling large dependencies. Remi needs only a web browser to show your GUI.

  • Do I need to know HTML? NO, It is not required, you have to code only in Python.

  • Is it open source? For sure! Remi is released under the Apache License. See the LICENSE file for more details.

  • Do I need some kind of web server? No, it's included.

Brief tutorial

Import Remi library and some other useful stuff.

import remi.gui as gui
from remi import start, App

Subclass the App class and declare a main function that will be the entry point of the application. Inside the main function you have to return the root widget.

class MyApp(App):
    def __init__(self, *args):
        super(MyApp, self).__init__(*args)

    def main(self):
        lbl = gui.Label("Hello world!", width=100, height=30)

        # return of the root widget
        return lbl

Outside the main class, start the application by calling the function start and passing the name of the class you declared previously as the parameter:

# starts the webserver
start(MyApp, port=8081)

Run the script. If it's all OK the GUI will be opened automatically in your browser, otherwise, you have to type in the address bar "http://127.0.0.1:8081".

You can customize optional parameters in the start call like:

start(MyApp, address='127.0.0.1', port=8081, multiple_instance=False, enable_file_cache=True, update_interval=0.1, start_browser=True)

Parameters:

  • address: network interface IP
  • port: listen port
  • multiple_instance: boolean, if True multiple clients that connect to your script has different App instances (identified by unique cookie session identifier)
  • enable_file_cache: boolean, if True enable resource caching
  • update_interval: GUI update interval in seconds. If zero, the update happens at each change. If zero, the App.idle method is not called.
  • start_browser: boolean that defines if the browser should be opened automatically at startup
  • standalone: boolean, indicates where to run the application as a standard Desktop application with its own window. If False, the interface is shown in a browser webpage.

Additional Parameters:

  • username: for a basic HTTP authentication
  • password: for a basic HTTP authentication
  • certfile: SSL certificate filename
  • keyfile: SSL key file
  • ssl_version: authentication version (i.e. ssl.PROTOCOL_TLSv1_2). If None disables SSL encryption

All widgets constructors accept two standards**kwargs that are:

  • width: can be expressed as int (and is interpreted as a pixel) or as str (and you can specify the measuring unit like '10%')
  • height: can be expressed as int (and is interpreted as a pixel) or as str (and you can specify the measuring unit like '10%')

Events and callbacks

Widgets expose a set of events that happen during user interaction. Such events are a convenient way to define the application behavior. Each widget has its own callbacks, depending on the type of user interaction it allows. The specific callbacks for the widgets will be illustrated later.

In order to register a function as an event listener you have to call a function like eventname.do (i.e. onclick.do) passing as parameters the callback that will manage the event. Follows an example:

import remi.gui as gui
from remi import start, App

class MyApp(App):
    def __init__(self, *args):
        super(MyApp, self).__init__(*args)

    def main(self):
        container = gui.VBox(width=120, height=100)
        self.lbl = gui.Label('Hello world!')
        self.bt = gui.Button('Press me!')

        # setting the listener for the onclick event of the button
        self.bt.onclick.do(self.on_button_pressed)

        # appending a widget to another, the first argument is a string key
        container.append(self.lbl)
        container.append(self.bt)

        # returning the root widget
        return container

    # listener function
    def on_button_pressed(self, widget):
        self.lbl.set_text('Button pressed!')
        self.bt.set_text('Hi!')

# starts the web server
start(MyApp)

In the shown example self.bt.onclick.do(self.on_button_pressed) registers the self's on_button_pressed function as a listener for the event onclick exposed by the Button widget. Simple, easy.

Listener's callbacks will receive the emitter's instance firstly, then all other parameters provided by the specific event.

Besides the standard event registration (as aforementioned), it is possible to pass user parameters to listener functions. This can be achieves appending parameters to the do function call.

import remi.gui as gui
from remi import start, App

class MyApp(App):
    def __init__(self, *args):
        super(MyApp, self).__init__(*args)

    def main(self):
        container = gui.VBox(width=120, height=100)
        self.lbl = gui.Label('Hello world!')
        self.bt = gui.Button('Hello name!')
        self.bt2 = gui.Button('Hello name surname!')

        # setting the listener for the onclick event of the buttons
        self.bt.onclick.do(self.on_button_pressed, "Name")
        self.bt2.onclick.do(self.on_button_pressed, "Name", "Surname")

        # appending a widget to another
        container.append(self.lbl)
        container.append(self.bt)
        container.append(self.bt2)

        # returning the root widget
        return container

    # listener function
    def on_button_pressed(self, widget, name='', surname=''):
        self.lbl.set_text('Button pressed!')
        widget.set_text('Hello ' + name + ' ' + surname)

# starts the web server
start(MyApp)

This allows great flexibility, getting different behaviors with the same event listener definition.

HTML Attribute accessibility

Sometimes it is required to access Widget's HTML representation in order to manipulate HTML attributes. The library allows accessing this information easily.

A simple example: It is the case where you would like to add a hover text to a widget. This can be achieved by the title attribute of an HTML tag. In order to do this:

    widget_instance.attributes['title'] = 'Your title content'

A special case of HTML attribute is the style. The style attributes can be altered in this way:

    widget_instance.style['color'] = 'red'

The assignment of a new attribute automatically creates it.

For a reference list of HTML attributes, you can refer to https://www.w3schools.com/tags/ref_attributes.asp

For a reference list of style attributes, you can refer to https://www.w3schools.com/cssref/default.asp

Take care about internally used attributes. These are:

  • class: It is used to store the Widget class name for styling purpose
  • id: It is used to store the instance id of the widget for callback management

Remote access

If you are using your REMI app remotely, with a DNS and behind a firewall, you can specify special parameters in the start call:

  • port: HTTP server port. Don't forget to NAT this port on your router;
start(MyApp, address='0.0.0.0', port=8081)

Standalone Execution

I suggest using the browser as a standard interface window.

However, you can avoid using the browser. This can be simply obtained joining REMI and PyWebView. Here is an example about this standalone_app.py.

Be aware that PyWebView uses qt, gtk and so on to create the window. An outdated version of these libraries can cause UI problems. If you experience UI issues, update these libraries, or better avoid standalone execution.

Authentication

In order to limit remote access to your interface, you can define a username and password. It consists of a simple authentication process. Just define the parameters username and password in the start call:

start(MyApp, username='myusername', password='mypassword')

Styling

In order to define a new style for your app, you have to do the following. Create a res folder and pass it to your App class constructor:

class MyApp(App):
    def __init__(self, *args):
        res_path = os.path.join(os.path.dirname(__file__), 'res')
        super(MyApp, self).__init__(*args, static_file_path={'res':res_path})

Copy the standard style.css file from the remi folder and paste it inside your res folder. Edit it in order to customize. This way the standard style.css file gets overridden by the one you created.

Compatibility

Remi is made to be compatible from Python2.7 to Python3.X. Please notify compatibility issues.

Security

Remi should be intended as a standard desktop GUI framework. The library itself doesn't implement security strategies, and so it is advised to not expose its access to unsafe public networks.

When loading data from external sources, consider protecting the application from potential javascript injection before displaying the content directly.

Projects using Remi

PySimpleGUI: Launched in 2018 Actively developed and supported. Supports tkinter, Qt, WxPython, Remi (in browser). Create custom layout GUI's simply. Python 2.7 & 3 Support. 100+ Demo programs & Cookbook for rapid start. Extensive documentation.

App Template For REMI: A really well written template for multiview applications.

Web based dynamic reconfigure for ROS robots

razmq

Espresso-ARM

PiPresents

The Python Banyan Framework

LightShowPi show manager

rElectrum: A powerful promising Electrum wallet manager for safe transactions.

Other Implementations

Listed here are other implementations of this library:

remi's People

Contributors

amaank404 avatar awesomebytes avatar bernhardreiter avatar bethany-1 avatar cetus1 avatar cyberpro4 avatar dddomodossola avatar eothred avatar gitter-badger avatar jjclark1982 avatar kent2 avatar khink avatar ksengine avatar maxmorais avatar mcondarelli avatar mryslab avatar nick-hebi avatar npes87184 avatar nzjrs avatar paarthtandon avatar pec0ra avatar purporc avatar smurfix avatar tcyrus avatar timgates42 avatar tristantrim avatar ulda avatar vpoulailleau avatar wcastello avatar zciurus-alt-del avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

remi's Issues

Update the webapp dynamically?

I tried to make a little app where I check for some parameters of a running system and show them in a DropDown. I wanted to update this dropdown with the current parameters of the system (to choose one, and from there on, show also a dynamically generated table of the data to hopefully be edited). I made refresh button for trying to update them. I expected reloading the webpage to actually run the function "main" again, but I found out that does not happen. I used simple_app.py as my starting point.

So in short, is it possible or will it be possible to edit/add elements to the layout? I see you can set_text in some fields, but what about update dropdown contents or directly add new widgets on the fly?

Maybe it is just possible right now but I don't see how :P

Follow Python's "Best of the Best Practices" more closely

I'm not a PEP 8 code-snob, promise! I'm specifically talking about the getter- and setter-methods which are more at home in other languages, which nearly all of your widgets make use of. Especially at what I would consider the beginning of the project, you have a chance to make the Widget code very pythonic without any drawbacks (i.e. breaking backwards-compatibility).

Maybe I am being shortsighted, is there a reason why you are simply not using properties or attributes (when there's no logic involved in setting and/or getting the attribute)?

PS: "Best of the Best Practices"

Better branch model

Actually every changes / fixes / features, are pushed on master branch, but, the master branch should contain only stable / tested release.
Can I suggest this model?

Download displays the file in browser rather than saving it. IE only.

The download works fine in Firefox with the download dialog allowing it to be saved, but in IE the logo.png is displayed in the browser instead of causing the download dialog. I vaguely remember from the distant past that IE needs a header to be sent. Can advise you if necessary.

Setting the initial value of the DropDown

I cannot work out how to reliably set the initial value of a DropDown. A set_value method would be useful as it would allow the displayed value to be changed by the App. Same will probably apply to the SpinBox, Slider and Colour Picker etc.

UnicodeEncodeError: 'latin-1' codec can't encode character

Full traceback:
Traceback (most recent call last):
File "/home/pybokeh/miniconda3/envs/remi/lib/python3.4/socketserver.py", line 617, in process_request_thread
self.finish_request(request, client_address)
File "/home/pybokeh/miniconda3/envs/remi/lib/python3.4/socketserver.py", line 344, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "test.py", line 10, in init
super(MyApp, self).init(*args)
File "/home/pybokeh/miniconda3/envs/remi/lib/python3.4/socketserver.py", line 673, in init
self.handle()
File "/home/pybokeh/miniconda3/envs/remi/lib/python3.4/http/server.py", line 398, in handle
self.handle_one_request()
File "/home/pybokeh/miniconda3/envs/remi/lib/python3.4/http/server.py", line 386, in handle_one_request
method()
File "/home/pybokeh/miniconda3/envs/remi/lib/python3.4/site-packages/remi/server.py", line 552, in do_GET
self.process_all(path)
File "/home/pybokeh/miniconda3/envs/remi/lib/python3.4/site-packages/remi/server.py", line 572, in process_all
self.wfile.write(encodeIfPyGT3(html))
File "/home/pybokeh/miniconda3/envs/remi/lib/python3.4/site-packages/remi/server.py", line 90, in encodeIfPyGT3
data = data.encode('latin-1')
UnicodeEncodeError: 'latin-1' codec can't encode character '\u2020' in position 20239: ordinal not in range(256)

My code:

import remi.gui as gui
from remi import start, App
import pandas as pd
from db import DB

# import ipdb; ipdb.set_trace()

class MyApp(App):
    def __init__(self, *args):
        super(MyApp, self).__init__(*args)

    def main(self):
        wid = gui.Widget(1200, 800, gui.Widget.LAYOUT_HORIZONTAL, 10)

        db = DB(filename="/home/pybokeh/Dropbox/data_sets/nba", dbtype="sqlite")

        column_names = [column.name for column in db.tables.player_game_stats._columns]

        row_data = db.query("select * from player_game_stats where team_name like '%Cav%'").values

        self.table = gui.Table(600, 400)

        row = gui.TableRow()
        for column in column_names:
            item = gui.TableTitle()
            item.append(str(id(item)), str(column))
            row.append(str(id(item)), item)

        self.table.append(str(id(row)), row)


        for _row in row_data:
            row = gui.TableRow()
            for row_item in _row:
                item = gui.TableTitle()
                item.append(str(id(item)), str(row_item))
                row.append(str(id(item)), item)

                self.table.append(str(id(row)), row)

        wid.append('1', self.table)

        return wid

if __name__ == "__main__":
    start(MyApp)

If I limit my query to return just 5 rows, I do not get an error. So it seems there is a character that it doesn't like somewhere in the other rows in my table.

Using virtual environment created with conda with python version 3.4.

My platform:

import platform
print(platform.platform())

Linux-3.13.0-68-generic-x86_64-with-debian-jessie-sid

Installed python libraries:

import pip
modules = pip.get_installed_distributions()
for m in modules:
    print(m)

setuptools 18.4
prettytable 0.7.2
ptyprocess 0.5
ipython 4.0.0
ipython-genutils 0.1.0
PyMeta3 0.5.1
numpy 1.10.1
traitlets 4.0.0
wheel 0.26.0
python-dateutil 2.4.2
pandas 0.17.0
pexpect 4.0.1
simplegeneric 0.8.1
pybars3 0.9.1
decorator 4.0.4
ipdb 0.8.1
pytz 2015.7
six 1.10.0
pickleshare 0.5
remi 0.1
db.py 0.4.4
pip 7.1.2
path.py 8.1.2

Regards,
Daniel

Issues with arabic language when set dynamically

Hello, I have an issue that is blocking me. I wanted to make a little internal interface to set up some sentences in multilang for another app and I deal with arabic.

The thing is, if I load from a file that contains arabic into a TextInput on the main method of the app its shown fine. But if I do a set_text on it with the same text later on from a click of a button it's shown wrong.

I've made a proof of concept of this happening:

https://github.com/awesomebytes/remi_arabic_text

In: https://github.com/awesomebytes/remi_arabic_text/blob/master/test_arabic.py

First I load the contents of a text file with arabic doing a set_text just after creating the TextInput:
https://github.com/awesomebytes/remi_arabic_text/blob/master/test_arabic.py#L32-L33

And it looks like:
working

But if do set_text on the TextInput later on it looks like:
https://github.com/awesomebytes/remi_arabic_text/blob/master/test_arabic.py#L47-L49
non_working

Help?

Extend documentation to indicate which Python versions are supported

The readme, or hopefully the more complete documentation in the future (check out Sphinx), should indicate whether this project is usable with Python 2, 3 or both. If the latter is the case, the examples should be adjusted to work with both Python versions. Currently some of them make use of print-statements which are deprecated in Python 3.

ability to update widgets from code

Label has set_text that can be called from within the gui. I would like

Slider.set_value()
SpinBox.set_value()

so that I can update the GUI to reflect the state of my program

Input dialog splits text at /

When InputDialog is a single line, the text is longer than the box, and it contains a / it splits at / and the remainder goes second line.

Structure of gui files for deployment

I would like to separate the code of my application from that of gui so that each can have its own licence etc. and gui is easily replaced when it changes.

The way I have done it is to have a two level directory structure

  • Top level contains the code and ancilliary files for my application.
  • The gui code and all its resources etc. is in a sub directory

Not a very clear description but you can see it in action in https://github.com/KenT2/manager-for-pipresents.

If you like the idea it would be good to arrange your github repository in the same way; the top level directory would contain the two examples.

The change requires gui to have an empty init.py file and for some changes to imports etc in the example Apps.

However at the moment the res directory and styles.css have to be moved from gui upwards to be with the examples. I think it would be better for separation if they stayed in gui. Is this possible?

Checkbox widget?

Any plan to implement a checkbox widget?

I may hack one with two images of a checked and unchecked checkbox, but I believe you can do better by creating the html element for it.

Problems in BaseApp

When I ran simple_app, I got this:

Traceback (most recent call last):
File "gui\simple_app.py", line 45, in
start( App )
File "C:\Python27\mypython\kpad\gui\server.py", line 198, in start
server = HTTPServer(('', PORT_NUMBER), mainGuiClass)
File "C:\Python27\lib\SocketServer.py", line 408, in init
self.server_bind()
File "C:\Python27\lib\BaseHTTPServer.py", line 108, in server_bind
SocketServer.TCPServer.server_bind(self)
File "C:\Python27\lib\SocketServer.py", line 419, in server_bind
self.socket.bind(self.server_address)
File "C:\Python27\lib\socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 10013] An attempt was made to access a socket in a way forbidden by its access permissions

InputNumber?

Would it be possible to have an input supporting only numbers?
I can write letters in the actual SpinBox :S.

Maybe able to choose between Integer and some decimal point representation?

Idle Method configuration parameter

The idle interval configuration parameter affects gui's response to button presses etc. In addition it affects how often the idle method is run. It would be good to separate these so the config is just for idle()

Uploader and Downloader could be Dialogs and not Widgets

I have used the new uploader and downloader. I have also been doing a lot of development of my app and it is now on github at https://github.com/KenT2/manager-for-pipresents

All my development and testing has been on Pi for server and Internet Explorer and Firefox running on Windows. Most museums will be Windows/IE so that is my most important user.

The uploader and downloader upload and download fine with one exception (see next issue) I have one problem with each of them, it is not possible to dynamically change the destination directory for the uploader or the source file for the downloader because they are defined as widgets in the main page rather than dialogs.

Uploader would be much better if you could do

   def on_a_click(self):
upload_dialog=gui.FileUploader(600,600,self.media_dir+os.sep)
    upload_dialog.set_on_success_listener(self,'on_media_upload_success')
    upload_dialog.set_on_failed_listener(self,'on_media_upload_failed')
    upload_dialog.show(self)

which would be executed as a result of a button click or menu click etc. event . It would open the browser's file selection dialog directly. Downloader would be similar and open the browser's download box.

    profile_download=gui.FileDownloader(600,600,'Click to download current profile',self.file_to_download)
    profile_download.show(self)

Old browsers support

Should we support old browsers (for example IE9) that mainly does not have websockets? As a solution we can build a layer that implements the same protocol of the websocket class in the server, but communicates with POST requests.
Is it a good idea?

read_next_message string index out of range

I've seen this error happen from time to time, I cannot reproduce it:

Exception in server.py-read_next_message.
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/remi/server.py", line 177, in read_next_message
    length = self.bytetonum(length[1]) & 127
IndexError: string index out of range

Errno 104 Connection reset by peer

Its probably just a faulty network killing stuff and there is maybe nothing to do... but I do get:

Exception happened during processing of request from ('172.16.15.28', 32928)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 593, in process_request_thread
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 334, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python2.7/SocketServer.py", line 649, in __init__
    self.handle()
  File "/usr/local/lib/python2.7/dist-packages/remi/server.py", line 164, in handle
    if not self.read_next_message():
  File "/usr/local/lib/python2.7/dist-packages/remi/server.py", line 175, in read_next_message
    length = self.rfile.read(2)
  File "/usr/lib/python2.7/socket.py", line 380, in read
    data = self._sock.recv(left)
error: [Errno 104] Connection reset by peer

Connecting a phone to my machine and accessing a non-trivial app.

Is there any try: except: thing we can do?

Two Simple Dialogs would be useful

There are two simple dialogs which I have used a lot. They have no input field just the title and message fields, an OK button, and optionally a Cancel button. You can see my fudged versions in ok_cancel and display_error methods in pp_manager.py

rename framework

'gui' is too broad of a name to be used for a framework. it is a general term that is already known and used.

can you select another one?

it would also better allow you to clean up the project structure as per #21

Key for removing a ListView item

ListView items are removed using the object reference. It would be better if they were removed using the reference defined when they were created.

Width and height paramters for the file selection dialog.

It would be good to have the width and height of the FileSelectionDialog as parameters. As a fix I changed the height of the FileSelectionDialog locally in gui.py but the number of entries displayed does not change with the height

Include get_value()/get_key() as appropriate in these widgets please

This could be a duplicate, original seems to have got lost in Github when changing to remi :-(

Include get_value()/get_key() as appropriate in these widgets
SpinBox - value
ListView - key and value of selected item
DropDown - key and value of selected item
Input - value
Slider - value
ColorPicker - value
Date - value

Icons and filenames in FileSelectionDialog

In the file selection dialog I think it would be more intuitive if clicking on the directory icon opened that directory and clicking on the filename does the selection of files and directories, rather than the other way round.

Clicking on a file icon would probably do nothing.

Hover text?

Any plan on implementing hover text on the widgets?

I would like to be able to show some text over a widget to help understand what it does.

Using examples without setup.py gives import error

I tried using the examples without running setup.py. This gave an import error. I moved the examples up a directory level and they worked,

Is there a way change the examples such that they will do the imports across sub-directories.

A General Purpose Dialog

I noticed that the INPUT DIALOG generates a new web page and returned to the previous one when OK was pressed.

I just wondered if there could be a general purpose 'DIALOG'. It would have OK and Cancel buttons. It would be able to have any of the Widgets that the main gui page has (maybe with exceptions). The values of the widgets would be read by App when the OK button is pressed in the on_confirm event method using the read_value method for each of the widgets. The values would not be returned as a list as in the InputDialog.

IOError: Permission denied on some files

Hello, I was just trying your thing (looks pretty cool!) but I cannot run it correctly.

I just git cloned it then did:

sudo python setup.py install

and entered the examples folder and executed the widgets_overview_app.py then I got:

127.0.0.1 - - [03/Nov/2015 21:25:15] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [03/Nov/2015 21:25:15] "GET /res/style.css HTTP/1.1" 200 -
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 43276)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 593, in process_request_thread
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 334, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "widgets_overview_app.py", line 22, in __init__
    super(MyApp, self).__init__(*args)
  File "/usr/lib/python2.7/SocketServer.py", line 649, in __init__
    self.handle()
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 340, in handle
    self.handle_one_request()
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 328, in handle_one_request
    method()
  File "/usr/local/lib/python2.7/dist-packages/remi-0.1-py2.7.egg/remi/server.py", line 540, in do_GET
    self.process_all(function)
  File "/usr/local/lib/python2.7/dist-packages/remi-0.1-py2.7.egg/remi/server.py", line 574, in process_all
    with open(filename, 'r+b') as f:
IOError: [Errno 13] Permission denied: '/usr/local/lib/python2.7/dist-packages/remi-0.1-py2.7.egg/remi/res/style.css'
----------------------------------------
127.0.0.1 - - [03/Nov/2015 21:25:15] "GET /res/logo.png HTTP/1.1" 200 -
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 43277)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 593, in process_request_thread
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 334, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "widgets_overview_app.py", line 22, in __init__
    super(MyApp, self).__init__(*args)
  File "/usr/lib/python2.7/SocketServer.py", line 649, in __init__
    self.handle()
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 340, in handle
    self.handle_one_request()
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 328, in handle_one_request
    method()
  File "/usr/local/lib/python2.7/dist-packages/remi-0.1-py2.7.egg/remi/server.py", line 540, in do_GET
    self.process_all(function)
  File "/usr/local/lib/python2.7/dist-packages/remi-0.1-py2.7.egg/remi/server.py", line 574, in process_all
    with open(filename, 'r+b') as f:
IOError: [Errno 13] Permission denied: '/usr/local/lib/python2.7/dist-packages/remi-0.1-py2.7.egg/remi/res/logo.png'
----------------------------------------
127.0.0.1 - - [03/Nov/2015 21:25:15] "GET /res/logo.png HTTP/1.1" 200 -
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 43278)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 593, in process_request_thread
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 334, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "widgets_overview_app.py", line 22, in __init__
    super(MyApp, self).__init__(*args)
  File "/usr/lib/python2.7/SocketServer.py", line 649, in __init__
    self.handle()
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 340, in handle
    self.handle_one_request()
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 328, in handle_one_request
    method()
  File "/usr/local/lib/python2.7/dist-packages/remi-0.1-py2.7.egg/remi/server.py", line 540, in do_GET
    self.process_all(function)
  File "/usr/local/lib/python2.7/dist-packages/remi-0.1-py2.7.egg/remi/server.py", line 574, in process_all
    with open(filename, 'r+b') as f:
IOError: [Errno 13] Permission denied: '/usr/local/lib/python2.7/dist-packages/remi-0.1-py2.7.egg/remi/res/logo.png'

Am I doing anything wrong?

Also Chrome (in ubuntu 14.04) says "Connection is closed" when I run the script. And the website looks wrong.

Add userdata to callbacks

Is there a way to pass multiple variables from multiple text inputs to a single listener function?

My thought was to set up an on_change listener for each text input but use the same listener function name for each one, then when writing the actual listener function pass all the variables you want that function to use, for example:
self.input1 = gui.TextInput(200, 20)
self.input1.set_on_change_listener(self, 'listener_function')
self.input2 = gui.TextInput(200, 50)
self.input2.set_on_change_listener(self, 'listener_function')
def listener_function(self, var1, var2)
self.lbl.set_text(str(var1) + ' & ' + str(var2)

However, doing this breaks the function so it won't populate the 'lbl' or do anything else defined in that function but doesn't return any errors.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.