flexx
flexx copied to clipboard
Set a PyWidget in e.g. StackLayout fails because its not using the sub Widget
Hi,
I have an application that looks like this:
- A main
PyWidget
object that acts like a hub widget, with some smaller widgets and aStackLayout
for displayingPage
widgets - Many
Page
widgets that are used to display some widgets, with each having read/updatePython
functions
Now if I make the page a Widget
, it is displayed correctly but I cannot use the Python
read/update functions.
But if I make it a PyWidget
, there is nothing displayed inside the main StackLayout
when I show a Page
inside it.
Is there a way to make this work without breaking up the Page
widget into two?
Thanks, Matic
My current working solution is to have two objects (one JS on Py) and a creation function like so:
class JsPage(flx.Widget):
py_page = flx.AnyProp(None, settable=True)
def init(self, py_page):
self.py_page = py_page
# Create all widgets
@flx.action
def set_value_of_widget_0(self, value):
# Set value
@flx.action
def set_value_of_widget_1(self, value):
# Set another value
...
class PyPage(flx.PyComponent):
def set_js_page(self, js_page):
self.js_page= js_page
def read(self):
# Read and store all data
def update(self):
self.js_page.set_value_of_widget_0(self.data[0])
self.js_page.set_value_of_widget_1(self.data[1])
...
def create_page():
py_page = PyPage()
js_page = Agregat(py_page)
worker.set_js_page(js_page )
return js_page
Why does the JsPage
have a reference to a PyPage
? Because I want to access everything from a single object, the JsPage
object:
# Create
page = create_page()
# Read
page.py_page.read()
# Update
page.py_page.update()
Is there a simple way of integrating the JsPage
and the PyPage
as one?
Thanks
This should work:
from flexx import flx
class MainPage(flx.PyWidget):
def init(self):
with flx.TabLayout():
Page("page 1")
Page("page 2")
Page("page 3")
class Page(flx.PyWidget):
def init(self, name):
flx.Button(text=name)
m = flx.launch(MainPage, "chrome-browser")
flx.run()
Yes, that works. But this does not:
from flexx import flx, event
class MainPage(flx.PyWidget):
def init(self):
with flx.HBox():
with flx.VBox():
self.buta = flx.Button(text='1')
self.butb = flx.Button(text='2')
self.butc = flx.Button(text='3')
flx.Widget(flex=1)
with flx.StackLayout(flex=1) as self.sl:
self.buta.w = Page("page 1")
self.butb.w = Page("page 2")
self.butc.w = Page("page 3")
@event.reaction('buta.pointer_down', 'butb.pointer_down', 'butc.pointer_down')
def _stacked_current(self, *events):
button = events[-1].source
print(button.w)
self.sl.set_current(button.w)
class Page(flx.PyWidget):
def init(self, name):
flx.Button(text=name)
m = flx.launch(MainPage, "firefox-browser")
flx.run()
When a button from 1 to 3 on the left side is pushed, an empty widget is displayed in the StackLayout instead of the corresponding page, even though the page object is printed correctly in the event? print(button.w) in the above code
Any Ideas?
Aah, this is because technically a PyWidget
is a PyComponent
that wraps a Widget
. It works if you change it to self.sl.set_current(button.w._jswidget)
.
This is a bit of a hack (using the private attribute), so we'd need to do something to make this work correctly. Maybe simply exposing the subwidget with a public attribute. Or convert when serializing a PyWidget. mmm, this needs some thoughts ...