diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..9937eed447154bcc3801b29dc2c6dfa370c3ee68 --- /dev/null +++ b/README.md @@ -0,0 +1,52 @@ +# Flutter UI for Python +#### 完成情况 2022-04-28 16:29:00 + +我完成的是lists和tabs简化版的例子 + +大概流程过程如下: + + - 首先我在https://material.io/components/lists和https://material.io/components/tabs找到lists和tabs的样例代码 + - 找到相应的Flutter代码,参考它构建类的接口 + - 再对照相应的Web代码,作为新建类的具体实现 + - 编写调试代码flutter_test_3.py验证结果 + +相关细节: + + - 对于lists这个Widget,我构建了两个类,一个是ListTile可以新建list的一项,另一个是ListView新建的是整个list的框架。 + 详细参考的Web代码如下: + +![输入图片说明](%E8%AF%B4%E6%98%8E%E6%96%87%E6%A1%A3%E5%BC%95%E7%94%A8%E5%9B%BE%E7%89%87/image.png) + + 编写的代码如下: + +![输入图片说明](%E8%AF%B4%E6%98%8E%E6%96%87%E6%A1%A3%E5%BC%95%E7%94%A8%E5%9B%BE%E7%89%87/image4.png) +![输入图片说明](%E8%AF%B4%E6%98%8E%E6%96%87%E6%A1%A3%E5%BC%95%E7%94%A8%E5%9B%BE%E7%89%87/image5.png) + + - 对于tabs这个Widget,同样我构建了两个类,一个是Tab可以新建tab的一项,另一个是TabBar新建的是整个tab的框架。 + 详细参考的Web代码如下: + +![输入图片说明](%E8%AF%B4%E6%98%8E%E6%96%87%E6%A1%A3%E5%BC%95%E7%94%A8%E5%9B%BE%E7%89%87/image1.png) + + 编写的代码如下: + +![输入图片说明](%E8%AF%B4%E6%98%8E%E6%96%87%E6%A1%A3%E5%BC%95%E7%94%A8%E5%9B%BE%E7%89%87/image6.png) +![输入图片说明](%E8%AF%B4%E6%98%8E%E6%96%87%E6%A1%A3%E5%BC%95%E7%94%A8%E5%9B%BE%E7%89%87/image7.png) + +遇到的问题: + + - 网页提供Flutter代码和Web代码并不是完全对应的,有些参数在Web代码上并没有体现,所以我只能简化相关内容。 + - 一些简单的赋值、maketag、appendChild等操作(可以确认没有写错)总是会导致程序运行出现问题(黑屏没有画面),这导致花了很长时间 + 完成,很多额外想做内容只能放弃。有时候能复制之前没有出现问题的语句再改成一样的内容可行。目前不知道为什么会这样。 + - 老师后面更新了代码,进行了调整 + +效果如下: + + - lists+tabs + +![输入图片说明](%E8%AF%B4%E6%98%8E%E6%96%87%E6%A1%A3%E5%BC%95%E7%94%A8%E5%9B%BE%E7%89%87/image2.png) + + - lists与tabs都可调整项目数量、每个项的文字内容和icon + +![输入图片说明](%E8%AF%B4%E6%98%8E%E6%96%87%E6%A1%A3%E5%BC%95%E7%94%A8%E5%9B%BE%E7%89%87/image3.png) + + diff --git a/web/index.html b/web/index.html index bcce34c98b43e81d8f09d598232b30d1fb9823c7..fbbd1a37ac4161a4b5d1ee36b2bef14e242fa83a 100755 --- a/web/index.html +++ b/web/index.html @@ -1,11 +1,8 @@ - - + - - @@ -16,10 +13,6 @@ - - diff --git a/web/ipad.html b/web/ipad.html index 72014f9a01c7c03d6f87663dd73cfba3f409974b..103c31a2fc9e7c8353ae855745ded448eae33abb 100755 --- a/web/ipad.html +++ b/web/ipad.html @@ -1,6 +1,18 @@ -
+ + + + +iPad + + + + +
- +
-
-
\ No newline at end of file +
+
+ + + \ No newline at end of file diff --git a/web/iphone.html b/web/iphone.html index 7fb96a59f2af79844e22b7f17cb566c0964339f1..e5994bfc4d3715bb2f62e4a17629a458de24b50b 100755 --- a/web/iphone.html +++ b/web/iphone.html @@ -1,6 +1,18 @@ -
+ + + + +iPhone + + + + +
- +
-
\ No newline at end of file +
+ + + \ No newline at end of file diff --git a/web/lib/apple.png b/web/lib/apple.png new file mode 100644 index 0000000000000000000000000000000000000000..8427fc61872af437de365c5e4124d33fcc5ceb66 Binary files /dev/null and b/web/lib/apple.png differ diff --git a/web/lib/mdc_test.html b/web/lib/mdc_test.html new file mode 100644 index 0000000000000000000000000000000000000000..37f8499d11f2c88e3591a291535b2cd0c6532d37 --- /dev/null +++ b/web/lib/mdc_test.html @@ -0,0 +1,2630 @@ + + + + + + MDC + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
+
+
+ + Fixed top app bars stay at the top of the page and elevate above the content when scrolled +
+ +
+
+
+ + + + + + + + + +

