flexgui 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flexgui-1.0.0/LICENSE +21 -0
- flexgui-1.0.0/PKG-INFO +235 -0
- flexgui-1.0.0/README.md +205 -0
- flexgui-1.0.0/flexgui/__init__.py +71 -0
- flexgui-1.0.0/flexgui/app.py +221 -0
- flexgui-1.0.0/flexgui/builder.py +211 -0
- flexgui-1.0.0/flexgui/designer.py +1974 -0
- flexgui-1.0.0/flexgui/editor.py +277 -0
- flexgui-1.0.0/flexgui/mode.py +95 -0
- flexgui-1.0.0/flexgui/registry.py +188 -0
- flexgui-1.0.0/flexgui/runtime.py +190 -0
- flexgui-1.0.0/flexgui/theme.py +139 -0
- flexgui-1.0.0/flexgui/triggers.py +467 -0
- flexgui-1.0.0/flexgui/widgets.py +738 -0
- flexgui-1.0.0/pyproject.toml +42 -0
flexgui-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 FlexGUI Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
flexgui-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: flexgui
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Thư viện GUI Python kéo-thả-thiết-kế trên tkinter — FlexGUI Studio tích hợp (design mode + mini VS Code cho trigger)
|
|
5
|
+
Keywords: gui,tkinter,designer,drag-and-drop,visual-designer,no-code,vietnamese,flexgui
|
|
6
|
+
Author: FlexGUI Team
|
|
7
|
+
Requires-Python: >=3.8
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Software Development :: User Interfaces
|
|
22
|
+
Classifier: Natural Language :: Vietnamese
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: pyinstaller>=6.0 ; extra == "build"
|
|
25
|
+
Project-URL: Documentation, https://github.com/your-name/flexgui#readme
|
|
26
|
+
Project-URL: Homepage, https://github.com/your-name/flexgui
|
|
27
|
+
Provides-Extra: build
|
|
28
|
+
Import-Name: flexgui
|
|
29
|
+
|
|
30
|
+
# FlexGUI
|
|
31
|
+
|
|
32
|
+
**Thư viện GUI Python kéo-thả-thiết-kế trên tkinter** — viết code siêu gọn,
|
|
33
|
+
thiết kế giao diện bằng chuột trong **FlexGUI Studio** (nền tối hiện đại),
|
|
34
|
+
code trigger sửa được **ngay trong Studio hoặc VS Code**, đóng gói `.exe`
|
|
35
|
+
một cú click.
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install flexgui
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 1. Viết code thuần (60 giây)
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
import flexgui
|
|
47
|
+
from flexgui import App, Label, Button, Input, Checkbox, Text
|
|
48
|
+
|
|
49
|
+
app = App("Ứng dụng của tôi", 860, 560)
|
|
50
|
+
|
|
51
|
+
Label("Xin chào!", 40, 30) # label[1]
|
|
52
|
+
Button("Bấm tôi", 40, 80) # button[2]
|
|
53
|
+
Input(40, 130, width=26) # input[3]
|
|
54
|
+
Checkbox("Đồng ý", 40, 180) # checkbox[4]
|
|
55
|
+
Text(40, 230, width=42, height=7) # text[5]
|
|
56
|
+
|
|
57
|
+
app.run()
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Mọi widget định vị **tuyệt đối bằng `place(x, y)`** — đặt đâu nằm đó,
|
|
61
|
+
chồng lớp tự do.
|
|
62
|
+
|
|
63
|
+
## 2. Chế độ thiết kế — FlexGUI Studio
|
|
64
|
+
|
|
65
|
+
Thêm **một dòng** vào file là mở được trình thiết kế:
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
import flexgui
|
|
69
|
+
|
|
70
|
+
flexgui.setup() # hoặc: from flexgui import design; design.mode = True
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Chạy `python myapp.py` → **Studio tự mở giao diện trống** (hoặc nạp
|
|
74
|
+
thiết kế đã lưu). Tính năng:
|
|
75
|
+
|
|
76
|
+
- Kéo thả mượt (canvas item — không tàn ảnh), **snap lưới 10px** (bật/tắt)
|
|
77
|
+
- **Resize 8 núm** quanh thành phần đang chọn
|
|
78
|
+
- **Multi-select**: Ctrl/Shift + click, quét vùng chuột, kéo cả cụm
|
|
79
|
+
- Đổi z-order (menu chuột phải), nhân bản `Ctrl+D`, undo/redo `Ctrl+Z/Y`
|
|
80
|
+
- Bảng thuộc tính bên phải: chữ, tọa độ, kích thước **pixel WYSIWYG**,
|
|
81
|
+
màu chữ/nền, cỡ chữ, ẩn khi chạy, khoá...
|
|
82
|
+
- **Xem trước F5** — chạy thử app thật + trigger thật ngay tại chỗ
|
|
83
|
+
- **Build .exe** bằng PyInstaller (nút 📦 — tự cài nếu thiếu)
|
|
84
|
+
- **Xuất .py** — 1 file tự chạy nhúng toàn bộ thiết kế + trigger
|
|
85
|
+
|
|
86
|
+
`Ctrl+S` lưu 2 file cạnh `myapp.py`:
|
|
87
|
+
|
|
88
|
+
| File | Nội dung |
|
|
89
|
+
|---|---|
|
|
90
|
+
| `myapp.flexgui.json` | bố cục + thuộc tính mọi thành phần |
|
|
91
|
+
| `myapp.triggers.py` | **code trigger — file dùng chung** |
|
|
92
|
+
|
|
93
|
+
## 3. Trigger — sửa ở Studio HOẶC VS Code đều được
|
|
94
|
+
|
|
95
|
+
`myapp.triggers.py` là file Python thật: mở bằng **mini VS Code** trong
|
|
96
|
+
Studio (nút ⌨ Triggers) **hoặc** VS Code ngoài — cả hai sửa cùng một file.
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
# myapp.triggers.py — label/button/... đã có sẵn, không cần import
|
|
100
|
+
|
|
101
|
+
def on_start(): # chạy 1 lần khi app mở
|
|
102
|
+
label[1].set_text("Xin chào!")
|
|
103
|
+
|
|
104
|
+
def on_button_2_click(): # bấm button[2]
|
|
105
|
+
import random # Python thật — import gì cũng được
|
|
106
|
+
label[1].set_text(f"Số: {random.randint(1, 99)}")
|
|
107
|
+
|
|
108
|
+
def on_checkbox_4_toggle(): # tick/bỏ tick checkbox[4]
|
|
109
|
+
text[5].visible = checkbox[4].checked
|
|
110
|
+
|
|
111
|
+
def on_input_3_enter(): # Enter trong input[3]
|
|
112
|
+
alert("Bạn vừa gõ: " + input[3].text)
|
|
113
|
+
|
|
114
|
+
def on_text_5_change(): # gõ chữ trong text[5]
|
|
115
|
+
pass
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Quy ước tên hàm: `on_<loại>_<id>_<sự kiện>`
|
|
119
|
+
(`click` / `toggle` / `enter` / `change`). Studio tự sinh sườn hàm khi lưu.
|
|
120
|
+
|
|
121
|
+
Kiểu **decorator** mạnh hơn (cũng viết trong file trigger):
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
@on_click(button[2])
|
|
125
|
+
def xu_ly(): ...
|
|
126
|
+
|
|
127
|
+
@on_change(input[3]) # gõ bất kỳ chữ nào
|
|
128
|
+
def khi_go(): ...
|
|
129
|
+
|
|
130
|
+
@when(lambda: checkbox[4].checked and input[3].text == "admin")
|
|
131
|
+
def khi_du(): ... # điều kiện SAI → ĐÚNG mới chạy
|
|
132
|
+
|
|
133
|
+
@every(1000) # lặp mỗi giây
|
|
134
|
+
def dong_ho(): ...
|
|
135
|
+
|
|
136
|
+
@on_init # = on_start
|
|
137
|
+
def khoi_dong(): ...
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## 4. Chạy thật
|
|
141
|
+
|
|
142
|
+
Đổi 1 dòng trong `myapp.py`:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
import flexgui
|
|
146
|
+
|
|
147
|
+
flexgui.run(__file__) # nạp myapp.flexgui.json + myapp.triggers.py
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Hoặc dùng cờ dòng lệnh quen thuộc: `python myapp.py --design`.
|
|
151
|
+
|
|
152
|
+
## 5. Thuộc tính & lệnh điều khiển widget
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
from flexgui import label, button, input, checkbox, text
|
|
156
|
+
|
|
157
|
+
label[1].text = "Số đếm: 5" # đọc/ghi trực tiếp
|
|
158
|
+
label[1].set_text("...") # tương đương
|
|
159
|
+
label[1].get_text()
|
|
160
|
+
label[1].x = 200 # tọa độ pixel (đọc/ghi)
|
|
161
|
+
label[1].color = "red" # màu chữ
|
|
162
|
+
label[1].bg = "#FFF3B0" # màu nền
|
|
163
|
+
label[1].font_size = 14
|
|
164
|
+
label[1].visible = False # tàng hình / hiện lại
|
|
165
|
+
label[1].enabled = False # khoá / mở
|
|
166
|
+
label[1].place(120, 80) # đặt lại vị trí tuyệt đối
|
|
167
|
+
label[1].move(10, 0) # dịch tương đối
|
|
168
|
+
label[1].resize(220, 30) # cỡ pixel WYSIWYG
|
|
169
|
+
label[1].refresh() # vẽ lại mọi thuộc tính đã lưu
|
|
170
|
+
label[1].show() / .hide() / .focus()
|
|
171
|
+
|
|
172
|
+
checkbox[4].checked = True # (chỉ Checkbox)
|
|
173
|
+
checkbox[4].toggle()
|
|
174
|
+
button[2].command = ham_xu_ly # gán lệnh bằng code
|
|
175
|
+
|
|
176
|
+
# Lệnh app — gọi thẳng trong trigger
|
|
177
|
+
refresh() · set_title("...") · set_size(1024, 640) · set_bg("black")
|
|
178
|
+
alert("...") · confirm("...?") → True/False · prompt("Tên?") → str/None
|
|
179
|
+
close_app()
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Widget bị xóa thì `input[3]` trả **widget rỗng an toàn** — code cũ không
|
|
183
|
+
bao giờ văng lỗi. ID **tái sử dụng**: xóa `input[3]` rồi thêm widget mới
|
|
184
|
+
thì widget mới nhận lại đúng ID `[3]`.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Đóng gói & chia sẻ
|
|
189
|
+
|
|
190
|
+
- **Build .exe** (nút 📦 trong Studio): PyInstaller tự động — file nằm
|
|
191
|
+
trong `flexgui_build/dist/`.
|
|
192
|
+
- **Xuất .py** (nút ▲): 1 file duy nhất nhúng thiết kế + trigger — chạy
|
|
193
|
+
bằng `python ten_file.py` (cần `pip install flexgui`).
|
|
194
|
+
|
|
195
|
+
## Cấu trúc package
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
flexgui/
|
|
199
|
+
├── __init__.py # API công khai: App, 5 widget, run/setup/design...
|
|
200
|
+
├── mode.py # design.mode = True
|
|
201
|
+
├── registry.py # label[1] / button[2] ... + widget rỗng an toàn
|
|
202
|
+
├── widgets.py # Label/Button/Input/Checkbox/Text (pixel WYSIWYG)
|
|
203
|
+
├── triggers.py # engine trigger + decorator + lệnh app
|
|
204
|
+
├── app.py # cửa sổ App + ID tái sử dụng
|
|
205
|
+
├── runtime.py # run() / setup() / run_embedded()
|
|
206
|
+
├── editor.py # mini VS Code (tô màu Python, IME tiếng Việt an toàn)
|
|
207
|
+
├── designer.py # FlexGUI Studio (canvas Figma-style)
|
|
208
|
+
└── builder.py # xuất file đơn + PyInstaller
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Yêu cầu
|
|
212
|
+
|
|
213
|
+
- Python 3.8+ (chỉ dùng thư viện chuẩn — **không cần cài thêm gì**)
|
|
214
|
+
- Build `.exe` cần `pip install pyinstaller` (Studio tự cài nếu thiếu)
|
|
215
|
+
|
|
216
|
+
## Đăng package lên PyPI (cho người phát hành)
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
pip install --upgrade build twine
|
|
220
|
+
|
|
221
|
+
# 1. build sdist + wheel (ra thư mục dist/)
|
|
222
|
+
python -m build
|
|
223
|
+
|
|
224
|
+
# 2. đăng (cần tài khoản PyPI + API token tại pypi.org)
|
|
225
|
+
twine upload dist/*
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Sau đó mọi người cài chỉ với `pip install flexgui`.
|
|
229
|
+
*Lưu ý: nếu tên `flexgui` đã bị ai chiếm trên PyPI, đổi `name` trong
|
|
230
|
+
`pyproject.toml` (ví dụ `flexgui-vn`) rồi build lại.*
|
|
231
|
+
|
|
232
|
+
## License
|
|
233
|
+
|
|
234
|
+
MIT
|
|
235
|
+
|
flexgui-1.0.0/README.md
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# FlexGUI
|
|
2
|
+
|
|
3
|
+
**Thư viện GUI Python kéo-thả-thiết-kế trên tkinter** — viết code siêu gọn,
|
|
4
|
+
thiết kế giao diện bằng chuột trong **FlexGUI Studio** (nền tối hiện đại),
|
|
5
|
+
code trigger sửa được **ngay trong Studio hoặc VS Code**, đóng gói `.exe`
|
|
6
|
+
một cú click.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
pip install flexgui
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 1. Viết code thuần (60 giây)
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
import flexgui
|
|
18
|
+
from flexgui import App, Label, Button, Input, Checkbox, Text
|
|
19
|
+
|
|
20
|
+
app = App("Ứng dụng của tôi", 860, 560)
|
|
21
|
+
|
|
22
|
+
Label("Xin chào!", 40, 30) # label[1]
|
|
23
|
+
Button("Bấm tôi", 40, 80) # button[2]
|
|
24
|
+
Input(40, 130, width=26) # input[3]
|
|
25
|
+
Checkbox("Đồng ý", 40, 180) # checkbox[4]
|
|
26
|
+
Text(40, 230, width=42, height=7) # text[5]
|
|
27
|
+
|
|
28
|
+
app.run()
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Mọi widget định vị **tuyệt đối bằng `place(x, y)`** — đặt đâu nằm đó,
|
|
32
|
+
chồng lớp tự do.
|
|
33
|
+
|
|
34
|
+
## 2. Chế độ thiết kế — FlexGUI Studio
|
|
35
|
+
|
|
36
|
+
Thêm **một dòng** vào file là mở được trình thiết kế:
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
import flexgui
|
|
40
|
+
|
|
41
|
+
flexgui.setup() # hoặc: from flexgui import design; design.mode = True
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Chạy `python myapp.py` → **Studio tự mở giao diện trống** (hoặc nạp
|
|
45
|
+
thiết kế đã lưu). Tính năng:
|
|
46
|
+
|
|
47
|
+
- Kéo thả mượt (canvas item — không tàn ảnh), **snap lưới 10px** (bật/tắt)
|
|
48
|
+
- **Resize 8 núm** quanh thành phần đang chọn
|
|
49
|
+
- **Multi-select**: Ctrl/Shift + click, quét vùng chuột, kéo cả cụm
|
|
50
|
+
- Đổi z-order (menu chuột phải), nhân bản `Ctrl+D`, undo/redo `Ctrl+Z/Y`
|
|
51
|
+
- Bảng thuộc tính bên phải: chữ, tọa độ, kích thước **pixel WYSIWYG**,
|
|
52
|
+
màu chữ/nền, cỡ chữ, ẩn khi chạy, khoá...
|
|
53
|
+
- **Xem trước F5** — chạy thử app thật + trigger thật ngay tại chỗ
|
|
54
|
+
- **Build .exe** bằng PyInstaller (nút 📦 — tự cài nếu thiếu)
|
|
55
|
+
- **Xuất .py** — 1 file tự chạy nhúng toàn bộ thiết kế + trigger
|
|
56
|
+
|
|
57
|
+
`Ctrl+S` lưu 2 file cạnh `myapp.py`:
|
|
58
|
+
|
|
59
|
+
| File | Nội dung |
|
|
60
|
+
|---|---|
|
|
61
|
+
| `myapp.flexgui.json` | bố cục + thuộc tính mọi thành phần |
|
|
62
|
+
| `myapp.triggers.py` | **code trigger — file dùng chung** |
|
|
63
|
+
|
|
64
|
+
## 3. Trigger — sửa ở Studio HOẶC VS Code đều được
|
|
65
|
+
|
|
66
|
+
`myapp.triggers.py` là file Python thật: mở bằng **mini VS Code** trong
|
|
67
|
+
Studio (nút ⌨ Triggers) **hoặc** VS Code ngoài — cả hai sửa cùng một file.
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
# myapp.triggers.py — label/button/... đã có sẵn, không cần import
|
|
71
|
+
|
|
72
|
+
def on_start(): # chạy 1 lần khi app mở
|
|
73
|
+
label[1].set_text("Xin chào!")
|
|
74
|
+
|
|
75
|
+
def on_button_2_click(): # bấm button[2]
|
|
76
|
+
import random # Python thật — import gì cũng được
|
|
77
|
+
label[1].set_text(f"Số: {random.randint(1, 99)}")
|
|
78
|
+
|
|
79
|
+
def on_checkbox_4_toggle(): # tick/bỏ tick checkbox[4]
|
|
80
|
+
text[5].visible = checkbox[4].checked
|
|
81
|
+
|
|
82
|
+
def on_input_3_enter(): # Enter trong input[3]
|
|
83
|
+
alert("Bạn vừa gõ: " + input[3].text)
|
|
84
|
+
|
|
85
|
+
def on_text_5_change(): # gõ chữ trong text[5]
|
|
86
|
+
pass
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Quy ước tên hàm: `on_<loại>_<id>_<sự kiện>`
|
|
90
|
+
(`click` / `toggle` / `enter` / `change`). Studio tự sinh sườn hàm khi lưu.
|
|
91
|
+
|
|
92
|
+
Kiểu **decorator** mạnh hơn (cũng viết trong file trigger):
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
@on_click(button[2])
|
|
96
|
+
def xu_ly(): ...
|
|
97
|
+
|
|
98
|
+
@on_change(input[3]) # gõ bất kỳ chữ nào
|
|
99
|
+
def khi_go(): ...
|
|
100
|
+
|
|
101
|
+
@when(lambda: checkbox[4].checked and input[3].text == "admin")
|
|
102
|
+
def khi_du(): ... # điều kiện SAI → ĐÚNG mới chạy
|
|
103
|
+
|
|
104
|
+
@every(1000) # lặp mỗi giây
|
|
105
|
+
def dong_ho(): ...
|
|
106
|
+
|
|
107
|
+
@on_init # = on_start
|
|
108
|
+
def khoi_dong(): ...
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## 4. Chạy thật
|
|
112
|
+
|
|
113
|
+
Đổi 1 dòng trong `myapp.py`:
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
import flexgui
|
|
117
|
+
|
|
118
|
+
flexgui.run(__file__) # nạp myapp.flexgui.json + myapp.triggers.py
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Hoặc dùng cờ dòng lệnh quen thuộc: `python myapp.py --design`.
|
|
122
|
+
|
|
123
|
+
## 5. Thuộc tính & lệnh điều khiển widget
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
from flexgui import label, button, input, checkbox, text
|
|
127
|
+
|
|
128
|
+
label[1].text = "Số đếm: 5" # đọc/ghi trực tiếp
|
|
129
|
+
label[1].set_text("...") # tương đương
|
|
130
|
+
label[1].get_text()
|
|
131
|
+
label[1].x = 200 # tọa độ pixel (đọc/ghi)
|
|
132
|
+
label[1].color = "red" # màu chữ
|
|
133
|
+
label[1].bg = "#FFF3B0" # màu nền
|
|
134
|
+
label[1].font_size = 14
|
|
135
|
+
label[1].visible = False # tàng hình / hiện lại
|
|
136
|
+
label[1].enabled = False # khoá / mở
|
|
137
|
+
label[1].place(120, 80) # đặt lại vị trí tuyệt đối
|
|
138
|
+
label[1].move(10, 0) # dịch tương đối
|
|
139
|
+
label[1].resize(220, 30) # cỡ pixel WYSIWYG
|
|
140
|
+
label[1].refresh() # vẽ lại mọi thuộc tính đã lưu
|
|
141
|
+
label[1].show() / .hide() / .focus()
|
|
142
|
+
|
|
143
|
+
checkbox[4].checked = True # (chỉ Checkbox)
|
|
144
|
+
checkbox[4].toggle()
|
|
145
|
+
button[2].command = ham_xu_ly # gán lệnh bằng code
|
|
146
|
+
|
|
147
|
+
# Lệnh app — gọi thẳng trong trigger
|
|
148
|
+
refresh() · set_title("...") · set_size(1024, 640) · set_bg("black")
|
|
149
|
+
alert("...") · confirm("...?") → True/False · prompt("Tên?") → str/None
|
|
150
|
+
close_app()
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Widget bị xóa thì `input[3]` trả **widget rỗng an toàn** — code cũ không
|
|
154
|
+
bao giờ văng lỗi. ID **tái sử dụng**: xóa `input[3]` rồi thêm widget mới
|
|
155
|
+
thì widget mới nhận lại đúng ID `[3]`.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Đóng gói & chia sẻ
|
|
160
|
+
|
|
161
|
+
- **Build .exe** (nút 📦 trong Studio): PyInstaller tự động — file nằm
|
|
162
|
+
trong `flexgui_build/dist/`.
|
|
163
|
+
- **Xuất .py** (nút ▲): 1 file duy nhất nhúng thiết kế + trigger — chạy
|
|
164
|
+
bằng `python ten_file.py` (cần `pip install flexgui`).
|
|
165
|
+
|
|
166
|
+
## Cấu trúc package
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
flexgui/
|
|
170
|
+
├── __init__.py # API công khai: App, 5 widget, run/setup/design...
|
|
171
|
+
├── mode.py # design.mode = True
|
|
172
|
+
├── registry.py # label[1] / button[2] ... + widget rỗng an toàn
|
|
173
|
+
├── widgets.py # Label/Button/Input/Checkbox/Text (pixel WYSIWYG)
|
|
174
|
+
├── triggers.py # engine trigger + decorator + lệnh app
|
|
175
|
+
├── app.py # cửa sổ App + ID tái sử dụng
|
|
176
|
+
├── runtime.py # run() / setup() / run_embedded()
|
|
177
|
+
├── editor.py # mini VS Code (tô màu Python, IME tiếng Việt an toàn)
|
|
178
|
+
├── designer.py # FlexGUI Studio (canvas Figma-style)
|
|
179
|
+
└── builder.py # xuất file đơn + PyInstaller
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Yêu cầu
|
|
183
|
+
|
|
184
|
+
- Python 3.8+ (chỉ dùng thư viện chuẩn — **không cần cài thêm gì**)
|
|
185
|
+
- Build `.exe` cần `pip install pyinstaller` (Studio tự cài nếu thiếu)
|
|
186
|
+
|
|
187
|
+
## Đăng package lên PyPI (cho người phát hành)
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
pip install --upgrade build twine
|
|
191
|
+
|
|
192
|
+
# 1. build sdist + wheel (ra thư mục dist/)
|
|
193
|
+
python -m build
|
|
194
|
+
|
|
195
|
+
# 2. đăng (cần tài khoản PyPI + API token tại pypi.org)
|
|
196
|
+
twine upload dist/*
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Sau đó mọi người cài chỉ với `pip install flexgui`.
|
|
200
|
+
*Lưu ý: nếu tên `flexgui` đã bị ai chiếm trên PyPI, đổi `name` trong
|
|
201
|
+
`pyproject.toml` (ví dụ `flexgui-vn`) rồi build lại.*
|
|
202
|
+
|
|
203
|
+
## License
|
|
204
|
+
|
|
205
|
+
MIT
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
FlexGUI — thư viện GUI Python kéo-thả-thiết-kế trên nền tkinter.
|
|
4
|
+
|
|
5
|
+
pip install flexgui
|
|
6
|
+
|
|
7
|
+
ĐỒNG GÓI 2 PHẦN TRONG 1 THƯ VIỆN:
|
|
8
|
+
|
|
9
|
+
(A) THƯ VIỆN RUNTIME — cú pháp gọn, định vị tuyệt đối bằng place(x, y):
|
|
10
|
+
|
|
11
|
+
import flexgui
|
|
12
|
+
from flexgui import App, Label, Button, Input, Checkbox, Text
|
|
13
|
+
|
|
14
|
+
app = App("Ứng dụng của tôi", 860, 560)
|
|
15
|
+
Label("Xin chào!", 40, 30)
|
|
16
|
+
Button("Bấm tôi", 40, 80)
|
|
17
|
+
Input(40, 130, width=26)
|
|
18
|
+
Checkbox("Đồng ý", 40, 180)
|
|
19
|
+
Text(40, 230, width=42, height=7)
|
|
20
|
+
app.run()
|
|
21
|
+
|
|
22
|
+
(B) CHẾ ĐỘ THIẾT KẾ (FlexGUI Studio) — mở bằng MỘT trong các cách:
|
|
23
|
+
|
|
24
|
+
import flexgui
|
|
25
|
+
flexgui.setup() # cách 1 — mở Studio ngay
|
|
26
|
+
|
|
27
|
+
from flexgui import design # cách 2 — tương đương
|
|
28
|
+
design.mode = True
|
|
29
|
+
|
|
30
|
+
python myapp.py --design # cách 3 — cờ dòng lệnh
|
|
31
|
+
|
|
32
|
+
→ Chạy file ở design mode: Studio tự tạo GIAO DIỆN TRỐNG (hoặc nạp
|
|
33
|
+
myapp.flexgui.json đã lưu). Kéo thả thành phần, chỉnh thuộc tính,
|
|
34
|
+
viết trigger bằng mini VS Code ngay trong Studio HOẶC mở file
|
|
35
|
+
myapp.triggers.py bằng VS Code thật — cả hai sửa CÙNG một file.
|
|
36
|
+
|
|
37
|
+
→ Chạy thật: đổi setup() thành flexgui.run(__file__) rồi chạy lại.
|
|
38
|
+
|
|
39
|
+
Truy cập widget theo ID (tự động, tái sử dụng ID khi xóa):
|
|
40
|
+
from flexgui import label, button, input, checkbox, text
|
|
41
|
+
label[1].set_text("Xin chào!") # đọc/ghi thuộc tính trực tiếp
|
|
42
|
+
|
|
43
|
+
Chi tiết: README.md đi kèm package.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
from .mode import design
|
|
47
|
+
from .registry import label, button, input, checkbox, text
|
|
48
|
+
from .triggers import (
|
|
49
|
+
on_click, on_change, on_enter, when, every, on_init,
|
|
50
|
+
refresh, set_title, set_size, set_bg, alert, confirm, prompt, close_app,
|
|
51
|
+
)
|
|
52
|
+
from .widgets import Label, Button, Input, Checkbox, Text
|
|
53
|
+
from .app import App
|
|
54
|
+
from .runtime import run, setup, run_embedded
|
|
55
|
+
|
|
56
|
+
__version__ = "1.0.0"
|
|
57
|
+
__author__ = "FlexGUI Team"
|
|
58
|
+
|
|
59
|
+
__all__ = [
|
|
60
|
+
# cửa sổ & widget
|
|
61
|
+
"App", "Label", "Button", "Input", "Checkbox", "Text",
|
|
62
|
+
# vùng tên theo ID
|
|
63
|
+
"label", "button", "input", "checkbox", "text",
|
|
64
|
+
# chế độ thiết kế & chạy
|
|
65
|
+
"design", "setup", "run", "run_embedded",
|
|
66
|
+
# decorator trigger
|
|
67
|
+
"on_click", "on_change", "on_enter", "when", "every", "on_init",
|
|
68
|
+
# lệnh app
|
|
69
|
+
"refresh", "set_title", "set_size", "set_bg",
|
|
70
|
+
"alert", "confirm", "prompt", "close_app",
|
|
71
|
+
]
|