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 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
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,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.37.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ fluxpy