buttons

+ +
+ +
+ + +

Text button

+ + + + +

Text button with icon

+ + + + +

Outlined button

+ + + + +

Outlined button with icon

+ + + + +

Contained button

+ + + + +

Contained button with icon

+ + + + +

To add an icon

+ + + + +

use an SVG icon

+ + + + +

Trailing Icon

+ + + + +

Disabled

+ + + + + +

FAB (floating action button)

+ +
+ +
+ + +

Regular FAB example

+ + + + +

Mini FAB example

+ + + + +

Extended FAB example

+ + + + + + +

Cards

+ +
+
+ + +
+
+ + +

Outlined card with icon buttons

+ +
+
+ + + +
+
+ +

Rich media

+ +
+
+
+
Title
+
+
+
+
+ +

Actions

+ +
+
+
+
Title
+
+
+
+
+ + +
+
+ +

Actions 2

+ +
+
+
+
Title
+
+
+
+
+ + + +
+
+ + +

To have a single action button take up the entire width of the action row

+ +
+ +
+ + +

To display buttons and icons in the same row, wrap them in mdc-card__action-buttons and mdc-card__action-icons elements

+ +
+
+
+ + +
+
+ + +
+
+
+ + +

The following is an example incorporating all of the above elements

+ +
+
+
+
Title
+
+ +
+
+
+
+ + +
+
+ + +
+
+
+ + +

checkboxes

+ +
+
+ +
+ + + +
+
+
+
+
+ + +

Checkbox example

+ +
+
+ +
+ + + +
+
+
+
+ +
+ + +

Disabled checkboxes

+ +
+ +
+ + + +
+
+
+
+ + + +

Indeterminate checkboxes

+ +
+ +
+ + + +
+
+
+
+ + + + + + +

Chips

+ + + + + + + + + + + + + + + + + + + + +

Standard data table

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DessertCarbs (g)Protein (g)Comments
Frozen yogurt244.0Super tasty
Ice cream sandwich374.33333333333I like ice cream more
Eclair246.0New filing flavor
+
+
+ + +

Data table with row selection

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +
+
+
+
+
Signal nameStatusSeverityStageTimeRoles
+
+ +
+ + + +
+
+
+
+
Arcus watch slowdownOnlineMediumTriaged0:33Allison Brie
+
+ +
+ + + +
+
+
+
+
monarch: prod shared ares-managed-features-provider-heavyOfflineHugeTriaged0:33Brie Larson
+
+ +
+ + + +
+
+
+
+
monarch: prod shared ares-managed-features-provider-heavyOnlineMinorNot triaged0:33Jeremy Lake
+
+ +
+ + + +
+
+
+
+
Arcus watch slowdownOnlineNegligibleTriaged0:33Angelina Cheng
+
+
+ +

