PyChroGUI – A GUI with Python and Chrome?

A Graphic User Interface with Python… never so easy… and using Chrome! But not the usual Chrome, a version with just an empty window, so that it looks like a ‘normal’ app and not a browser’s window. I like it for it’s more clean and leave all the space for your content.

So, today we are gonna explore another way to get user input and make a GUI with Python… but using html and javascript. I love to code in Python and I think that the html and javascript are great because they let you do a lot of stuff using a browser… so why we should not have it all? Let’s use Python to launch a GUI made with Chrome using cefpython. You could say: what is the news? You can just launch an html file with Python. With cefpython3 you can use a basic version of Chrome that has no address bar or anything, but just a plain window that can render html. So, we can make a GUI, with all the flexibility of html and javascript and with all the chance to insert links to web pages or to local files, to use the widgets of the dom etc.

Here is the code:

from cefpython3 import cefpython as cef
import sys
import os


def open_link(url):
    "Launches Chrome with a local file"
    # cef.cefexepthook = cefExceptHook
    cef.Initialize()
    cef.CreateBrowserSync(
        url=url, window_title=url.replace("file:///", ""))
    cef.MessageLoop()


def create_dictionary_from_p1(p1):
    "Creates a dictionary from p1 string"
    p1 = p1.split("\n\n")
    paragraphs = {}
    for line in p1:
        key, value = line.split("\n", 1)
        paragraphs[key] = value
    return paragraphs


def create_html(par):
    html = ""
    html += "<hr><h2>Index</h2>"
    for k in par:
        html += f"<a href='#{k}'><h3>{k}</h3></a>"
    html += "<hr><h2>START OF CONTENT</h2>"
    for k in par:
        html += f"<a href='#'><h3 id='{k}'>{k}</h3></a>"
        html += par[k]
    return html


def save(name, html):
    if name not in os.listdir():
        print("New file generated")
        with open(name, "w") as file:
            file.write(html)
    else:
        with open(name) as file:
            if file.read() == html:
                print("Same data... same file")
                pass
            else:
                print("New data... file updated")
                with open(name, "w") as file:
                    file.write(html)
    return name


p1 = """Chapter 1
This is the content of my <b>ebook</b>
<img src="https://i0.wp.com/pythonprogramming.altervista.org/wp-content/uploads/2019/12/cropped-python_white.png">

Chapter2
This is a <b style="color:red">new chapter</b>, I hope you like it.
<br>
This is the end of the 2nd paragraph.
Input your name:
<br>
<input type="text" onchange="alert('Hello ' + this.value)">

Chapter 3
As you can see we've come to an end
"""

if __name__ == "__main__":
    paragraphs = create_dictionary_from_p1(p1)
    html = create_html(paragraphs)
    name = save("my.html", html)
    open_link("file:///" + name)

The output

The live coding video about PyChroGUI

A version that uses tkinter to input the data

Add the text with title as the first row, content as next rows. Separate with an empty line the different chapters and then add title and content again… and so on. When you want to look at the result in chrome, press ctrl + s.

This is the code for this version:

from cefpython3 import cefpython as cef
import sys
import os
from tkinter import Tk
import tkinter as tk


def open_link(url):
    "Launches Chrome with a local file"
    # cef.cefexepthook = cefExceptHook
    cef.Initialize()
    cef.CreateBrowserSync(
        url=url, window_title=url.replace("file:///", ""))
    cef.MessageLoop()


def create_dictionary_from_p1(p1):
    "Creates a dictionary from p1 string"
    p1 = p1.split("\n\n")
    paragraphs = {}
    for line in p1:
        key, value = line.split("\n", 1)
        paragraphs[key] = value
    return paragraphs


def create_html(par):
    html = ""
    html += "<hr><h2>Index</h2>"
    for k in par:
        html += f"<a href='#{k}'><h3>{k}</h3></a>"
    html += "<hr><h2>START OF CONTENT</h2>"
    for k in par:
        html += f"<a href='#'><h3 id='{k}'>{k}</h3></a>"
        html += par[k]
    return html


def save(name, html):
    if name not in os.listdir():
        print("New file generated")
        with open(name, "w") as file:
            file.write(html)
    else:
        with open(name) as file:
            if file.read() == html:
                print("Same data... same file")
                pass
            else:
                print("New data... file updated")
                with open(name, "w") as file:
                    file.write(html)
    return name


root = Tk()


def start(event):
    print(text.get("0.0", tk.END))
    paragraphs = create_dictionary_from_p1(text.get("0.0", tk.END))
    html = create_html(paragraphs)
    name = save("my.html", html)
    open_link("file:///" + name)



text = tk.Text(root)
text.pack()
text.bind("<Control - s>", start)


root.mainloop()

Tips: You could save your data in text files and then copy and paste them in the text box of tkinter to render them into Chrome.

A version that uses external files for the data

In this version you’ll be asked to enter the number of a list of text files that are in the directory to transform the text into html. The rules are the same: 1st row for the title, the following (with no black lines – use <br> to live a space) will be the content until there is a blank line that means a new paragraph, like in this example:

Title
There was a nice sound coming from the door of the pub.

Title
I was looking for a little space where I could sit and read my book.

The code:

from cefpython3 import cefpython as cef
import sys
import os


def open_link(url):
    "Launches Chrome with a local file"
    # cef.cefexepthook = cefExceptHook
    cef.Initialize()
    cef.CreateBrowserSync(
        url=url, window_title=url.replace("file:///", ""))
    cef.MessageLoop()


def create_dictionary_from_p1(p1):
    "Creates a dictionary from p1 string"
    p1 = p1.split("\n\n")
    paragraphs = {}
    for line in p1:
        key, value = line.split("\n", 1)
        key = key.replace("=", "")
        paragraphs[key] = value
    return paragraphs


def create_html(par):
    html = ""
    html += "<hr><h2 id='indice'>Indice</h2>"
    for k in par:
        html += f"<a href='#{k}'><h3>{k}</h3></a>"
    html += "<hr><h2>START OF CONTENT</h2>"
    for k in par:
        html += f"<a href='#indice'><h3 id='{k}'>{k}</h3></a>"
        html += par[k]
    return html


def save(name, html):
    if name not in os.listdir():
        print("New file generated")
        with open(name, "w") as file:
            file.write(html)
    else:
        with open(name) as file:
            if file.read() == html:
                print("Same data... same file")
                pass
            else:
                print("New data... file updated")
                with open(name, "w") as file:
                    file.write(html)
    return name


x = [str(n) + " " + x for n,x in enumerate(os.listdir()) if x.endswith(".txt")]
print(*x, sep="\n")
p = int(input("Numero del file: "))
with open(os.listdir()[p], "r", encoding="utf-8") as file:
    p1 = file.read()



if __name__ == "__main__":
    paragraphs = create_dictionary_from_p1(p1)
    html = create_html(paragraphs)
    name = save("my.html", html)
    open_link("file:///" + name)

 

Utilities

Published by pythonprogramming

Started with basic on the spectrum, loved javascript in the 90ies and python in the 2000, now I am back with python, still making some javascript stuff when needed.