Unable to open a local HTML file generated in folium using wxPython - python

I am currently trying to plot GPS coordinates as markers on a map and displaying the result within wxPython.
I have used folium to plot coordinate markers and generate an HTML file:
import folium
fmap = folium.Map([-43.5321,172.6362], zoom_start=12)
folium.Marker([-43.5321,172.6362], popup='Marker1').add_to(fmap)
fmap.save('maparea.html')
I am able to open this HTML file in Firefox without any issues.
I need to create a programme in wxPython to display this HTML file, and I tried implementing the following code:
import wx
import wx.html2
class MyBrowser(wx.Dialog):
def __init__(self, *args, **kwds):
wx.Dialog.__init__(self, *args, **kwds)
sizer = wx.BoxSizer(wx.VERTICAL)
self.browser = wx.html2.WebView.New(self)
self.browser.LoadURL("maparea.html")
sizer.Add(self.browser, 1, wx.EXPAND, 10)
self.SetSizer(sizer)
self.SetSize((1280, 720))
if __name__ == '__main__':
app = wx.App()
dialog = MyBrowser(None)
dialog.Show()
app.MainLoop()
However, all I get is a blank page. If I change the URL in the code to a website (e.g. http://www.google.com), the code above works without issues.
Why am I unable to view the HTML file in wxPython? Is there another way to load and display an HTML file in wxPython? I would prefer to use the HTML file over displaying a screenshot in wxPython, since I would like to retain the ability pan, zoom and click on markers within the map.
(I'm running Python 3.6.8 and wxPython 4.0.3 gtk3 (phoenix) wxWidgets 3.0.5 on Ubuntu 18.04.)

I believe you need to convert the file path into a URL first (i.e. file://path/to/file.html), you can use wxFileSystem::FileNameToURL() function for that.
See https://docs.wxwidgets.org/3.0/classwx_file_system.html#a616610cafdb14b841940d5e6b08a9615

In addition to the file path needing to be a file:///url there appears to be some issue with an invalid character.
Try it without asking for the folium.Marker and you should see a map of Christchurch.
Edit:
folium is using for the Marker the wrong character for a single quote ' it's using ` instead in it's var declarations.
i.e. instead of
var html_280344edc4004eb6b0012ec2e57f9b85 = $('<div id="html_280344edc4004eb6b0012ec2e57f9b85" style="width: 100.0%; height: 100.0%;">Marker1</div>')[0];
it is providing:
var html_280344edc4004eb6b0012ec2e57f9b85 = $(`<div id="html_280344edc4004eb6b0012ec2e57f9b85" style="width: 100.0%; height: 100.0%;">Marker1</div>`)[0];
You can replace them or use webbrowser rather than wx.html2

Related

Label fails to render using python.net

I'm trying to rebuild a C# .net form I built in visual studio in Python to better suit my needs. After some googling around, I came across the package python.net/pythonnet and it's exactly what I've been looking for. Unfortunately, for some reason, I'm able to get it to generate a window and change the title of the window, but that's about it. I've tried looking at the package's documentation and .net documentation and I'm struggling to try and figure out why.
This is the snippet of the code I'm trying to use:
import clr
clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")
from System.Windows.Forms import Form, Label
from System.Drawing import Font, Size, Point
window = Form()
window.Text = "Window Title"
window.Title = Label()
window.Title.AutoSize = True
window.Title.Location = Point(8, 9)
window.Title.Name = "Title"
window.Title.Size = Size(780, 65)
window.Title.Font = Font("Serif", 42.0)
window.Title.Text = "Title Test"
window.ShowDialog()
Currently, all this does is open a blank form window that's titled "Window Title".

Using Glade 3.12 widgets in python

Just as some history, I have been using python for about 5 years now and have finally decided to make my first gui app in Glade.
I started with something basic, I have a button, a Gtkentry and gtktextview
This is what I am trying to accomplish:
on button press, take from the text from gtk.entry and have it appended to the gtk.textview
now the main problem I have is that I can not find descent documentation for how to use the widgets, and the examples I find on the Internet reference both a builder variation as well as another variation of glade project which I can only assume has been discontinued. I would like to learn how builder fits into the python / glade collaboration.
my code so far:
import gtk
import pygtk
def onDeleteWindow(self, *args):
Gtk.main_quit(*args)
def hello(button):
text_buffer.set_text(txtinput.get_text())
builder = gtk.Builder()
builder.add_from_file("dagui.glade")
handlers = {
"onDeleteWindow": gtk.main_quit,
"buttondown": hello
}
builder.connect_signals(handlers)
textarea = builder.get_object("textview1")
window = builder.get_object("window1")
txtinput = builder.get_object("entry1")
window.show_all()
gtk.main()
window.show_all()
gtk.main()
now this all works and pressing the button will print what ever is in the gtk.entry but I can not find how to append it to the textview. I also am not sure what to search for to find documentation, I tried "gtk builder gtk.textview" and pygtk build gtk.textview append" and all other variations.
Though knowing how to simply add the text to the text view would be great, having a link to somewhere where I can get in plain english how to use these widgets I would be forever great-full.
Frob the gtk.TextView, you need to get the gtk.TextBuffer by using the textview's buffer property.
From the textbuffer, you need to get the iterator that points to the end of the buffer with the get_end_iter method. With that iterator, and your text, you can use the textbuffer's insert method.
Edit: Since I don't have the dagui.glade file, I couldn't test it, but see the following code:
def hello(button):
global textarea, txtinput
buffer = textarea.get_property('buffer')
i = buffer.get_end_iter()
buffer.insert(i, txtinput.get_text())
# clear the input window after appending the text
txtinput.set_text('')
I figured it out, I have found out the the gtk.textview.get_buffer actually sets the buffer ID and then the textview.set_text(buffer) isall I needed.
here is the full working code, the glade is just a button, an entry and a textview:
#!/usr/bin/python
import os
import sys
import gtk
import pygtk
def onDeleteWindow(self, *args):
Gtk.main_quit(*args)
def hello(button):
textbuffer = textarea.get_buffer()
textbuffer.set_text(txtinput.get_text())
builder = gtk.Builder()
builder.add_from_file("dagui.glade")
handlers = {
"onDeleteWindow": gtk.main_quit,
"buttondown": hello
}
builder.connect_signals(handlers)
textarea = builder.get_object("textview1")
window = builder.get_object("window1")
txtinput = builder.get_object("entry1")
window.show_all()
gtk.main()
Use this to add text :
textarea.set_text('whatever you want')
and this for adding pango markup ( http://goo.gl/94Pkk ) :
textarea.set_markup('<span size="large>Example</span>')
Here's the documentation : http://python-gtk-3-tutorial.readthedocs.org/en/latest/index.html

Website to image

I'm running Python 3.1 and you would call me an advanced novice :)
My question is simple: I'm trying to make a simple program which asks the users for a URL (or multiple URLs) and then goes to the website and takes a screenshot (of the whole page, not just what can be seen in the browser without scrolling all the way down).
It's simpler then it sounds, I want to use an existing platform on the web, similar to this:
import subprocess
MYFILENAME = "google_screen"
MYURL = "www.google.com"
subprocess.Popen(['wget', '-O', MYFILENAME+'.png', 'http://images.websnapr.com/?url='+MYURL+'&size=s&nocache=82']).wait()
Although this website does not work :(, I'm wondering is it possible to do it with this website and if so, how? If it is not possible, are there any alternatives?
There is a package called webkit2png that you can use for this, its located: here
More information on this blog post
Example from blog post(copied to SO for preservation, read the blog post to understand it if you have issues):
#!/usr/bin/env python
import sys
import signal
from PyQt4.QtCore import *
from PyQt 4.QtGui import *
from PyQt4.QtWebKit import QWebPage
def onLoadFinished(result):
if not result:
print "Request failed"
sys.exit(1)
# Set the size of the (virtual) browser window
webpage.setViewportSize(webpage.mainFrame().contentsSize())
# Paint this frame into an image
image = QImage(webpage.viewportSize(), QImage.Format_ARGB32)
painter = QPainter(image)
webpage.mainFrame().render(painter)
painter.end()
image.save("output2.png")
sys.exit(0)
app = QApplication(sys.argv)
signal.signal(signal.SIGINT, signal.SIG_DFL)
webpage = QWebPage()
webpage.connect(webpage, SIGNAL("loadFinished(bool)"), onLoadFinished)
webpage.mainFrame().load(QUrl("http://www.google.com"))
sys.exit(app.exec_())
Edit: Link to the pyqt4 download page
You can use Selenium to get a screenshot, but it'll only be what is viewed by the browser.

How do I render *parts* of a svg file?

I want to render parts of a svg file by name but for the life of me I cannot figure out how to do so (using python + gtk).
Here's the svg file in question: http://david.bellot.free.fr/svg-cards/files/SVG-cards-2.0.1.tar.gz (Update: this file no longer exists, but you can track it down at http://svg-cards.sourceforge.net/)
On his site, David, says:
You can draw a card either by
rendering the file onto a pixmap and
clipping each card manually or by
using the card's name through a DOM
interface. All cards are embedded into
a SVG group.
I don't know what he means by a DOM interface. I have done some searching and the best result I found that seems to fit what I want to do is:
QSvgRenderer *renderer = new QSvgRenderer(QLatin1String("SvgCardDeck.svg"));
QGraphicsSvgItem *black = new QGraphicsSvgItem();
QGraphicsSvgItem *red = new QGraphicsSvgItem();
black->setSharedRenderer(renderer);
black->setElementId(QLatin1String("black_joker"));
red->setSharedRenderer(renderer);
red->setElementId(QLatin1String("red_joker"));
Notice however that it is for Qt and is not even written in python.
This is what I have so far:
#!/usr/bin/env python
from __future__ import absolute_import
import cairo
import gtk
import rsvg
from xml import xpath
from xml.dom import minidom
window = gtk.Window()
window.set_title("Foo")
window.set_size_request(256, 256)
window.set_property("resizable", False)
window.set_position(gtk.WIN_POS_CENTER)
window.connect("destroy", gtk.main_quit)
window.show()
document = minidom.parse("cards.svg")
element = xpath.Evaluate("//*[#id='1_club']", document)[0]
xml = element.toxml()
svg = rsvg.Handle()
svg.write(xml)
pixbuf = svg.get_pixbuf()
image = gtk.Image()
image.set_from_pixbuf(pixbuf)
image.show()
window.add(image)
gtk.main()
It doesn't work, of course.
What am I missing?
The GTK library for rendering SVG is called RSVG. It has python bindings, but they are undocumented, and they don't wrap the rsvg_handle_get_pixbuf_sub() and rsvg_handle_render_cairo_sub() functions which you would normally use for that purpose in C. Here's what you have to do as far as I can tell. You extract the XML node as Adam Crossland suggested. To render it, you have to do something like this:
import gtk
import rsvg
handle = rsvg.Handle()
handle.write(buffer=xml_data)
# xml_data is the XML string for the object you want
image = gtk.Image()
image.set_from_pixbuf(handle.get_pixbuf())
That's if you want it in a gtk.Image, otherwise do something else with the pixbuf. You can also render it to a Cairo context with handle.render_cairo(cr) where cr is your Cairo context.
EDIT:
Sorry, I didn't read the python bindings closely enough at first. The _sub() functions are implemented using the id= argument, so your program can boil down to this:
#!/usr/bin/env python
import gtk
import rsvg
window = gtk.Window()
window.set_title("Foo")
window.connect("destroy", gtk.main_quit)
window.show()
svg = rsvg.Handle(file='cards.svg')
pixbuf = svg.get_pixbuf(id='#3_diamond')
image = gtk.Image()
image.set_from_pixbuf(pixbuf)
image.show()
window.add(image)
gtk.main()
I tested this and it works. However, the window is the size of the entire SVG canvas, and is clipped to the screen size (which is why I rendered the 3 of diamonds instead of the ace of clubs which is up in the corner.) So you'll still have to find some way to crop the pixbuf around the card that you want, but that shouldn't be too hard.
Here's my answer to the cropping blank space problem. It's a rough hack but it worked great. This would also serve as a good starting point to get cards for anyone making a card game in python.
import gtk
import rsvg
svg = rsvg.Handle(file="/usr/share/gnome-games-common/cards/gnomangelo_bitmap.svg")
w, h = 202.5, 315
card_names = map(str, range(1,11)) + ["jack", "queen", "king"]
suites = ["club", "diamond", "heart", "spade"]
specials = [{"name":"black_joker","x":0, "y":4}, {"name":"red_joker","x":1, "y":4}, {"name":"back","x":2, "y":4}]
for suite_number, suite in enumerate(suites):
for card_number, card in enumerate(card_names):
print "processing", suite, card, '#'+card+'_'+suite
pixbuf = svg.get_pixbuf(id='#'+card+'_'+suite)
pixbuf.subpixbuf(int(w*card_number), int(h*suite_number), int(w), int(h)).save("./"+card+"_"+suite+".png","png", {})
for special in specials:
print "processing", special["name"]
pixbuf = svg.get_pixbuf(id='#'+special["name"])
card_number = special["x"]
suite_number = special["y"]
pixbuf.subpixbuf(int(w*card_number), int(h*suite_number), int(w), int(h)).save("./"+special["name"]+".png","png", {})
Grave-digging a little bit here, but the answer by ptomato from 2010 also works now in 2019 for Gtk3 with some slight modifications. The below code will render only the 3 of diamonds svg id.
#!/usr/bin/env python
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Rsvg', '2.0')
from gi.repository import Gtk, Rsvg
svg = Rsvg.Handle.new_from_file('svg-cards.svg')
pixbuf = svg.get_pixbuf_sub('#3_diamond')
image = Gtk.Image()
image.set_from_pixbuf(pixbuf)
image.show()
window = Gtk.Window()
window.set_title("Foo")
window.connect("destroy", Gtk.main_quit)
window.show()
window.add(image)
Gtk.main()
I believe that what he means by 'through a DOM interface' is that since SVG is XML, you could load the SVG file in minidom, or some other Python XML parser, and extract the XML node with the specific name that you are looking for. That XML node should represent an item that can be rendered.
You can do it by editing the tag. Edit width and height, set the viewBox attribute on the main svg element to the rectangle you want, render, repeat.
See How to show a subsection or "slice" of an SVG graphic? and http://dingoskidneys.com/~dholth/svg/

Showing an image from console in Python

What is the easiest way to show a .jpg or .gif image from Python console?
I've got a Python console program that is checking a data set which contains links to images stored locally. How should I write the script so that it would display images pop-up graphical windows?
Using the awesome Pillow library:
>>> from PIL import Image
>>> img = Image.open('test.png')
>>> img.show()
This will open the image in your default image viewer.
In a new window using Pillow/PIL
Install Pillow (or PIL), e.g.:
$ pip install pillow
Now you can
from PIL import Image
with Image.open('path/to/file.jpg') as img:
img.show()
Using native apps
Other common alternatives include running xdg-open or starting the browser with the image path:
import webbrowser
webbrowser.open('path/to/file.jpg')
Inline a Linux console
If you really want to show the image inline in the console and not as a new window, you may do that but only in a Linux console using fbi see ask Ubuntu or else use ASCII-art like CACA.
Since you are probably running Windows (from looking at your tags), this would be the easiest way to open and show an image file from the console without installing extra stuff like PIL.
import os
os.system('start pic.png')
Or simply execute the image through the shell, as in
import subprocess
subprocess.call([ fname ], shell=True)
and whatever program is installed to handle images will be launched.
In Xterm-compatible terminals, you can show the image directly in the terminal. See my answer to "PPM image to ASCII art in Python"
If you would like to show it in a new window, you could use Tkinter + PIL library, like so:
import tkinter as tk
from PIL import ImageTk, Image
def show_imge(path):
image_window = tk.Tk()
img = ImageTk.PhotoImage(Image.open(path))
panel = tk.Label(image_window, image=img)
panel.pack(side="bottom", fill="both", expand="yes")
image_window.mainloop()
This is a modified example that can be found all over the web.
Why not just display it in the user's web browser?
You cannot display images in a console window.
You need a graphical toolkit such as Tkinter, PyGTK, PyQt, PyKDE, wxPython, PyObjC, or PyFLTK.
There are plenty of tutorials on how to create simple windows and loading images in python.
You can also using the Python module Ipython, which in addition to displaying an image in the Spyder console can embed images in Jupyter notebook. In Spyder, the image will be displayed in full size, not scaled to fit the console.
from IPython.display import Image, display
display(Image(filename="mypic.png"))
I made a simple tool that will display an image given a filename or image object or url.
It's crude, but it'll do in a hurry.
Installation:
$ pip install simple-imshow
Usage:
from simshow import simshow
simshow('some_local_file.jpg') # display from local file
simshow('http://mathandy.com/escher_sphere.png') # display from url
If you want to open the image in your native image viewer, try os.startfile:
import os
os.startfile('file')
Or you could set the image as the background using a GUI library and then show it when you want to. But this way uses a lot more code and might impact the time your script takes to run. But it does allow you to customize the ui. Here's an example using wxpython:
import wx
########################################################################
class MainPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent=parent)
self.SetBackgroundStyle(wx.BG_STYLE_PAINT) # Was wx.BG_STYLE_CUSTOM)
self.frame = parent
sizer = wx.BoxSizer(wx.VERTICAL)
hSizer = wx.BoxSizer(wx.HORIZONTAL)
for num in range(4):
label = "Button %s" % num
btn = wx.Button(self, label=label)
sizer.Add(btn, 0, wx.ALL, 5)
hSizer.Add((1,1), 1, wx.EXPAND)
hSizer.Add(sizer, 0, wx.TOP, 100)
hSizer.Add((1,1), 0, wx.ALL, 75)
self.SetSizer(hSizer)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
#----------------------------------------------------------------------
def OnEraseBackground(self, evt):
"""
Add a picture to the background
"""
# yanked from ColourDB.py
dc = evt.GetDC()
if not dc:
dc = wx.ClientDC(self)
rect = self.GetUpdateRegion().GetBox()
dc.SetClippingRect(rect)
dc.Clear()
bmp = wx.Bitmap("file")
dc.DrawBitmap(bmp, 0, 0)
########################################################################
class MainFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, size=(600,450))
panel = MainPanel(self)
self.Center()
########################################################################
class Main(wx.App):
""""""
#----------------------------------------------------------------------
def __init__(self, redirect=False, filename=None):
"""Constructor"""
wx.App.__init__(self, redirect, filename)
dlg = MainFrame()
dlg.Show()
#----------------------------------------------------------------------
if __name__ == "__main__":
app = Main()
app.MainLoop()
(source code from how to put a image as a background in wxpython)
You can even show the image in your terminal using timg:
import timg
obj = timg.Renderer()
obj.load_image_from_file("file")
obj.render(timg.SixelMethod)
(PyPI: https://pypi.org/project/timg)
You can use the following code:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
%matplotlib inline
img = mpimg.imread('FILEPATH/FILENAME.jpg')
imgplot = plt.imshow(img)
plt.axis('off')
plt.show()
Displaying images in console using Python
For this you will need a library called ascii_magic
Installation : pip install ascii_magic
Sample Code :
import ascii_magic
img = ascii_magic.from_image_file("Image.png")
result = ascii_magic.to_terminal(img)
Reference : Ascii_Magic
2022:
import os
os.open("filename.png")
It will open the filename.png in a window using default image viewer.
The easiest way to display an image from a console script is to open it in a web browser using webbrowser standard library module.
No additional packages need to be installed
Works across different operating systems
On macOS, webbrowser directly opens Preview app if you pass it an image file
Here is an example, tested on macOS.
import webbrowser
# Generate PNG file
path = Path("/tmp/test-image.png")
with open(path, "wb") as out:
out.write(png_data)
# Test the image on a local screen
# using a web browser.
# Path URL format may vary across different operating systems,
# consult Python manual for details.
webbrowser.open(f"file://{path.as_posix()}")

Categories

Resources