Data table with pagination

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DessertCarbs (g)Protein (g)Comments
Frozen yogurt244.0Super tasty
Ice cream sandwich374.33333333333I like ice cream more
Eclair246.0New filing flavor
+
+ +
+
+
+
+ Rows per page +
+ +
+
+ + 10 + + + + + + + + + + + + + +
+ +
+
    +
  • + 10 +
  • +
  • + 25 +
  • +
  • + 100 +
  • +
+
+
+
+ +
+
+ 1‑10 of 100 +
+ + + + +
+
+
+
+ +

Data table with progress indicator

+ + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DessertCarbs (g)Protein (g)Comments
Frozen yogurt244.0Super tasty
Ice cream sandwich374.33333333333I like ice cream more
Eclair246.0New filing flavor
+
+ +
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+ +

Data table with column sorting

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ Dessert +
+ + +
+
+
+ +
+ Carbs (g) +
+ +
+
+
+ +
+ Protein (g) +
+ +
+
+ Comments +
Frozen yogurt + 24 + + 4.0 + Super tasty
Bread + 10 + + 8.0 + Super tasty
+
+ + + + + +

Alert dialog

+ +
+
+
+
+ Discard draft? +
+
+ + +
+
+
+
+
+ + + + + + +

Simple dialog

+ +
+
+
+ +

Choose a Ringtone

+
+
    +
  • + None +
  • +
  • + Callisto +
  • + +
+
+
+
+
+
+ + + + +

Confirmation dialog

+ +
+
+
+ +

Choose a Ringtone

+
+
    +
  • + +
    + +
    +
    +
    +
    +
    +
    + +
  • + +
+
+
+ + +
+
+
+
+
+ + + + +

Full-screen dialog

+ + +
+
+ +
+
+
+ + + + +

Banner

+ + + + + + +

Fixed Banner

+ + + + + + + +

Banner with graphic

+ + + + + + + +

Banner with two actions

+ + + + + + +

Standard Image List

+ + + + + +

Masonry Image List

+ + + + +

Single-line list

+ + + + +

Two-line list

+ + + + +

List Groups

+ +
+

List 1

+ +

List 2

+ +
+ + +

List Dividers

+ + + + +

List Dividers 2

+ + +
+ + + +

Single Selection List

+ + + + +

Pre-selected list item

+ + + + +

List with radio group

+ + + + +

List with checkbox items

+ + + + + + + +

Basic Menu

+ + + +
+ +
+ + +

Selection Group Menu

+ + + +
+ +
+ + +

Anchored To Parent

+ +
+ + + + +
+ +

Anchor To Element Within Wrapper

+ +
+ + + + + + + +
+ + + +

Standard navigation drawers

+ + + + + +

Dismissible Modal drawers

+ +
+ +
+ + + +

Drawer with separate list groups

+ + + + +

Drawer with header

+ + + + + + + + +

radio buttons

+ +
+
+ +
+
+
+
+
+
+
+ + + + +

Radio button

+ +
+
+ +
+
+
+
+
+
+ +
+ + +

Disabled radio buttons

+ +
+
+ +
+
+
+
+
+
+ +
+ + + +

Continuous slider

+ +
+ +
+
+
+
+
+
+
+
+
+
+ + + + +

Continuous range slider

+ +
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + +

Discrete slider

+ +
+ +
+
+
+
+
+
+
+ +
+
+
+ + + + +

Discrete slider with tick marks

+ +
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+ + + + +

Discrete range slider

+ +
+ + +
+
+
+
+
+
+
+ +
+
+
+ +
+
+
+ + + + +

Disabled slider

+ +
+ +
+
+
+
+
+
+
+
+
+
+ + + + +

Snackbars

+ + + +
+ +
+ + + + +

Snackbars Stacked

+ + + +
+ +
+ + + + +

Snackbars Leading

+ + + +
+ +
+ + + + +

Switches

+ + + + + + + + + + + + + +

Tabs

+ +
+
+
+
+ + +
+
+
+
+ + + + +

text fields

+ + + +

Outlined text

