BruceSherwood / vpython-jupyter

This repository has been moved to https://github.com/vpython/vpython-jupyter
64 stars 33 forks source link

HTML Table Support to Layout wtext (no_notebook instance) #41

Open wilsoc5 opened 6 years ago

wilsoc5 commented 6 years ago

I would like to layout some wtext objects into a table so that I may edit them dynamically based on user feedback. You can somewhat think of it as a read-only excel spreadsheet in HTML form, where all the values are determined by user input via sliders and other controls.

So I attempted to do something like:

import numpy as np
import vpython.no_notebook as vp

tableData = []
userData = [[1.0,0,0],
            [2.0,0,0]]
def buildTable(userData):
        global tableData
        vp.scene.append_to_caption('<table><thead><tr><th>Object Name</th><th>')
        tdHeaderXPosText = vp.wtext();
        tdHeaderXPosText.text = 'X Pos (m) '
        vp.scene.append_to_caption('</th><th>')
        tdHeaderYPosText = vp.wtext();
        tdHeaderYPosText.text = 'Y Pos (m) '
        vp.scene.append_to_caption('</th></tr></thead><tbody>')
        tableData.append([0,{'z':tdHeaderXPosText}])
        for ud in userData:
            x,y,_ = ud
            vp.scene.append_to_caption('<tr><td>')
            tdObjNameText = vp.wtext()
            tdObjNameText.text = tdObjNameText.text
            vp.scene.append_to_caption('</td><td>')
            tdObjXPosText = vp.wtext()
            tdObjXPosText.text = "%16.3f" % (x,)
            vp.scene.append_to_caption('</td><td>')
            tdObjYPosText = vp.wtext()
            tdObjYPosText.text = "%16.3f" % (y,)
            vp.scene.append_to_caption('</td></tr>')
            tableData.append([1,{'name':tdObjNameText,'x':tdObjXPosText,'y':tdObjYPosText}])
        vp.scene.append_to_caption('</tbody></table>')

buildTable(userData)

What ends up happening is that the first wtext entry tdHeaderXPosText closes the opened table. Additionally, all further Widget implementation is killed due to a javascript error:

Uncaught TypeError: Cannot read property 'childNodes' of null
    at ja (jquery.min.js:3)
    at Ha (jquery.min.js:3)
    at n.fn.init.append (jquery.min.js:3)
    at canvas.append_to_caption (glow.min.js:1)
    at handle_cmds ((index):552)
    at handler ((index):480)
    at WebSocket.ws.onmessage ((index):68)
BruceSherwood commented 6 years ago

Please provide an appropriate call to the BuildTable function so that it's possible to see the problem. Actually, it would probably be more useful to post this question to the VPython forum

https://groups.google.com/forum/?fromgroups&hl=en#!forum/vpython-users

where many more people would see it; perhaps someone has already found a way to do something like this.

wilsoc5 commented 6 years ago

Thanks, I didn't know about the forum. Minimal working example has been updated in the original comment.

I no longer get the javascript error, so that was probably something else. I'll poke around the forums for the table issue.

wilsoc5 commented 6 years ago

It seems like this has come up before: https://groups.google.com/forum/?fromgroups&hl=en#!searchin/vpython-users/html%7Csort:date/vpython-users/yA6s0V1UlY0/UI13ofxqBgAJ

When I am thinking about it I come to the question wether or not it would be helpful to have more access to html-control.

BruceSherwood commented 6 years ago

Not sure what is meant by "html-control", but as you saw, you can use jquery, which is surely more powerful than Wx. Incidentally, one of the many reasons we had to abandon Classic VPython (though not the determining issue) was that Wx for Python 3 was delayed and delayed and delayed.

pmelanson commented 5 years ago

As a workaround for anyone else with this issue, I was able to do the following:

scene.caption += '<table>'
wtext1 = vpython.wtext(text='initial text 1')
scene.caption += '<tr><td><div id="1">initial text 1</div></td></tr>'

wtext2 = vpython.wtext(text='initial text 2')
scene.caption += '<tr><td><div id="2">initial text 2</div></td></tr>'

scene.caption += '</table>'

Adding directly to scene.caption doesn't prematurely insert a closing tag, and it turns out wtexts are implemented by a div with id=1, id=2, etc incrementing each time a new wtext is made. Adding directly to scene.caption will also remove this special

from the caption, so you'll have to reinsert it (as the code above does).

The end result is a table with several embedded wtext fields.

Another workaround is making a wtext with a text field that contains HTML table tags etc., but every time this text field is updated any opened dropdown menus will be closed, so may not work for you.