Code With Python
Photo
## 🔹 Multi-Window Applications
### 1. Creating Secondary Windows
### 2. Window Communication
---
## 🔹 Model-View Architecture
### 1. QListView with StringListModel
### 2. Custom Table Model
---
## 🔹 Practical Example: Text Editor
---
## 🔹 Best Practices
1. Separate UI code from business logic
2. Use models for complex data views
3. Optimize performance for large datasets
4. Localize strings for internationalization
5. Document signals and public methods
---
### 📌 What's Next?
In Part 3, we'll cover:
➡️ Dialogs & Message Boxes
➡️ File System Operations
➡️ Drag & Drop
➡️ Threading with QThread
#PyQt5 #GUIPython #ProfessionalDevelopment 🚀
Practice Exercise:
1. Create a contacts app with tree view and detail form
2. Build a styled calculator with custom buttons
3. Implement a multi-window image viewer with thumbnails
### 1. Creating Secondary Windows
class SettingsWindow(QDialog):
def __init__(self):
super().__init__()
self.setWindowTitle("Settings")
layout = QVBoxLayout()
layout.addWidget(QLabel("Application Settings"))
self.setLayout(layout)
# In main window:
def show_settings(self):
settings = SettingsWindow()
settings.exec_() # Modal dialog
# OR settings.show() for non-modal
### 2. Window Communication
# Main window with signal
class MainWindow(QMainWindow):
settings_changed = pyqtSignal(dict)
def open_settings(self):
dialog = SettingsDialog(self) # Pass parent
if dialog.exec_():
self.settings_changed.emit(dialog.get_settings())
# Settings dialog
class SettingsDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
# ... setup UI ...
def get_settings(self):
return {"theme": self.theme_combo.currentText()}
---
## 🔹 Model-View Architecture
### 1. QListView with StringListModel
model = QStringListModel()
model.setStringList(["Item 1", "Item 2", "Item 3"])
list_view = QListView()
list_view.setModel(model)
# Add items
model.insertRow(model.rowCount())
model.setData(model.index(model.rowCount()-1), "New Item")
### 2. Custom Table Model
class CustomTableModel(QAbstractTableModel):
def __init__(self, data):
super().__init__()
self._data = data
def rowCount(self, parent=None):
return len(self._data)
def columnCount(self, parent=None):
return len(self._data[0]) if self._data else 0
def data(self, index, role=Qt.DisplayRole):
if role == Qt.DisplayRole:
return str(self._data[index.row()][index.column()])
return None
# Usage
data = [[1, "Alice"], [2, "Bob"], [3, "Charlie"]]
model = CustomTableModel(data)
table = QTableView()
table.setModel(model)
---
## 🔹 Practical Example: Text Editor
class TextEditor(QMainWindow):
def __init__(self):
super().__init__()
self.setup_ui()
self.setup_menu()
def setup_ui(self):
self.text_edit = QTextEdit()
self.setCentralWidget(self.text_edit)
# Status bar
self.statusBar().showMessage("Ready")
# Toolbar
toolbar = self.addToolBar("Tools")
save_act = QAction(QIcon("save.png"), "Save", self)
save_act.triggered.connect(self.save_file)
toolbar.addAction(save_act)
def setup_menu(self):
menubar = self.menuBar()
# File menu
file_menu = menubar.addMenu("File")
open_act = QAction("Open", self)
open_act.triggered.connect(self.open_file)
file_menu.addAction(open_act)
# Edit menu
edit_menu = menubar.addMenu("Edit")
edit_menu.addAction("Copy", self.text_edit.copy)
edit_menu.addAction("Paste", self.text_edit.paste)
def open_file(self):
path, _ = QFileDialog.getOpenFileName()
if path:
with open(path, 'r') as f:
self.text_edit.setText(f.read())
def save_file(self):
path, _ = QFileDialog.getSaveFileName()
if path:
with open(path, 'w') as f:
f.write(self.text_edit.toPlainText())
---
## 🔹 Best Practices
1. Separate UI code from business logic
2. Use models for complex data views
3. Optimize performance for large datasets
4. Localize strings for internationalization
5. Document signals and public methods
---
### 📌 What's Next?
In Part 3, we'll cover:
➡️ Dialogs & Message Boxes
➡️ File System Operations
➡️ Drag & Drop
➡️ Threading with QThread
#PyQt5 #GUIPython #ProfessionalDevelopment 🚀
Practice Exercise:
1. Create a contacts app with tree view and detail form
2. Build a styled calculator with custom buttons
3. Implement a multi-window image viewer with thumbnails
Code With Python
Photo
def show_error(self, message):
self.thread.quit()
QMessageBox.critical(self, "Error", message)
class FileWorker(QObject):
progress = pyqtSignal(int)
finished = pyqtSignal()
error = pyqtSignal(str)
def __init__(self):
super().__init__()
self.files = []
def set_files(self, files):
self.files = files
def process(self):
try:
total = len(self.files)
for i, file in enumerate(self.files):
# Simulate processing
time.sleep(0.5)
# Check for cancellation
if QThread.currentThread().isInterruptionRequested():
break
# Update progress
self.progress.emit(int((i + 1) / total * 100))
self.finished.emit()
except Exception as e:
self.error.emit(str(e))
---
## 🔹 Best Practices
1. Always clean up threads - Use
finished signals2. Never update UI from worker threads - Use signals
3. Validate file operations - Check permissions/existence
4. Handle drag-and-drop properly - Check MIME types
5. Make dialogs modal/non-modal appropriately -
exec_() vs show()---
### 📌 What's Next?
In Part 4, we'll cover:
➡️ Database Integration (SQLite, PostgreSQL)
➡️ Data Visualization (Charts, Graphs)
➡️ Model-View-Controller Pattern
➡️ Advanced Widget Customization
#PyQt5 #ProfessionalDevelopment #PythonGUI 🚀
Practice Exercise:
1. Build a thumbnail generator with progress reporting
2. Create a JSON config editor with file monitoring
3. Implement a thread-safe logging system for background tasks
❤4
Code With Python
Photo
# 📚 PyQt5 Tutorial - Part 4/6: Database Integration & Data Visualization
#PyQt5 #SQL #DataViz #MVC #ProfessionalDevelopment
Welcome to Part 4 of our PyQt5 series! This comprehensive lesson covers professional database integration, data visualization, and architectural patterns for building robust desktop applications.
---
## 🔹 Database Integration with PyQt5
### 1. SQLite Connection & Setup
### 2. SQL Model-View Integration
### 3. PostgreSQL Connection
---
#PyQt5 #SQL #DataViz #MVC #ProfessionalDevelopment
Welcome to Part 4 of our PyQt5 series! This comprehensive lesson covers professional database integration, data visualization, and architectural patterns for building robust desktop applications.
---
## 🔹 Database Integration with PyQt5
### 1. SQLite Connection & Setup
from PyQt5.QtSql import QSqlDatabase, QSqlQuery
def setup_database():
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("app_data.db")
if not db.open():
QMessageBox.critical(None, "Database Error", db.lastError().text())
return False
# Create tables if they don't exist
query = QSqlQuery()
query.exec_("""
CREATE TABLE IF NOT EXISTS contacts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE,
phone TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
""")
return True
### 2. SQL Model-View Integration
from PyQt5.QtSql import QSqlTableModel
class ContactManager(QWidget):
def __init__(self):
super().__init__()
self.model = QSqlTableModel()
self.model.setTable("contacts")
self.model.select()
self.setup_ui()
def setup_ui(self):
layout = QVBoxLayout()
# Table View
self.table = QTableView()
self.table.setModel(self.model)
self.table.setSelectionBehavior(QTableView.SelectRows)
self.table.setEditTriggers(QTableView.DoubleClicked)
# Buttons
add_btn = QPushButton("Add Contact")
add_btn.clicked.connect(self.add_contact)
del_btn = QPushButton("Delete Selected")
del_btn.clicked.connect(self.delete_contact)
# Layout
btn_layout = QHBoxLayout()
btn_layout.addWidget(add_btn)
btn_layout.addWidget(del_btn)
layout.addWidget(self.table)
layout.addLayout(btn_layout)
self.setLayout(layout)
def add_contact(self):
name, ok = QInputDialog.getText(self, "Add Contact", "Name:")
if ok and name:
record = self.model.record()
record.setValue("name", name)
self.model.insertRecord(-1, record)
self.model.submitAll()
def delete_contact(self):
selected = self.table.selectionModel().selectedRows()
for index in sorted(selected, reverse=True):
self.model.removeRow(index.row())
self.model.submitAll()
### 3. PostgreSQL Connection
def connect_postgresql():
db = QSqlDatabase.addDatabase("QPSQL")
db.setHostName("localhost")
db.setDatabaseName("myapp")
db.setUserName("postgres")
db.setPassword("password")
db.setPort(5432)
if not db.open():
error = db.lastError()
QMessageBox.critical(None, "Database Error",
f"Code: {error.number()}\n{error.text()}")
return False
return True
---