+ + + +

Textarea

+ + + +

Textarea Outlined

+ + + +

Text field without label: Filled

+ + + +

Text field without label: Outlined

+ + + +

Text field without label: Textarea

+ + + +

Disabled text field

+ + + +

Text field with helper text

+ + +
+ +
+ +

Text field with character counter

+ + +
+
0 / 10
+
+ +

Multi-line text field (textarea) with character counter

+ + +
+
0 / 140
+
+ +

Multi-line text field (textarea) with character counter 2

+ + + +

Text field with prefix and suffix text

+ + + +

HTML5 validation

+ + + +

Pre-filled

+ + + +

Baseline alignment

+ +
+ + Text that is aligned with the text field's value +
+ +
+ + Text that is aligned to the bottom of the text field's outline +
+ + + + +

Tooltips

+ + + + Link + +

Rich tooltip

+ +
+ + +
+ +

Default rich tooltip with interactive content

+ +
+ + +
+ +

Persistent rich tooltip with interactive content

+ +
+ + +
+ + +

+ + + + + + + + + + +
+ + + + diff --git a/web/main.py b/web/main.py index c70e130d38edf5d2a57e82407e23c5a551ff3e08..592a946b8309295aa594e4fdee8c9ad338c3cbe1 100755 --- a/web/main.py +++ b/web/main.py @@ -2,5 +2,8 @@ # import flutter_test_1 # flutter_test_1.run_app() -import flutter_test_2 -flutter_test_2.run_app() +# import flutter_test_2 +# flutter_test_2.run_app() + +import flutter_test_3 +flutter_test_3.run_app() diff --git a/web/py_lib/flutter.py b/web/py_lib/flutter.py index 46d0d8564e0e8061734d990c0d976f66ef763faa..b23b16bf783248a6b95fbcea2809419c80326267 100755 --- a/web/py_lib/flutter.py +++ b/web/py_lib/flutter.py @@ -124,7 +124,7 @@ class Container: self.margin = margin self.boxShadow = boxShadow self.shape = shape - def render(self): + def render(self, parent): style = {} if self.width is not None: style['width'] = f'{self.width}px' if isinstance(self.width, int) else self.width @@ -149,7 +149,8 @@ class Container: if self.child.textAlign is not None: style['text-align'] = self.child.textAlign e = maketag('div', style=style) - e.appendChild(self.child.render()) + parent.appendChild(e) + self.child.render(e) return e class FontWeight: @@ -214,7 +215,7 @@ class Text: self.style = style self.overflow = overflow self.maxLines = maxLines - def render(self): + def render(self, parent): style = {} if self.style is not None: style['font'] = str(self.style) @@ -234,6 +235,7 @@ class Text: style['-webkit-line-clamp'] = self.maxLines style['-webkit-box-orient'] = 'vertical' e = maketag('div', style=style) + parent.appendChild(e) p = javascript.document.createTextNode(self.text) e.appendChild(p) return e @@ -242,8 +244,8 @@ class RichText: def __init__(self, text): assert isinstance(text, TextSpan) self.text = text - def render(self): - return self.text.render() + def render(self, parent): + return self.text.render(parent) class TextSpan: def __init__(self, text=None, color=None, style=None, children=None): @@ -260,7 +262,7 @@ class TextSpan: self.color = color self.style = style self.children = children - def render(self): + def render(self, parent): style = {} if self.style is not None: style['font'] = str(self.style) @@ -274,22 +276,24 @@ class TextSpan: if self.color is not None: style['color'] = self.color e = maketag('span', style=style) + parent.appendChild(e) if self.text is not None: p = javascript.document.createTextNode(self.text) e.appendChild(p) elif self.children is not None: for c in self.children: - e.appendChild(c.render()) + c.render(e) return e class Center: def __init__(self, child): assert hasattr(child, 'render') and callable(child.render) self.child = child - def render(self): + def render(self, parent): e = maketag('div', style={'display': 'flex', 'align-items': 'center', 'justify-content': 'center', 'width': '100%', 'height': '100%'}) - e.appendChild(self.child.render()) + parent.appendChild(e) + self.child.render(e) return e class Stack: @@ -298,10 +302,11 @@ class Stack: for c in children: assert isinstance(c, Positioned) self.children = children - def render(self): + def render(self, parent): e = maketag('div',style={'position':'relative'}) for c in self.children: - e.appendChild(c.render()) + c.render(e) + parent.appendChild(e) return e class Positioned: @@ -312,11 +317,12 @@ class Positioned: self.child = child self.left = left self.top = top - def render(self): + def render(self, parent): top = f'{self.top}px' if isinstance(self.top, int) else self.top left = f'{self.left}px' if isinstance(self.left, int) else self.left e = maketag('div', style={'position':'absolute','top':top,'left':left}) - e.appendChild(self.child.render()) + parent.appendChild(e) + self.child.render(e) return e class Transform: @@ -327,7 +333,7 @@ class Transform: self.child = child self.rotate = rotate self.scale = scale - def render(self): + def render(self, parent): transform = [] if self.rotate is not None: rotate = f'{self.rotate}deg' if isinstance(self.rotate, int) else self.rotate @@ -335,9 +341,10 @@ class Transform: if self.scale is not None: transform.append(f'scale({self.scale})') e = maketag('div') + parent.appendChild(e) if len(transform)>0: e.style.transform = ' '.join(transform) - e.appendChild(self.child.render()) + self.child.render(e) return e @@ -393,7 +400,7 @@ class Flex: self.mainAxisAlignment = mainAxisAlignment self.crossAxisAlignment = crossAxisAlignment self.mainAxisSize = mainAxisSize - def render(self): + def render(self, parent): style = {'display': 'flex', 'flex-direction': self.direction, 'flex-wrap': 'nowrap', @@ -405,8 +412,9 @@ class Flex: else: style['height'] = '100%' e = maketag('div', style=style) + parent.appendChild(e) for child in self.children: - e.appendChild(child.render()) + child.render(e) return e class Row(Flex): @@ -432,69 +440,27 @@ class Column(Flex): mainAxisSize=mainAxisSize) -# 如何开发 MaterialDesignWidgets (用AppBar作为例子): -# -# 1. 在 https://material.io/components/app-bars-top/flutter -# 找到 AppBar 的 Dart 例子后适当简化并翻译为 Python -# -# Scaffold( -# appBar=AppBar( -# leading=IconButton( -# icon=Icon(Icons.menu), -# onPressed=None, -# ), -# title=Text('Example title'), -# actions=[ -# IconButton( -# icon=Icon(Icons.search), -# onPressed=None, -# ), -# ], -# ), -# # body is the majority of the screen. -# body=Center( -# child=Text('Hello, world!'), -# ), -# ) -# -# 2. 在 https://material.io/components/app-bars-top/web -# 找到 AppBar 的 Web实现: -# -#
-#
-#
-# -# Page title -#
-# -#
-#
-#
-# App content -#
-# -# 3. 设计和实现各个需要的 Python 类: Scaffold, AppBar, IconButton, Icon, Icons +# MDC (Material Design Components) class Scaffold: def __init__(self, appBar, body): - if appBar is not None: - assert hasattr(appBar, 'render') and callable(appBar.render) - if body is not None: - assert hasattr(body, 'render') and callable(body.render) + assert hasattr(appBar, 'render') and callable(appBar.render) + assert hasattr(body, 'render') and callable(body.render) self.appBar = appBar self.body = body - def render(self): - e = maketag('div') - header = maketag('header', {'class':'mdc-top-app-bar'}) + def render(self, parent): + scafflod_height = javascript.document.documentElement.clientHeight.data() + e = maketag('div', style={'display':'flex', 'flex-flow':'column', 'height':f'{scafflod_height}px'}) + header = maketag('header', {'class':'mdc-top-app-bar mdc-top-app-bar--fixed'}, + style={'flex': '0 1 auto'}) + parent.appendChild(e) e.appendChild(header) - main = maketag('header', {'class':'mdc-top-app-bar--fixed-adjust'}) + main = maketag('header', {'class':'mdc-top-app-bar--fixed-adjust'}, + style={'flex': '1 1 auto'}) e.appendChild(main) - header.appendChild(self.appBar.render()) - main.appendChild(self.body.render()) + self.appBar.render(header) + self.body.render(main) + self.topAppBar = javascript.mdc.topAppBar.MDCTopAppBar.new(e) return e class AppBar: @@ -510,25 +476,23 @@ class AppBar: self.leading = leading self.title = title self.actions = actions - def render(self): + def render(self, parent): e = maketag('div', {'class':'mdc-top-app-bar__row'}) + parent.appendChild(e) start = maketag('header', {'class':'mdc-top-app-bar__section mdc-top-app-bar__section--align-start'}) e.appendChild(start) end = maketag('header', {'class':'mdc-top-app-bar__section mdc-top-app-bar__section--align-end', 'rule':'toolbar'}) e.appendChild(end) if self.leading is not None: - leading = self.leading.render() + leading = self.leading.render(start) add_class(leading, 'mdc-top-app-bar__navigation-icon') - start.appendChild(leading) if self.title is not None: - title = self.title.render() + title = self.title.render(start) add_class(title, 'mdc-top-app-bar__title') - start.appendChild(title) if self.actions is not None: for action in self.actions: - action = action.render() + action = action.render(end) add_class(action, 'mdc-top-app-bar__action-item') - end.appendChild(action) return e class IconButton: @@ -538,19 +502,22 @@ class IconButton: assert callable(onPressed) self.icon = icon self.onPressed = onPressed - def render(self): + def render(self, parent): e = maketag('button', {'class':'material-icons mdc-top-app-bar__action-item mdc-icon-button'}) + parent.appendChild(e) e.appendChild(javascript.document.createTextNode(self.icon.icon)) if self.onPressed is not None: e.bind('click', self.onPressed) + javascript.mdc.ripple.MDCRipple.new(e) return e class Icon: def __init__(self, icon): assert isinstance(icon, str) self.icon = icon - def render(self): + def render(self, parent): e = maketag('span', {'class':'material-icons'}) + parent.appendChild(e) e.appendChild(javascript.document.createTextNode(self.icon)) return e @@ -576,3 +543,91 @@ Icons = flutter_icons.Icons # https://material.io/components/tabs # https://material.io/components/text-fields # https://material.io/components/tooltips +class ListTile: + def __init__(self, leading=None, title=None): + if leading is not None: + assert hasattr(leading, 'render') and callable(leading.render) + if title is not None: + assert hasattr(title, 'render') and callable(title.render) + self.leading = leading + self.title = title + + def render(self,parent): + e = maketag('li', {'class':'mdc-list-item'}) + parent.appendChild(e) + e1 = maketag('span',{'class':'mdc-list-item__ripple'}) + e.appendChild(e1) + if self.leading is not None: + leading = self.leading.render(e) + if self.title is not None: + title = self.title.render(e) + add_class(title, 'mdc-list-item__text') + return e + +class ListView: + def __init__(self, children=None): + if children is not None: + for tmp in children: + assert hasattr(tmp, 'render') and callable(tmp.render) + self.children = children + + def render(self,parent): + e = maketag('ul', {'class':'mdc-list'}) + if self.children is not None: + for tmp in self.children: + tmp.render(e) + parent.appendChild(e) + return e + +class Tab: + def __init__(self, text=None, icon=None): + if text is not None: + assert hasattr(text, 'render') and callable(text.render) + if icon is not None: + assert hasattr(icon, 'render') and callable(icon.render) + self.text = text + self.icon = icon + + def render(self,parent): + if True: + e = maketag('button', {'class':'mdc-tab mdc-tab--active','role':'tab'}) + e1 = maketag('span', {'class':'mdc-tab__content'}) + e.appendChild(e1) + e2 = maketag('span', {'class':'mdc-tab-indicator mdc-tab-indicator--active'}) + e.appendChild(e2) + e3 = maketag('span', {'class':'mdc-tab-indicator__content mdc-tab-indicator__content--underline'}) + e2.appendChild(e3) + e4 = maketag('span', {'class':'mdc-tab__ripple'}) + e.appendChild(e4) + + if self.icon is not None: + icon = self.icon.render(e1) + add_class(icon, 'mdc-tab__icon material-icons') + if self.text is not None: + text = self.text.render(e1) + add_class(text, 'mdc-tab__text-label') + parent.appendChild(e) + return e + +class TabBar: + def __init__(self, tabs=None): + if tabs is not None: + for tmp in tabs: + assert hasattr(tmp, 'render') and callable(tmp.render) + self.tabs = tabs + + def render(self,parent): + e = maketag('div', {'class':'mdc-tab-bar','role':'tablist'}) + if True: + e1 = maketag('div', {'class':'mdc-tab-scroller'}) + e.appendChild(e1) + e2 = maketag('div', {'class':'mdc-tab-scroller__scroll-area'}) + e1.appendChild(e2) + e3 = maketag('div', {'class':'mdc-tab-scroller__scroll-content'}) + e2.appendChild(e3) + + if self.tabs is not None: + for tmp in self.tabs: + tmp.render(e3) + parent.appendChild(e) + return e \ No newline at end of file diff --git a/web/py_lib/flutter_test_2.py b/web/py_lib/flutter_test_2.py index f80538c95e3e4b70c90a215348ecde60de781234..a3089e6a460d0160733416fe55391151f9f6568d 100755 --- a/web/py_lib/flutter_test_2.py +++ b/web/py_lib/flutter_test_2.py @@ -28,6 +28,8 @@ Icons = flutter.Icons # https://flutter.cn/docs/development/ui/widgets-intro def 使用Material组件(): + sysu_info = '''中山大学由孙中山先生创办,有着一百多年办学传统。作为中国教育部直属高校,通过部省共建,中山大学已经成为一所国内一流、国际知名的现代综合性大学。现由广州校区、珠海校区、深圳校区三个校区、五个校园及十家附属医院组成。中山大学正在向世界一流大学迈进,努力成为全球学术重镇。 + 中山大学具有人文社科和理医工多学科厚实基础,不断追求学术创新,以国际视野开放办学,现已形成了“综合性、研究型、开放式”的特色。学校坚持中国特色社会主义办学方向,坚持立德树人根本,以“面向世界科技前沿、面向经济主战场、面向国家重大需求、面向人民生命健康”为基本导向;树立了“三校区五校园”错位发展、合力支撑的发展思路。学校正在努力推进由外延式发展向内涵式发展转变,由常规发展向主动发展转变,由文理医优势向文理医工各具特色、融合发展转变。现在,中山大学正站在新的起点上,为稳居国内高校第一方阵,建设世界一流大学的目标努力奋斗!''' return Scaffold( appBar=AppBar( leading=IconButton( @@ -45,14 +47,12 @@ def 使用Material组件(): # body is the majority of the screen. body=Container( Center( - child=Text('Hello, world!'), + child=Text(sysu_info), ), - width=312, - height=480-72, color=Colors.white, ), ) def run_app(): widget = 使用Material组件() - javascript.document.body.appendChild(widget.render()) + widget.render(parent=javascript.document.body) diff --git a/web/py_lib/flutter_test_3.py b/web/py_lib/flutter_test_3.py new file mode 100644 index 0000000000000000000000000000000000000000..75b7a6e599b813ed2a455456bb7b904921ce11c5 --- /dev/null +++ b/web/py_lib/flutter_test_3.py @@ -0,0 +1,74 @@ + +from . import flutter +TextStyle = flutter.TextStyle +Container = flutter.Container +Center = flutter.Center +Text = flutter.Text +Stack = flutter.Stack +Positioned = flutter.Positioned +Transform = flutter.Transform +LinearGradient = flutter.LinearGradient +Colors = flutter.Colors +TextAlign = flutter.TextAlign +EdgeInsets = flutter.EdgeInsets +FontWeight = flutter.FontWeight +FontStyle = flutter.FontStyle +BoxShadow = flutter.BoxShadow +BoxShape = flutter.BoxShape +RichText = flutter.RichText +TextSpan = flutter.TextSpan +TextOverflow = flutter.TextOverflow +BorderRadius = flutter.BorderRadius +Offset = flutter.Offset +Scaffold = flutter.Scaffold +AppBar = flutter.AppBar +IconButton = flutter.IconButton +Icon = flutter.Icon +Icons = flutter.Icons +ListTile = flutter.ListTile +ListView = flutter.ListView +Tab = flutter.Tab +TabBar = flutter.TabBar +# https://flutter.cn/docs/development/ui/widgets-intro + + +def 使用Material组件(): + return Scaffold( + appBar=AppBar( + leading=IconButton( + icon=Icon(Icons.menu), + onPressed=None, + ), + title=Text('Example title'), + actions=[ + IconButton( + icon=Icon(Icons.search), + onPressed=None, + ), + ], + ), + # body is the majority of the screen. + body=Container( + child=Stack(children=[Positioned(child=ListView( + children=[ + ListTile(leading=Icon(Icons.label),title=Text('Single-line item 1')), + ListTile(leading=Icon(Icons.label),title=Text('Single-line item 2')), + ListTile(leading=Icon(Icons.label),title=Text('Single-line item 3')), + ListTile(leading=Icon(Icons.label),title=Text('Single-line item 4')), + ], + ),left=0,top=0), + Positioned(child=TabBar( + tabs = [ + Tab(icon = Icon(Icons.favorite), text = Text('FAVORITE'), ), + Tab(icon = Icon(Icons.search), text = Text('SEARCH'), ), + ], + ),left=10,top=350,),],), + width=320, + height=480-72, + color=Colors.white, + ), + ) + +def run_app(): + widget = 使用Material组件() + widget.render(parent=javascript.document.body) diff --git "a/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/.keep" "b/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/.keep" new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git "a/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image.png" "b/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image.png" new file mode 100644 index 0000000000000000000000000000000000000000..37053248db1020a9378b7e2b803f678057b35d4e Binary files /dev/null and "b/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image.png" differ diff --git "a/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image1.png" "b/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image1.png" new file mode 100644 index 0000000000000000000000000000000000000000..b8b5e448abde72846f97fcfaba2386299b69b580 Binary files /dev/null and "b/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image1.png" differ diff --git "a/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image2.png" "b/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image2.png" new file mode 100644 index 0000000000000000000000000000000000000000..97d66d9016810bbc14da5ecfc6891cb9bbd47a7e Binary files /dev/null and "b/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image2.png" differ diff --git "a/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image3.png" "b/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image3.png" new file mode 100644 index 0000000000000000000000000000000000000000..a97a855b641536e13f999da406647fe0e0d3ebad Binary files /dev/null and "b/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image3.png" differ diff --git "a/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image4.png" "b/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image4.png" new file mode 100644 index 0000000000000000000000000000000000000000..d162a3283df305f99dc37084ba3e9acb56ebbfd8 Binary files /dev/null and "b/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image4.png" differ diff --git "a/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image5.png" "b/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image5.png" new file mode 100644 index 0000000000000000000000000000000000000000..6f252077aa77ff5fb95659b5087642675a0ce500 Binary files /dev/null and "b/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image5.png" differ diff --git "a/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image6.png" "b/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image6.png" new file mode 100644 index 0000000000000000000000000000000000000000..92ac85b272d36c4a03a8ab0c0e6a15602f0f8bce Binary files /dev/null and "b/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image6.png" differ diff --git "a/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image7.png" "b/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image7.png" new file mode 100644 index 0000000000000000000000000000000000000000..2300591d39fd0f8fee9fb1686c1b7cba4aa397c2 Binary files /dev/null and "b/\350\257\264\346\230\216\346\226\207\346\241\243\345\274\225\347\224\250\345\233\276\347\211\207/image7.png" differ