fluxpy-ui 2.0.5__py3-none-any.whl
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.
- fluxpy/__init__.py +32 -0
- fluxpy/assets/flux_logo.ico +0 -0
- fluxpy/assets/flux_logo.png +0 -0
- fluxpy/core/__init__.py +0 -0
- fluxpy/core/app.py +100 -0
- fluxpy/core/orm.py +41 -0
- fluxpy/engine/__init__.py +0 -0
- fluxpy/engine/core.py +62 -0
- fluxpy/mobile/__init__.py +0 -0
- fluxpy/widgets/__init__.py +0 -0
- fluxpy/widgets/base.py +187 -0
- fluxpy_ui-2.0.5.dist-info/METADATA +78 -0
- fluxpy_ui-2.0.5.dist-info/RECORD +15 -0
- fluxpy_ui-2.0.5.dist-info/WHEEL +5 -0
- fluxpy_ui-2.0.5.dist-info/top_level.txt +1 -0
fluxpy/__init__.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from .core.app import FluxApp, Page
|
|
2
|
+
from .widgets.base import Text, Container, ElevatedButton, Row, Column, TextField, Icon, Checkbox
|
|
3
|
+
from .engine.core import FluxEngine, GameEntity
|
|
4
|
+
from .core.orm import Model
|
|
5
|
+
|
|
6
|
+
__version__ = "2.0.5"
|
|
7
|
+
|
|
8
|
+
def help():
|
|
9
|
+
print(f"\n[FluxPy-UI v{__version__} - Enterprise Framework]")
|
|
10
|
+
print("-" * 50)
|
|
11
|
+
print("Core:")
|
|
12
|
+
print(" - FluxApp: Main application entry point")
|
|
13
|
+
print(" - Page: Window controller (title, icon, bgcolor, frameless, show_message)")
|
|
14
|
+
print(" - Model: Simple ORM for database management")
|
|
15
|
+
print("\nLayouts:")
|
|
16
|
+
print(" - Row: Horizontal layout container")
|
|
17
|
+
print(" - Column: Vertical layout container")
|
|
18
|
+
print(" - Container: Styled box model")
|
|
19
|
+
print("\nWidgets:")
|
|
20
|
+
print(" - Text: Customizable text (size, weight, color)")
|
|
21
|
+
print(" - TextField: User input (placeholder, password, on_change)")
|
|
22
|
+
print(" - ElevatedButton: Modern button with icon support")
|
|
23
|
+
print(" - Icon: Display icons")
|
|
24
|
+
print(" - Checkbox: Boolean selection")
|
|
25
|
+
print("\nGame Engine:")
|
|
26
|
+
print(" - FluxEngine: 2D Graphics engine")
|
|
27
|
+
print(" - GameEntity: Game object with physics properties")
|
|
28
|
+
print("\nWindow Customization:")
|
|
29
|
+
print(" page.icon = 'path/to/icon.png'")
|
|
30
|
+
print(" page.show_minimize = False")
|
|
31
|
+
print(" page.frameless = True")
|
|
32
|
+
print("-" * 50)
|
|
Binary file
|
|
Binary file
|
fluxpy/core/__init__.py
ADDED
|
File without changes
|
fluxpy/core/app.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import os
|
|
3
|
+
import traceback
|
|
4
|
+
from PyQt6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QScrollArea, QMessageBox
|
|
5
|
+
from PyQt6.QtCore import Qt, pyqtSignal, QObject
|
|
6
|
+
from PyQt6.QtGui import QIcon, QFont
|
|
7
|
+
|
|
8
|
+
class FluxDebugger:
|
|
9
|
+
@staticmethod
|
|
10
|
+
def handle_exception(exc_type, exc_value, exc_traceback):
|
|
11
|
+
tb = traceback.extract_tb(exc_traceback)
|
|
12
|
+
last_call = tb[-1]
|
|
13
|
+
print(f"\n[FluxPy Smart Debugger]")
|
|
14
|
+
print(f"File: {last_call.filename}")
|
|
15
|
+
print(f"Line: {last_call.lineno}")
|
|
16
|
+
print(f"Error Type: {exc_type.__name__}")
|
|
17
|
+
print(f"Message: {exc_value}")
|
|
18
|
+
print("-" * 30)
|
|
19
|
+
|
|
20
|
+
sys.excepthook = FluxDebugger.handle_exception
|
|
21
|
+
|
|
22
|
+
class Page(QObject):
|
|
23
|
+
update_signal = pyqtSignal()
|
|
24
|
+
|
|
25
|
+
def __init__(self, window):
|
|
26
|
+
super().__init__()
|
|
27
|
+
self.window = window
|
|
28
|
+
self.title = "FluxPy App"
|
|
29
|
+
self.bgcolor = "#ffffff"
|
|
30
|
+
self.padding = 20
|
|
31
|
+
self.controls = []
|
|
32
|
+
|
|
33
|
+
# Default Logo
|
|
34
|
+
assets_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "assets")
|
|
35
|
+
self.icon = os.path.join(assets_dir, "flux_logo.png")
|
|
36
|
+
|
|
37
|
+
self.show_minimize = True
|
|
38
|
+
self.show_maximize = True
|
|
39
|
+
self.show_close = True
|
|
40
|
+
self.frameless = False
|
|
41
|
+
|
|
42
|
+
self.central_widget = QWidget()
|
|
43
|
+
self.layout = QVBoxLayout(self.central_widget)
|
|
44
|
+
self.layout.setAlignment(Qt.AlignmentFlag.AlignTop)
|
|
45
|
+
|
|
46
|
+
self.scroll = QScrollArea()
|
|
47
|
+
self.scroll.setWidgetResizable(True)
|
|
48
|
+
self.scroll.setWidget(self.central_widget)
|
|
49
|
+
self.scroll.setFrameShape(QScrollArea.Shape.NoFrame)
|
|
50
|
+
|
|
51
|
+
self.window.setCentralWidget(self.scroll)
|
|
52
|
+
|
|
53
|
+
def add(self, *args):
|
|
54
|
+
for control in args:
|
|
55
|
+
self.controls.append(control)
|
|
56
|
+
qt_widget = control.build()
|
|
57
|
+
self.layout.addWidget(qt_widget)
|
|
58
|
+
self.update()
|
|
59
|
+
|
|
60
|
+
def clean(self):
|
|
61
|
+
self.controls = []
|
|
62
|
+
for i in reversed(range(self.layout.count())):
|
|
63
|
+
widget = self.layout.itemAt(i).widget()
|
|
64
|
+
if widget:
|
|
65
|
+
widget.setParent(None)
|
|
66
|
+
|
|
67
|
+
def update(self):
|
|
68
|
+
self.window.setWindowTitle(self.title)
|
|
69
|
+
self.central_widget.setStyleSheet(f"background-color: {self.bgcolor};")
|
|
70
|
+
self.layout.setContentsMargins(self.padding, self.padding, self.padding, self.padding)
|
|
71
|
+
|
|
72
|
+
if os.path.exists(self.icon):
|
|
73
|
+
self.window.setWindowIcon(QIcon(self.icon))
|
|
74
|
+
|
|
75
|
+
self.update_signal.emit()
|
|
76
|
+
|
|
77
|
+
def show_message(self, title, message, type="info"):
|
|
78
|
+
msg = QMessageBox(self.window)
|
|
79
|
+
msg.setWindowTitle(title)
|
|
80
|
+
msg.setText(message)
|
|
81
|
+
if type == "success": msg.setIcon(QMessageBox.Icon.Information)
|
|
82
|
+
elif type == "error": msg.setIcon(QMessageBox.Icon.Critical)
|
|
83
|
+
elif type == "warning": msg.setIcon(QMessageBox.Icon.Warning)
|
|
84
|
+
else: msg.setIcon(QMessageBox.Icon.Information)
|
|
85
|
+
msg.exec()
|
|
86
|
+
|
|
87
|
+
class FluxApp:
|
|
88
|
+
def __init__(self):
|
|
89
|
+
self.app = QApplication(sys.argv)
|
|
90
|
+
default_font = QFont("Segoe UI", 11)
|
|
91
|
+
self.app.setFont(default_font)
|
|
92
|
+
|
|
93
|
+
self.window = QMainWindow()
|
|
94
|
+
self.window.resize(1000, 700)
|
|
95
|
+
self.page = Page(self.window)
|
|
96
|
+
|
|
97
|
+
def run(self, target):
|
|
98
|
+
target(self.page)
|
|
99
|
+
self.window.show()
|
|
100
|
+
sys.exit(self.app.exec())
|
fluxpy/core/orm.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import sqlite3
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
class Model:
|
|
5
|
+
database = "flux_db.sqlite"
|
|
6
|
+
table_name = ""
|
|
7
|
+
|
|
8
|
+
def __init__(self, **kwargs):
|
|
9
|
+
for key, value in kwargs.items():
|
|
10
|
+
setattr(self, key, value)
|
|
11
|
+
|
|
12
|
+
@classmethod
|
|
13
|
+
def _get_conn(cls):
|
|
14
|
+
return sqlite3.connect(cls.database)
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def create_table(cls, **fields):
|
|
18
|
+
cls.table_name = cls.__name__.lower()
|
|
19
|
+
columns = ", ".join([f"{name} {type}" for name, type in fields.items()])
|
|
20
|
+
query = f"CREATE TABLE IF NOT EXISTS {cls.table_name} (id INTEGER PRIMARY KEY AUTOINCREMENT, {columns})"
|
|
21
|
+
with cls._get_conn() as conn:
|
|
22
|
+
conn.execute(query)
|
|
23
|
+
|
|
24
|
+
def save(self):
|
|
25
|
+
fields = {k: v for k, v in self.__dict__.items() if not k.startswith('_')}
|
|
26
|
+
columns = ", ".join(fields.keys())
|
|
27
|
+
placeholders = ", ".join(["?" for _ in fields])
|
|
28
|
+
query = f"INSERT INTO {self.table_name} ({columns}) VALUES ({placeholders})"
|
|
29
|
+
with self._get_conn() as conn:
|
|
30
|
+
conn.execute(query, list(fields.values()))
|
|
31
|
+
|
|
32
|
+
@classmethod
|
|
33
|
+
def all(cls):
|
|
34
|
+
cls.table_name = cls.__name__.lower()
|
|
35
|
+
query = f"SELECT * FROM {cls.table_name}"
|
|
36
|
+
with cls._get_conn() as conn:
|
|
37
|
+
cursor = conn.execute(query)
|
|
38
|
+
rows = cursor.fetchall()
|
|
39
|
+
# Get column names
|
|
40
|
+
cols = [description[0] for description in cursor.description]
|
|
41
|
+
return [cls(**dict(zip(cols, row))) for row in rows]
|
|
File without changes
|
fluxpy/engine/core.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from PyQt6.QtWidgets import QGraphicsView, QGraphicsScene, QGraphicsRectItem, QGraphicsEllipseItem
|
|
2
|
+
from PyQt6.QtCore import QTimer, Qt
|
|
3
|
+
from PyQt6.QtGui import QBrush, QColor
|
|
4
|
+
|
|
5
|
+
class GameEntity:
|
|
6
|
+
def __init__(self, x, y, width, height, color="red", shape="rect"):
|
|
7
|
+
self.x = x
|
|
8
|
+
self.y = y
|
|
9
|
+
self.width = width
|
|
10
|
+
self.height = height
|
|
11
|
+
self.color = color
|
|
12
|
+
self.shape = shape
|
|
13
|
+
self.item = None
|
|
14
|
+
self.vx = 0
|
|
15
|
+
self.vy = 0
|
|
16
|
+
|
|
17
|
+
def build(self):
|
|
18
|
+
if self.shape == "rect":
|
|
19
|
+
self.item = QGraphicsRectItem(0, 0, self.width, self.height)
|
|
20
|
+
else:
|
|
21
|
+
self.item = QGraphicsEllipseItem(0, 0, self.width, self.height)
|
|
22
|
+
self.item.setBrush(QBrush(QColor(self.color)))
|
|
23
|
+
self.item.setPos(self.x, self.y)
|
|
24
|
+
return self.item
|
|
25
|
+
|
|
26
|
+
def update(self):
|
|
27
|
+
self.x += self.vx
|
|
28
|
+
self.y += self.vy
|
|
29
|
+
if self.item:
|
|
30
|
+
self.item.setPos(self.x, self.y)
|
|
31
|
+
|
|
32
|
+
class FluxEngine:
|
|
33
|
+
def __init__(self, width=800, height=600, bgcolor="#000000"):
|
|
34
|
+
self.width = width
|
|
35
|
+
self.height = height
|
|
36
|
+
self.bgcolor = bgcolor
|
|
37
|
+
self.entities = []
|
|
38
|
+
|
|
39
|
+
self.scene = QGraphicsScene(0, 0, width, height)
|
|
40
|
+
self.scene.setBackgroundBrush(QBrush(QColor(bgcolor)))
|
|
41
|
+
|
|
42
|
+
self.view = QGraphicsView(self.scene)
|
|
43
|
+
self.view.setRenderHint(Qt.RenderHint.Antialiasing)
|
|
44
|
+
self.view.setFixedSize(width, height)
|
|
45
|
+
|
|
46
|
+
self.timer = QTimer()
|
|
47
|
+
self.timer.timeout.connect(self.game_loop)
|
|
48
|
+
self.fps = 60
|
|
49
|
+
|
|
50
|
+
def add_entity(self, entity):
|
|
51
|
+
self.entities.append(entity)
|
|
52
|
+
self.scene.addItem(entity.build())
|
|
53
|
+
|
|
54
|
+
def start(self):
|
|
55
|
+
self.timer.start(1000 // self.fps)
|
|
56
|
+
|
|
57
|
+
def game_loop(self):
|
|
58
|
+
for entity in self.entities:
|
|
59
|
+
entity.update()
|
|
60
|
+
|
|
61
|
+
def build(self):
|
|
62
|
+
return self.view
|
|
File without changes
|
|
File without changes
|
fluxpy/widgets/base.py
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
from PyQt6.QtWidgets import (QPushButton, QLabel, QFrame, QVBoxLayout, QHBoxLayout,
|
|
2
|
+
QLineEdit, QCheckBox, QRadioButton, QComboBox, QSlider,
|
|
3
|
+
QProgressBar, QScrollArea, QStackedWidget)
|
|
4
|
+
from PyQt6.QtCore import Qt, QSize
|
|
5
|
+
from PyQt6.QtGui import QFont, QColor, QIcon
|
|
6
|
+
|
|
7
|
+
class BaseWidget:
|
|
8
|
+
def __init__(self, **kwargs):
|
|
9
|
+
self.width = kwargs.get("width")
|
|
10
|
+
self.height = kwargs.get("height")
|
|
11
|
+
self.padding = kwargs.get("padding", 0)
|
|
12
|
+
self.margin = kwargs.get("margin", 0)
|
|
13
|
+
self.bgcolor = kwargs.get("bgcolor", "transparent")
|
|
14
|
+
self.color = kwargs.get("color", "black")
|
|
15
|
+
self.border_radius = kwargs.get("border_radius", 0)
|
|
16
|
+
self.border_color = kwargs.get("border_color", "transparent")
|
|
17
|
+
self.border_width = kwargs.get("border_width", 0)
|
|
18
|
+
self.font_family = kwargs.get("font_family", "Segoe UI")
|
|
19
|
+
self.size = kwargs.get("size", 12)
|
|
20
|
+
self.weight = kwargs.get("weight", "normal")
|
|
21
|
+
self.widget = None
|
|
22
|
+
|
|
23
|
+
def apply_styles(self):
|
|
24
|
+
style = f"""
|
|
25
|
+
background-color: {self.bgcolor};
|
|
26
|
+
color: {self.color};
|
|
27
|
+
border-radius: {self.border_radius}px;
|
|
28
|
+
border: {self.border_width}px solid {self.border_color};
|
|
29
|
+
padding: {self.padding}px;
|
|
30
|
+
margin: {self.margin}px;
|
|
31
|
+
"""
|
|
32
|
+
if self.widget:
|
|
33
|
+
self.widget.setStyleSheet(style)
|
|
34
|
+
if self.width: self.widget.setFixedWidth(self.width)
|
|
35
|
+
if self.height: self.widget.setFixedHeight(self.height)
|
|
36
|
+
|
|
37
|
+
font = QFont(self.font_family, self.size)
|
|
38
|
+
if self.weight == "bold": font.setBold(True)
|
|
39
|
+
self.widget.setFont(font)
|
|
40
|
+
|
|
41
|
+
class Text(BaseWidget):
|
|
42
|
+
def __init__(self, value="", **kwargs):
|
|
43
|
+
super().__init__(**kwargs)
|
|
44
|
+
self.value = value
|
|
45
|
+
if "size" not in kwargs: self.size = 14 # Larger default font
|
|
46
|
+
|
|
47
|
+
def build(self):
|
|
48
|
+
self.widget = QLabel(self.value)
|
|
49
|
+
self.apply_styles()
|
|
50
|
+
return self.widget
|
|
51
|
+
|
|
52
|
+
class TextField(BaseWidget):
|
|
53
|
+
def __init__(self, value="", placeholder="", on_change=None, password=False, **kwargs):
|
|
54
|
+
super().__init__(**kwargs)
|
|
55
|
+
self.value = value
|
|
56
|
+
self.placeholder = placeholder
|
|
57
|
+
self.on_change = on_change
|
|
58
|
+
self.password = password
|
|
59
|
+
if "bgcolor" not in kwargs: self.bgcolor = "white"
|
|
60
|
+
if "padding" not in kwargs: self.padding = 8
|
|
61
|
+
if "border_radius" not in kwargs: self.border_radius = 5
|
|
62
|
+
if "border_width" not in kwargs: self.border_width = 1
|
|
63
|
+
if "border_color" not in kwargs: self.border_color = "#cccccc"
|
|
64
|
+
|
|
65
|
+
def build(self):
|
|
66
|
+
self.widget = QLineEdit()
|
|
67
|
+
self.widget.setText(self.value)
|
|
68
|
+
self.widget.setPlaceholderText(self.placeholder)
|
|
69
|
+
if self.password:
|
|
70
|
+
self.widget.setEchoMode(QLineEdit.EchoMode.Password)
|
|
71
|
+
if self.on_change:
|
|
72
|
+
self.widget.textChanged.connect(self._handle_change)
|
|
73
|
+
self.apply_styles()
|
|
74
|
+
return self.widget
|
|
75
|
+
|
|
76
|
+
def _handle_change(self, text):
|
|
77
|
+
self.value = text
|
|
78
|
+
if self.on_change:
|
|
79
|
+
self.on_change(text)
|
|
80
|
+
|
|
81
|
+
class Row(BaseWidget):
|
|
82
|
+
def __init__(self, controls=None, spacing=10, alignment="start", **kwargs):
|
|
83
|
+
super().__init__(**kwargs)
|
|
84
|
+
self.controls = controls or []
|
|
85
|
+
self.spacing = spacing
|
|
86
|
+
self.alignment = alignment
|
|
87
|
+
|
|
88
|
+
def build(self):
|
|
89
|
+
self.widget = QFrame()
|
|
90
|
+
layout = QHBoxLayout(self.widget)
|
|
91
|
+
layout.setSpacing(self.spacing)
|
|
92
|
+
layout.setContentsMargins(0, 0, 0, 0)
|
|
93
|
+
|
|
94
|
+
if self.alignment == "center": layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
95
|
+
elif self.alignment == "end": layout.setAlignment(Qt.AlignmentFlag.AlignRight)
|
|
96
|
+
else: layout.setAlignment(Qt.AlignmentFlag.AlignLeft)
|
|
97
|
+
|
|
98
|
+
for c in self.controls:
|
|
99
|
+
layout.addWidget(c.build())
|
|
100
|
+
self.apply_styles()
|
|
101
|
+
return self.widget
|
|
102
|
+
|
|
103
|
+
class Column(BaseWidget):
|
|
104
|
+
def __init__(self, controls=None, spacing=10, alignment="start", **kwargs):
|
|
105
|
+
super().__init__(**kwargs)
|
|
106
|
+
self.controls = controls or []
|
|
107
|
+
self.spacing = spacing
|
|
108
|
+
self.alignment = alignment
|
|
109
|
+
|
|
110
|
+
def build(self):
|
|
111
|
+
self.widget = QFrame()
|
|
112
|
+
layout = QVBoxLayout(self.widget)
|
|
113
|
+
layout.setSpacing(self.spacing)
|
|
114
|
+
layout.setContentsMargins(0, 0, 0, 0)
|
|
115
|
+
|
|
116
|
+
if self.alignment == "center": layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
117
|
+
elif self.alignment == "end": layout.setAlignment(Qt.AlignmentFlag.AlignBottom)
|
|
118
|
+
else: layout.setAlignment(Qt.AlignmentFlag.AlignTop)
|
|
119
|
+
|
|
120
|
+
for c in self.controls:
|
|
121
|
+
layout.addWidget(c.build())
|
|
122
|
+
self.apply_styles()
|
|
123
|
+
return self.widget
|
|
124
|
+
|
|
125
|
+
class Container(BaseWidget):
|
|
126
|
+
def __init__(self, content=None, **kwargs):
|
|
127
|
+
super().__init__(**kwargs)
|
|
128
|
+
self.content = content
|
|
129
|
+
|
|
130
|
+
def build(self):
|
|
131
|
+
self.widget = QFrame()
|
|
132
|
+
layout = QVBoxLayout(self.widget)
|
|
133
|
+
layout.setContentsMargins(0, 0, 0, 0)
|
|
134
|
+
if self.content:
|
|
135
|
+
layout.addWidget(self.content.build())
|
|
136
|
+
self.apply_styles()
|
|
137
|
+
return self.widget
|
|
138
|
+
|
|
139
|
+
class ElevatedButton(BaseWidget):
|
|
140
|
+
def __init__(self, text="", on_click=None, icon=None, **kwargs):
|
|
141
|
+
super().__init__(**kwargs)
|
|
142
|
+
self.text = text
|
|
143
|
+
self.on_click = on_click
|
|
144
|
+
self.icon = icon
|
|
145
|
+
if "bgcolor" not in kwargs: self.bgcolor = "#2196F3"
|
|
146
|
+
if "color" not in kwargs: self.color = "white"
|
|
147
|
+
if "padding" not in kwargs: self.padding = 12
|
|
148
|
+
if "border_radius" not in kwargs: self.border_radius = 8
|
|
149
|
+
|
|
150
|
+
def build(self):
|
|
151
|
+
self.widget = QPushButton(self.text)
|
|
152
|
+
if self.icon:
|
|
153
|
+
self.widget.setIcon(QIcon(self.icon))
|
|
154
|
+
if self.on_click:
|
|
155
|
+
self.widget.clicked.connect(self.on_click)
|
|
156
|
+
self.apply_styles()
|
|
157
|
+
return self.widget
|
|
158
|
+
|
|
159
|
+
class Icon(BaseWidget):
|
|
160
|
+
def __init__(self, name, size=24, color="black", **kwargs):
|
|
161
|
+
super().__init__(**kwargs)
|
|
162
|
+
self.name = name # Path to icon or name
|
|
163
|
+
self.size = size
|
|
164
|
+
self.color = color
|
|
165
|
+
|
|
166
|
+
def build(self):
|
|
167
|
+
self.widget = QLabel()
|
|
168
|
+
icon = QIcon(self.name)
|
|
169
|
+
pixmap = icon.pixmap(QSize(self.size, self.size))
|
|
170
|
+
self.widget.setPixmap(pixmap)
|
|
171
|
+
self.apply_styles()
|
|
172
|
+
return self.widget
|
|
173
|
+
|
|
174
|
+
class Checkbox(BaseWidget):
|
|
175
|
+
def __init__(self, label="", value=False, on_change=None, **kwargs):
|
|
176
|
+
super().__init__(**kwargs)
|
|
177
|
+
self.label = label
|
|
178
|
+
self.value = value
|
|
179
|
+
self.on_change = on_change
|
|
180
|
+
|
|
181
|
+
def build(self):
|
|
182
|
+
self.widget = QCheckBox(self.label)
|
|
183
|
+
self.widget.setChecked(self.value)
|
|
184
|
+
if self.on_change:
|
|
185
|
+
self.widget.stateChanged.connect(lambda state: self.on_change(state == 2))
|
|
186
|
+
self.apply_styles()
|
|
187
|
+
return self.widget
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: fluxpy-ui
|
|
3
|
+
Version: 2.0.5
|
|
4
|
+
Summary: An enterprise-grade modern desktop UI and Game framework for Python
|
|
5
|
+
Home-page: UNKNOWN
|
|
6
|
+
Author: FluxPy Team
|
|
7
|
+
License: UNKNOWN
|
|
8
|
+
Platform: UNKNOWN
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.7
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
Requires-Dist: PyQt6
|
|
15
|
+
|
|
16
|
+
# FluxPy 🚀 (Flet-Style Edition)
|
|
17
|
+
|
|
18
|
+
**FluxPy** is a massive, professional Python library for building stunning desktop applications with a declarative syntax inspired by **Flet**. It offers extreme customization for every single pixel.
|
|
19
|
+
|
|
20
|
+
## Key Features
|
|
21
|
+
- **Declarative UI:** Write code that looks like the UI structure.
|
|
22
|
+
- **Extreme Customization:** Control fonts, colors, gradients, borders, and shadows for every element.
|
|
23
|
+
- **Smart Debugger:** Instant error reporting with file and line precision.
|
|
24
|
+
- **High Performance:** Built on PyQt6 for native speed.
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
```bash
|
|
28
|
+
pip install fluxpy
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick Start (Flet-Style)
|
|
32
|
+
```python
|
|
33
|
+
import fluxpy as fx
|
|
34
|
+
|
|
35
|
+
def main(page: fx.Page):
|
|
36
|
+
page.title = "FluxPy Modern App"
|
|
37
|
+
page.bgcolor = "#f0f2f5"
|
|
38
|
+
|
|
39
|
+
# Highly customizable text
|
|
40
|
+
title = fx.Text(
|
|
41
|
+
"Welcome to FluxPy",
|
|
42
|
+
size=30,
|
|
43
|
+
weight="bold",
|
|
44
|
+
color="#1a73e8",
|
|
45
|
+
font_family="Verdana"
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
# Container with padding and border radius
|
|
49
|
+
card = fx.Container(
|
|
50
|
+
content=fx.Text("This is a customizable card", color="white"),
|
|
51
|
+
bgcolor="#34495e",
|
|
52
|
+
padding=20,
|
|
53
|
+
border_radius=15,
|
|
54
|
+
width=300
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def on_btn_click():
|
|
58
|
+
print("Button Clicked!")
|
|
59
|
+
title.value = "Button Clicked!"
|
|
60
|
+
page.update()
|
|
61
|
+
|
|
62
|
+
btn = fx.ElevatedButton("Click Me", on_click=on_btn_click, bgcolor="#e74c3c")
|
|
63
|
+
|
|
64
|
+
page.add(title, card, btn)
|
|
65
|
+
|
|
66
|
+
app = fx.FluxApp()
|
|
67
|
+
app.run(main)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Performance Tips
|
|
71
|
+
1. **Batch Updates:** Use `page.update()` only after making multiple changes.
|
|
72
|
+
2. **SVG Assets:** Use SVG for icons to maintain quality across DPI levels.
|
|
73
|
+
3. **Control Reuse:** Reuse complex containers instead of recreating them.
|
|
74
|
+
|
|
75
|
+
## Functions List
|
|
76
|
+
Run `fx.help()` in your script to see all available components.
|
|
77
|
+
|
|
78
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
fluxpy/__init__.py,sha256=zCUyyqNDeW__tRzvU-yNEs3AAS_l4kX5UOhy0m10Zjw,1355
|
|
2
|
+
fluxpy/assets/flux_logo.ico,sha256=gGCZo3EjudhN1gDLHwz-EISLSznD3m07lWuL8RY0c1U,16920
|
|
3
|
+
fluxpy/assets/flux_logo.png,sha256=ja_-NYxQ8en8zHIhBcYvXBxod3psJW35sv_DHxLqWlY,10752
|
|
4
|
+
fluxpy/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
fluxpy/core/app.py,sha256=ImgagTy7LwXeWBDcl_Uo9Vh2W0vPASuKdvoMGYuO3iY,3373
|
|
6
|
+
fluxpy/core/orm.py,sha256=mBPa7qYJwsYhRJgD4tQo3AMpqNVX5zWeFfMMa-4aXWY,1458
|
|
7
|
+
fluxpy/engine/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
fluxpy/engine/core.py,sha256=sufiq-GZLHD1Le5V54w4yJPqkdVXEVKaSjSd34nq-_w,1878
|
|
9
|
+
fluxpy/mobile/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
fluxpy/widgets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
+
fluxpy/widgets/base.py,sha256=pMogIFCaySUi_jvvnLYBT9jBQK8gmiDdLNnjoK2uakQ,6891
|
|
12
|
+
fluxpy_ui-2.0.5.dist-info/METADATA,sha256=XhVzHAl8yt5olsxANv4zabqJZrlw2wiQuWDMHB2wGzI,2241
|
|
13
|
+
fluxpy_ui-2.0.5.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
|
14
|
+
fluxpy_ui-2.0.5.dist-info/top_level.txt,sha256=cG9mHLaz8JNRVl0DoPG2nitIFhOQcrTZCVCiIQ1Q4ms,7
|
|
15
|
+
fluxpy_ui-2.0.5.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
fluxpy
|