Here I am using jinja template to integrate python with html. Backend code has been written to fetch images one after another from folder and count the number of objects in an image and display it on front end.There is one container for live image, another container for preview image and the total count box it should display on dashboard.
mian.py
app=Flask(__name__)
#app.route('/')
def welcome():
return render_template("index.html")
#app.route('/')
def count(photo):
image = cv2.imread(f"C:/Users/suhas/Documents/New folder/templates/static/photos/{photo}")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
plt.imshow(gray, cmap='gray')
#plt.show()
blur = cv2.GaussianBlur(gray, (11, 11), 0)
plt.imshow(blur, cmap='gray')
plt.show()
canny = cv2.Canny(blur, 25, 205, 2)
plt.imshow(canny, cmap='gray')
dilated = cv2.dilate(canny, (1, 1), iterations=2)
plt.imshow(dilated, cmap='gray')
(cnt, hierarchy) = cv2.findContours(
dilated.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
cv2.drawContours(rgb, cnt, -1, (0, 255, 0), 2)
bgr = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
imS = cv2.resize(rgb, (540, 340))
text = "Total count:"+str(len(cnt))
# font
font = cv2.FONT_HERSHEY_SIMPLEX
# org
org = (220, 325)
# fontScale
fontScale = 1
# Red color in BGR
color = (0, 0, 255)
# Line thickness of 2 px
thickness = 2
# Using cv2.putText() method
imag = cv2.putText(imS, text, org, font, fontScale,
color, thickness, cv2.LINE_AA, False)
cv2.imshow('output', imag)
img=print(f"Total numbe:{photo}", len(cnt))
cv2.waitKey(1)
time.sleep(10)
cv2.destroyAllWindows()
cnt = 0
# return 1
while 1:
photo=os.listdir("C:/Users/suhas/Documents/New folder/templates/static/photos/")
# if len(photo)==0:
# break
for i in photo:
count(i)
shutil.move("C:/Users/suhas/Documents/New folder/templates/static/photos/%s"%(i),"C:/Users/suhas/Documents/New folder/templates/static/move")
print("------")
time.sleep(10)
return render_template("index.html",live='photo',preview='img',TotalCount='text')
if __name__=="__main__":
app.run()
HTML
</div>
<div class="videoSection">
<div class="liveVideoContainer">
<h3>Live</h3>
{% for img in live %}
<img src=" {{url_for('static',filename= img )}} " width="80" height="142">
{% endfor %}
<div class="previewVideoContainer">
<h3>Preview</h3>
<img src="{{url_for('static',filename= preview)}} " width="80" height="142">
' </div>
<footer>
<div class="count">
<h3>{{Totalcount}}</h3>
</div>
</footer>
</div>
Related
I have been trying to display an image using Django in my HTML.
Normally do display a static file somebody would do:
<img src="{% static 'user_profile_pics/pfp_2.jpg' %}" >
This image static file has been stored in the variable picture in my models.py.
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(max_length=500, blank=True)
picture = models.TextField(max_length=500)
The user selects the image they want to choose as their profile image. The views.py file is below with the profile definition having the request JSON dictionary with the variable picture being assigned to the model profile.picture.
#login_required
def profile(request):
profile = Profile.objects.get(user = request.user)
return render (request, "profile.html", {"userinfo": {'bio': profile.bio, 'picture': profile.picture}})
def register(request):
if request.method == 'POST':
first_name = request.POST['first_name']
last_name = request.POST['last_name']
username = request.POST['username']
email = request.POST['email']
password = request.POST['password']
confirm_password = request.POST['confirm_password']
bio = request.POST['bio']
picture = request.POST['picture']
if password==confirm_password:
if User.objects.filter(username=username).exists():
messages.info(request, 'Username is already taken')
return redirect(register)
elif User.objects.filter(email=email).exists():
messages.info(request, 'Email is already taken')
return redirect(register)
else:
user = User.objects.create_user(username=username, password=password, email=email, first_name=first_name, last_name=last_name)
user.save()
profile = Profile(bio=bio, picture=picture, user=user)
profile.save()
return redirect('login_user')
else:
messages.info(request, 'Both passwords are not matching')
return redirect(register)
else:
return render(request, 'registration.html')
Next up, displaying the bio and picture within the profile html works like this.
<div id = "userprofiletext">
{% if user.is_authenticated %}
<a class="text" >Your Description is: , {{bio}}</a>
<img src= {{userinfo.picture}} />
{% endif %}
</div>
Before implementing the JSON, the bio managed to display. I believe something must be done in the HTML to get it to display and need some help. The picture when displaying on my page does not register but when debugging it is clear that 'picture' is picture file link. The picture on the page never shows up.
I have tried to figure out displaying the bio and picture as they have been correctly passed into the models. There is a django load static line at the top of my HTML file page as well.
Edit:
Everything looks normal in this picture yet it is still not displaying?
The image
Put {{userinfo.picture}} in double quotes
<img src="{{userinfo.picture}}" />
I have two request function in views one is with .get method and the other one with .post. Both of the function works properly because in the the terminal the code is 200.
[01/Apr/2021 08:04:39] "GET /search/search HTTP/1.1" 200 4164
[01/Apr/2021 08:04:57] "POST /search/search HTTP/1.1" 200 4164
The problem comes when i try to render the function with .post method to the html template nothing appear on the html page.
def wind_search(request):
if request.method == 'post':
city = request.post['city']
weather_city_url = urllib.request.urlopen('api.openweathermap.org/data/2.5/weather?q=' + city + '&appid=1a7c2a40a0734d1dc18141fc6b6241bb').read()
list_of_data = json.loads(waether_city_url)
# main wind information
wind_speed = list_of_data['wind']['speed']
# wind_gust = wea['current']['wind_gust']
wind_deg = list_of_data['wind']['deg']
# wind conversiont m/s to knots
def wind_converter(w):
knots = 2
kt = (float(w)) * knots
return kt
wind_response = wind_converter(wind_speed)
#convert wind degree in cardinal direction.
def degrees_to_cardinal(d):
dirs = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW']
ix = round(d / (360. / len(dirs)))
return dirs[ix % len(dirs)]
direction = degrees_to_cardinal(wind_deg)
wind_data = {
"wind_response":wind_response,
"wind_direction":direction,
}
else:
wind_data={}
context = {"wind_data":wind_data}
return render(request, 'API/wind_search.html',context)
This is the html template:
{% extends "API/base.html" %}
{% block content %}
<!--Jumbotron -->
<div class="jumbotron jumbotron-fluid">
<div class="container">
<h1 class="display-4">Wind search</h1>
<p class="lead">Write the city and check th wind condition. </p>
<!-- form input search tool -->
<nav class="navbar navbar-expand-lg navbar-dark">
<form method="post" class="col-md"">
{% csrf_token %}
<div class=" input-group">
<input type="text" class="form-control" name="city" placeholder="Choose Your City ...">
<div class="input-group-btn">
<button type="submit" class="btn btn-primary">Search</button>
</div>
</div>
</form>
</nav>
<div class="row">
{% if wind_response and wind_direction %}
<h4><span>Wind Speed :</span> {{wind_data.wind_speed}}</h4>
<h4><span>Wind_Direction :</span> {{wind_data.wind_direction}}</h4>
</div>
{% endif %}
</div>
{% endblock content %}
I think the problem is with the html because basically the view don't show any error message, so i tried to change couple of time the html code but without success. Any help/ explenation is nice.
Thank you very much.
Please set the render and redirect template,
def wind_search(request):
if request.method == 'POST':
#this block of code manages if there is a POST request...
city = request.POST.get('city')
weather_city_url = urllib.request.urlopen('api.openweathermap.org/data/2.5/weather?q=' + city + '&appid=1a7c2a40a0734d1dc18141fc6b6241bb').read()
list_of_data = json.loads(waether_city_url)
# main wind information
wind_speed = list_of_data['wind']['speed']
# wind_gust = wea['current']['wind_gust']
wind_deg = list_of_data['wind']['deg']
# wind conversiont m/s to knots
def wind_converter(w):
knots = 2
kt = (float(w)) * knots
return kt
wind_response = wind_converter(wind_speed)
#convert wind degree in cardinal direction.
def degrees_to_cardinal(d):
dirs = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW']
ix = round(d / (360. / len(dirs)))
return dirs[ix % len(dirs)]
direction = degrees_to_cardinal(wind_deg)
wind_data = {
"wind_response":wind_response,
"wind_direction":direction,
}
# the page that you want to load after submitting your POST request <-----------------------------------------------------
return redirect( 'redirect to a view ' )
#the below block of code will cater for the GET method request
else:
wind_data={
'foo' : 'foo'
}
#the page you want to render on a Get Request <-----------------------------------------------------
return render(request,'render the required html for GET request' , wind_data)
I'm trying to adjust the font-size of the title and cells and pop-up message of a bokeh DataTable.
When doing so using the HTMLTamplateFormatter I can get the font-size to increase, however, I do not know how to increase the height of a row.
Also I have no clue how to adjust the formatting/height of the top/title cell of the column.
I was able to make the title bold using the information provided at this issue. Is there a similar piece of code I could use to increase the font-size.
When hovering a cell I want to show some information, I would also like to format this, is that possible? And if so how?
This is a minimal example of what I currently have:
import pandas
from bokeh.models import (ColumnDataSource, TableColumn, DataTable)
from bokeh.models.widgets import HTMLTemplateFormatter
from bokeh.io import show
data = pandas.DataFrame({"x": [1, 2, 3, 4],
"y": [200, 3, 4, 5]})
source = ColumnDataSource(data=data)
columns = []
# column 1 with bold title: x and 200% font-size
template200 = """
<div title="<%= x %>" style="font-size: 200%">
<%= value %>
</div>
"""
htmltemplateformatter200 = HTMLTemplateFormatter(template=template200)
col = "x"
title = "<b>%s</b>" % col
columns.append(TableColumn(field=col, title=title,
width=50, editor=None,
formatter=htmltemplateformatter200))
# column 2 with normal title: y and 400% font-size
template400 = """
<div title="<%= x %>" style="font-size: 400%">
<%= value %>
</div>
"""
htmltemplateformatter400 = HTMLTemplateFormatter(template=template400)
col = "y"
columns.append(TableColumn(field=col, title=col,
width=50, editor=None,
formatter=htmltemplateformatter400))
data_table = DataTable(source=source, columns=columns, row_headers=False,
sortable=False)
show(data_table)
This code will make the text in the table cell bigger. However, when I change the size to 400% the text is larger than the height of the row can visualize.
Could anyone help me with this?
Cheers,
Dave
First edit:
To show what I want to be able to do:
In my case I think I would only need a single row height since I want all the font-sizes to be the same.
Second edit:
After the reply of Okonomiyaki I looked at my code again and came up with the following solution:
main.py:
import pandas
from bokeh.models import (ColumnDataSource, TableColumn, DataTable)
from bokeh.models.widgets import HTMLTemplateFormatter
from bokeh.io import curdoc
data = pandas.DataFrame({"x": [1, 2, 3, 4],
"y": [200, 3, 4, 5]})
source = ColumnDataSource(data=data)
columns = []
# column 1 with bold title: x and 20px font-size
template200 = """
<div title="<%= x %>" style="font-size: 20px;">
<%= value %>
</div>
"""
htmltemplateformatter200 = HTMLTemplateFormatter(template=template200)
col = "x"
title = "<b>%s</b>" % col
columns.append(TableColumn(field=col, title=title,
width=50, editor=None,
formatter=htmltemplateformatter200))
# column 2 with bold title: y and 20px font-size
template400 = """
<div title="<%= y %>" style="font-size: 20px;">
<%= value %>
</div>
"""
htmltemplateformatter400 = HTMLTemplateFormatter(template=template400)
col = "y"
columns.append(TableColumn(field=col, title=col,
width=50, editor=None,
formatter=htmltemplateformatter400))
data_table = DataTable(source=source, columns=columns, row_headers=False,
sortable=False, height=1000, fit_columns=True)
curdoc().add_root(data_table)
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
$(function() {
$( document ).tooltip();
});
</script>
<meta charset="utf-8">
{{ bokeh_css }}
{{ bokeh_js }}
<style>
{% include 'jquery-ui.css' %}
{% include 'styles.css' %}
</style>
</head>
<body>
<div class="content">
{{ plot_div|indent(8) }}
</div>
{{ plot_script|indent(8) }}
</body>
</html>
styles.css:
.ui-tooltip {
padding: 8px;
position: absolute;
z-index: 9999;
max-width: 500px;
-webkit-box-shadow: 0 0 5px #aaa;
box-shadow: 0 0 5px #aaa;
opacity: 1;
font-size: 20px;
}
So few things, it turns out it is not possible to have variable row heights with a data_table. This is a restriction set by the underlying Js library - Slick Grid.
https://groups.google.com/a/continuum.io/forum/#!topic/bokeh/cg01WWfpdhw
Some discussion relevant to bokeh here.
You can however easily have variable styles on each row, and this can be set within python. Having the text/styles change is easier done with an external css sheet - although could be done within the HTML formatter, but quite messily.
Create the following app structure: (to run in command prompt type bokeh serve --show myapp)
myapp
|
+---main.py
|---templates
+---index.html
+---styles.css
main.py (contained within myapp directory) :
import pandas
from bokeh.models import (ColumnDataSource, TableColumn, DataTable)
from bokeh.models.widgets import HTMLTemplateFormatter
from bokeh.io import show, curdoc
x0 = [1,"8px", "red", "bold", "hover 1"]
x1 = [2,"10px", "blue", "italic", "hover 2"]
x2 = [3,"12px", "green", "bold", "hover 3"]
x3 = [4,"14px", "orange", "strong", "hover 4"]
x = [x0,x1,x2,x3]
data = pandas.DataFrame({"x": x,
"y": [200, 3, 4, 5]})
source = ColumnDataSource(data=data)
columns = []
# now in the formatter value[0] = original x value
# value[1] = desired font size
# value[2] = desired font color
# value[3] = desired font style
# value[4] = text to display on hover
# you could feed in any styles you want, or do it externally via css + js
template200 = """
<div title="<%= x %>" style="font-size: <%= value[1]%> ;
color: <%=value[2]%>; font-weight:<%=value[3] %>;" >
<div class = "parent_div">
<span class="nonhover"> <%= value[0] %> </span>
<span class= "cell_hover"><%= value[4]%></span> </div>
</div>
"""
htmltemplateformatter200 = HTMLTemplateFormatter(template=template200)
col = "x"
title = "<b>%s</b>" % col
columns.append(TableColumn(field=col, title=title,
width=50, editor=None,
formatter=htmltemplateformatter200))
# column 2 with normal title: y and 400% font-size
template400 = """
<div title="<%= x %>" style="font-size: 20px;">
<%= value %>
</div>
"""
htmltemplateformatter400 = HTMLTemplateFormatter(template=template400)
col = "y"
columns.append(TableColumn(field=col, title=col,
width=50, editor=None,
formatter=htmltemplateformatter400))
data_table = DataTable(source=source, columns=columns, row_headers=False,
sortable=False,height = 1000, fit_columns=True)
curdoc().add_root(data_table)
styles.css (contained within directory templates)
Basically you have two spans within a div. When you hover over them, one has the display property set to none - therefore not visible. The other span which is previously not visible then has its display set to inline, becoming visible. You can change the style of the hover over text through this.
Also note because both of the spans are contained within the very outer div which has the styles set through python, both the hover and default text have the same css style properties.
.nonhover{
display: inline;
}
.cell_hover{
display: none;
background: yellow;
}
.parent_div:hover .nonhover{
display: none;
}
.parent_div:hover .cell_hover{
display: inline;
background: yellow;
}
index.html (contained within directory templates)
<!DOCTYPE html>
<html lang="en">
<head>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/0.10.0/lodash.min.js"></script>
<meta charset="utf-8">
{{ bokeh_css }}
{{ bokeh_js }}
<style>
{% include 'styles.css' %}
</style>
</head>
<body>
<div class="content">
{{ plot_div|indent(8) }}
</div>
{{ plot_script|indent(8) }}
</body>
</html>
Hope that still helps.
I've searched for the past 3 hours on the bokeh website and stack overflow but none of it is really what i was looking for.
I've generated my plots already, and have them in html files. All i want to do is embed the plots into my dashboard in a multi grid like formation in the white area in the pic below. However, adding just 2 plots cause them to overlay and be really weird.
I used the {{ include }} method to include the graphs this way:
Anyone can give me pointers on how to align them well? Ideally i want 6 small plots in that space. I didnt want to regenerate the plots everytime i loaded the dashboard so i didnt want the embed way.
Please help :( Thank you so much!
EDIT: following big's suggestion, using responsive = True works, but i am unable to control the css styling and the sizes of the charts. I suspect its to do with using the include tag. can anyone help? :)
Why you dont try to make it with the horizontal layout
horizontal-layout
Whith your way ( {% include %} ), i don't find a solution so probably sou must use the standart flask way. Python file:
#Your imports
from flask import Flask, render_template
from bokeh.embed import components
from bokeh.plotting import figure
#app.route('/')
def homepage():
title = 'home'
from bokeh.plotting import figure
#First Plot
p = figure(plot_width=400, plot_height=400, responsive = True)
p.circle([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], size=20, color="navy", alpha=0.5)
#Second Plot
p2 = figure(plot_width=400, plot_height=400,responsive = True)
p2.square([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], size=20, color="olive", alpha=0.5)
script, div = components(p)
script2, div2 = components(p)
return render_template('index.html', title = title, script = script,
div = div, script2 = script2, div2 = div2)
Your HTML file:
<!DOCTYPE html>
<html lang="en">
<head>
<link
href="http://cdn.bokeh.org/bokeh/release/bokeh-0.11.1.min.css"
rel="stylesheet" type="text/css">
<script src="http://cdn.bokeh.org/bokeh/release/bokeh-0.11.1.min.js"></script>
<meta charset="UTF-8">
<title>{{title}}</title>
</head>
<body>
<div style="width: 20%; display: inline-block;">
{{ div | safe }}
{{ script | safe }}
</div>
<div style="width: 20%; display: inline-block;">
{{ div2 | safe }}
{{ script2 | safe }}
</div>
</body>
</html>
And one other tip is to make a python file like my_plots.py
and add your plots there, and then import to you main.py it will make your code cleaner. (i dont know 100% if this will impact your speed, but i don't seen any isues until now ) For example.
my_plots.py:
from bokeh.plotting import figure
def first_plot():
p = figure(plot_width=400, plot_height=400, responsive = True)
p.circle([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], size=20, color="navy", alpha=0.5)
return p
def second_plot():
p2 = figure(plot_width=400, plot_height=400, responsive = True)
p2.square([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], size=20, color="olive", alpha=0.5)
return p2
main.py:
#app.route('/')
def homepage():
title = 'home'
#First Plot
from my_plots import first_plot
p = first_plot()
#Second Plot
from my_plots import second_plot
p2 = second_plot()
script, div = components(p)
script2, div2 = components(p)
return render_template('index.html', title = title, script = script,
div = div, script2 = script2, div2 = div2)
Hope i was helpful, Good Luck!
Updating Leo's answer as it is for the deprecated version of Bokeh.
Bokeh v3.0.1
Flask v2.2.2
Flask App
from flask import Flask, render_template
from bokeh.embed import components
from bokeh.plotting import figure
app = Flask(__name__)
#app.route('/')
def homepage():
title = 'home'
from bokeh.plotting import figure
### First Plot ###
p1 = figure(height = 400, sizing_mode = "stretch_width")
p1.circle([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], size=20, color="navy", alpha=0.5)
### Second Plot ###
p2 = figure(height = 400, sizing_mode = "stretch_width")
p2.square([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], size=20, color="olive", alpha=0.5)
script1, div1 = components(p1)
script2, div2 = components(p2)
return render_template(
'index.html',
title = title,
script = script1,
div = div1,
script2 = script2,
div2 = div2
)
if __name__ == '__main__':
app.run(debug=True)
HTML Template
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdnjs.cloudflare.com/ajax/libs/bokeh/3.0.1/bokeh.min.js"
integrity="sha512-p7EUyPmeDeOwHiu7fIZNboAcQLxei3sWtXoHoShWWiPNUSRng/Xs5JPcaFPRa4dKy9IuHjyIQuLE4caGCwuewA=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<title>Bokeh Charts</title>
</head>
<body>
<div style="width: 40%; display: inline-block;">
{{ div1 | safe }}
{{ script1 | safe }}
</div>
<div style="width: 40%; display: inline-block;">
{{ div2 | safe }}
{{ script2 | safe }}
</div>
</body>
</html>
I am writing a small app using wxPython. I have already save my data into a HTML string. I use the wx.html2.webview to display my HTMl.
And here is my code being simplified:
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)
sizer.Add(self.browser, 1, wx.EXPAND, 10)
self.SetSizer(sizer)
self.SetSize((800, 700))
if __name__ == '__main__':
app = wx.App()
dialog = MyBrowser(None, -1)
dialog.browser.SetPage(HTMLstring,"")
dialog.Show()
app.MainLoop()
there are images and links in my HTML string. I have successfully display my HTML string. But my question is :I hope the default webbrowser can open the links when I click on it.
So what should I do. Could someone please provide a link to such an example or (better still), post a short snippet here that shows how to do it?
By the way, I used the wx.HTMLwindow before I found it could not display my HTML string in the right way.
Here is my HTMLstring being simplified:
<html>
<head>
<style type="text/css">
div#container{background-color:#F0F8FF;width:700px}
div#content {height:200px;width:400px;float:left;word-break: break-all;}
div#predict{width:700px;}
.box {height:200px;width:300px;overflow:hidden;background-repeat: no-repeat;background-position:center center;float:left;}
img{margin-top: -50px;}
a:link{ text-decoration:none;}
</style>
</head>
<body>
<br>
<hr />
<p>SCCA Predicted:</p>
<div>
Eye discharge 1.0, Sensation of foreign body 0.99901248481,
</div>
</body></html>
There isn't a good way to do this. You can use webview's EVT_WEBVIEW_NAVIGATING event. However as the documentation notes, if there are multiple frames on the web page, then this event will get fired multiple times. If you want to go that route and try it out, then I would recommend using Python's webbrowser module to open your default browser.
Here's a quick demo:
import webbrowser
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.Bind(wx.html2.EVT_WEBVIEW_NAVIGATING, self.onNav)
self.browser.Bind(wx.html2.EVT_WEBVIEW_NEWWINDOW, self.onNewWindow)
sizer.Add(self.browser, 1, wx.EXPAND, 10)
self.SetSizer(sizer)
self.SetSize((700, 700))
def onNav(self, event):
print "onNav called"
url = event.GetURL()
print url
webbrowser.open(url)
def onNewWindow(self, event):
print "onNewWindow called"
url = event.GetURL()
print url
webbrowser.open(url)
if __name__ == '__main__':
html = """<html>
<head>
<style type="text/css">
div#container{background-color:#F0F8FF;width:700px}
div#content {height:200px;width:400px;float:left;word-break: break-all;}
div#predict{width:700px;}
.box {height:200px;width:300px;overflow:hidden;background-repeat: no-repeat;background-position:center center;float:left;}
img{margin-top: -50px;}
a:link{ text-decoration:none;}
</style>
</head>
<body>
<br>
<hr />
<p>SCCA Predicted:</p>
<div>
<a href="http://sideeffects.embl.de/se/C0423006" >Eye discharge 1.0, </a><a href="http://sideeffects.embl.de/se/C0423602" >Sensation of foreign body 0.99901248481, </a>
</div>
</body></html>
"""
app = wx.App()
dialog = MyBrowser(None, -1)
dialog.browser.SetPage(html, '')
dialog.Show()
app.MainLoop()
I use the desktop module for that, edited using Mike's example but using desktop module instead of webbrowser.
import wx
import wx.html2
import desktop
html = """
<html>
<head>
<style type="text/css">
div#container{background-color:#F0F8FF;width:700px}
div#content {height:200px;width:400px;float:left;word-break: break-all;}
div#predict{width:700px;}
.box {height:200px;width:300px;overflow:hidden;background-repeat: no-repeat;background-position:center center;float:left;}
img{margin-top: -50px;}
a:link{ text-decoration:none;}
</style>
</head>
<body>
<br>
<hr />
<p>SCCA Predicted:</p>
<div>
<a href="http://sideeffects.embl.de/se/C0423006" >Eye discharge 1.0, </a><a href="http://sideeffects.embl.de/se/C0423602" >Sensation of foreign body 0.99901248481, </a>
</div>
</body></html>
"""
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.Bind(wx.html2.EVT_WEBVIEW_NAVIGATING, self.onNav)
sizer.Add(self.browser, 1, wx.EXPAND, 10)
self.SetSizer(sizer)
self.SetSize((700, 700))
def onNav(self, event):
print "onNav called"
url = event.GetURL()
print url
self.openExternal(url)
def openExternal(self, url, doclear=False):
"""
Open an external file with desktop module.
:param `url`: the file url to open in external program
:param `doclear`: clear InfoBar message
"""
wx.BeginBusyCursor()
try:
desktop.open(url.strip())
except OSError:
text = (_(u'Your default browser could not be opened, \
or the external program was not found or no \
external program is defined for this file.'))
wx.EndBusyCursor()
if __name__ == '__main__':
app = wx.App()
with MyBrowser(None, -1) as dlg:
dlg.browser.SetPage(html, '')
dlg.ShowModal()
app.MainLoop()
I also use 'with' to create the dialog, this ensures that it is getting destroyed when one with done with it.
https://pypi.python.org/pypi/desktop
If you need it on Py3 I made some changes which you can get here:
https://bitbucket.org/wbruhin/desktop