Membangun Aplikasi To-Do List Modern dengan Python

 

Membangun Aplikasi To-Do List Modern dengan Python dan PyQt5: Dari Nol hingga Jadi!


PythonCode ID
- Selamat datang kembali di PythonCodeID - Di tengah kesibukan sehari-hari, memiliki daftar tugas atau to-do list adalah penyelamat. Aplikasi ini membantu kita tetap terorganisir, fokus, dan produktif. Daripada hanya menggunakan aplikasi yang sudah ada, mengapa tidak mencoba membuatnya sendiri? Ini adalah proyek yang sangat baik untuk mengasah kemampuan pemrograman Anda.

Dalam artikel ini, kita akan membedah langkah demi langkah cara membuat aplikasi To-Do List yang fungsional dan modern menggunakan Python, salah satu bahasa pemrograman paling populer, dan pustaka PyQt5 untuk antarmuka grafisnya (GUI). Hasil akhirnya bukan sekadar aplikasi biasa, tetapi aplikasi yang mampu mengingat semua tugas Anda bahkan setelah ditutup dan dibuka kembali. Keren bukaaan....?

Membangun Aplikasi To-Do List Modern dengan Python
Membangun Aplikasi To-Do List Modern dengan Python


Peralatan yang Dibutuhkan

Sebelum memulai, pastikan "peralatan" Anda sudah siap. Anda hanya memerlukan dua hal:

  1. Python: Pastikan Python sudah terinstal di komputer Anda. 
  2. PyQt5: Ini adalah pustaka yang akan kita gunakan untuk membangun semua elemen visual. Jika belum terinstal, buka Terminal atau Command Prompt, lalu ketik perintah sederhana ini:

    pip install PyQt5
    

Sudah siap? Yuk.. Mari kita mulai merakit aplikasi kita

Langkah 1: Merancang Kerangka Aplikasi

Setiap bangunan membutuhkan fondasi yang kokoh. Dalam PyQt5, fondasi aplikasi kita terdiri dari beberapa bagian penting:

  • QApplication: Objek inti yang mengelola semua proses aplikasi.
  • QMainWindow: Jendela utama tempat kita akan meletakkan semua komponen lain.

Kita akan membungkus semua logika dan tampilan aplikasi kita dalam sebuah kelas, misalnya TodoListApp, yang mewarisi sifat-sifat dari QMainWindow.

Langkah 2: Membangun Antarmuka (UI)

Sekarang bagian yang menyenangkan: mendesain tampilan. Kita akan mengatur beberapa komponen atau widget untuk membentuk antarmuka aplikasi:

  • QLabel: Untuk menampilkan teks judul yang menarik.
  • QLineEdit: Kotak input tempat pengguna mengetik tugas baru mereka.
  • QPushButton: Tombol interaktif seperti "Tambah", "Hapus", dan "Tandai Selesai".
  • QListWidget: Area utama untuk menampilkan daftar semua tugas.

Untuk menatanya agar rapi, kita menggunakan Layout Manager seperti QVBoxLayout (menata widget secara vertikal) dan QHBoxLayout (menata widget secara horizontal).

Langkah 3: Memberi "Nyawa" pada Tombol

Tampilan tanpa fungsi tentu tidak ada artinya. Di PyQt5, kita menggunakan mekanisme elegan yang disebut Signals dan Slots. Sederhananya:

  • Signal: Sebuah peristiwa yang terjadi (misalnya, tombol diklik).
  • Slot: Sebuah fungsi yang akan dijalankan sebagai respons terhadap sinyal tersebut.

Kita menghubungkan sinyal dari tombol ke slot yang telah kita definisikan:

  • self.add_button.clicked.connect(self.add_task)

Fungsi add_task akan mengambil teks dari QLineEdit, menambahkan tanggal dan jam saat ini, lalu menampilkannya di QListWidget. Begitu pula dengan fungsi delete_task dan mark_task_done.

Langkah 4: Memberi "Ingatan" Abadi pada Aplikasi

Ini adalah fitur andalan dari aplikasi kita. Bagaimana caranya agar daftar tugas tidak hilang saat aplikasi ditutup? Jawabannya adalah dengan menyimpannya ke dalam sebuah file.

  • Menyimpan Tugas: Setiap kali ada perubahan (tugas ditambah, dihapus, atau ditandai), kita akan memanggil fungsi save_tasks(). Fungsi ini akan membaca semua item di QListWidget, mengubahnya menjadi format data yang mudah dibaca bernama JSON, lalu menyimpannya ke dalam sebuah file bernama tasks_data.json.
  • Memuat Tugas: Saat aplikasi pertama kali dijalankan, kita memanggil fungsi load_tasks(). Fungsi ini akan mencari file tasks_data.json. Jika ada, ia akan membaca isinya dan menampilkan kembali semua tugas yang tersimpan ke dalam QListWidget, lengkap dengan status "selesai" jika sebelumnya sudah ditandai.

Dengan cara ini, aplikasi kita memiliki "ingatan" jangka panjang!

Langkah 5: Sentuhan Akhir dengan "Stylesheet"

Agar aplikasi tidak terlihat monoton, PyQt5 menyediakan fitur stylesheet yang sangat mirip dengan CSS pada pengembangan web. Kita bisa mendefinisikan warna latar belakang, warna tombol, ukuran font, dan properti visual lainnya untuk memberikan tampilan yang profesional dan modern.




Membangun Aplikasi To-Do List Modern dengan Python




Kode Lengkap untuk Anda Coba

Berikut adalah kode lengkap dari aplikasi yang telah kita bahas. Salin kode ini, simpan sebagai file .py, dan jalankan untuk melihat hasilnya secara langsung!


import sys
import json
import os
from datetime import datetime
from PyQt5.QtWidgets import (
QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
QPushButton, QLineEdit, QListWidget, QLabel, QMessageBox,
QListWidgetItem
)
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont

# Nama file untuk menyimpan data tugas
TASKS_FILE = "tasks_data.json"

class TodoListApp(QMainWindow):
"""
Kelas utama untuk aplikasi To-Do List menggunakan PyQt5.
Mewarisi QMainWindow untuk menyediakan struktur jendela standar.
"""
def __init__(self):
"""
Konstruktor kelas. Menginisialisasi UI dan semua komponennya.
"""
super().__init__()

# --- Konfigurasi Jendela Utama ---
self.setWindowTitle("Daftar Tugas Harian (PyQt5)")
self.setGeometry(100, 100, 550, 600) # x, y, width, height

# --- Widget Pusat dan Layout Utama ---
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
self.main_layout = QVBoxLayout(self.central_widget)

# --- Inisialisasi Komponen UI ---
self.init_ui()
# --- Terapkan Stylesheet untuk Tampilan Modern ---
self.apply_stylesheet()
# --- Muat tugas dari file saat aplikasi dimulai ---
self.load_tasks()

def init_ui(self):
"""
Fungsi untuk membuat dan mengatur semua widget di dalam jendela.
"""
# --- Judul Aplikasi ---
title_label = QLabel("Apa Rencanamu Hari Ini?")
title_label.setFont(QFont("Helvetica", 18, QFont.Bold))
title_label.setAlignment(Qt.AlignCenter)
self.main_layout.addWidget(title_label)

# --- Layout untuk Input Tugas ---
input_layout = QHBoxLayout()
self.task_entry = QLineEdit()
self.task_entry.setPlaceholderText("Ketik tugas baru di sini...")
self.task_entry.setFont(QFont("Helvetica", 12))
self.task_entry.returnPressed.connect(self.add_task)
input_layout.addWidget(self.task_entry)

self.add_button = QPushButton("Tambah")
self.add_button.setFont(QFont("Helvetica", 11))
self.add_button.clicked.connect(self.add_task)
input_layout.addWidget(self.add_button)
self.main_layout.addLayout(input_layout)

# --- Daftar Tugas ---
self.task_listbox = QListWidget()
self.task_listbox.setFont(QFont("Helvetica", 12))
self.main_layout.addWidget(self.task_listbox)

# --- Layout untuk Tombol Aksi ---
button_layout = QHBoxLayout()
self.mark_done_button = QPushButton("Tandai Selesai")
self.mark_done_button.clicked.connect(self.mark_task_done)
button_layout.addWidget(self.mark_done_button)
self.delete_button = QPushButton("Hapus Tugas")
self.delete_button.clicked.connect(self.delete_task)
button_layout.addWidget(self.delete_button)

self.main_layout.addLayout(button_layout)

def apply_stylesheet(self):
"""
Menerapkan gaya (CSS-like) ke aplikasi untuk tampilan yang lebih baik.
"""
self.setStyleSheet("""
QMainWindow { background-color: #f0f8ff; }
QLabel { color: #003366; padding: 10px; }
QLineEdit {
padding: 8px; border: 1px solid #b0c4de;
border-radius: 5px; font-size: 14px;
}
QListWidget {
border: 1px solid #b0c4de; border-radius: 5px;
background-color: white;
}
QListWidget::item { padding: 8px; }
QListWidget::item:selected { background-color: #add8e6; color: black; }
QPushButton {
background-color: #778899; color: white;
font-weight: bold; padding: 10px;
border-radius: 5px; border: none;
}
QPushButton:hover { background-color: #708090; }
QPushButton#delete_button { background-color: #dc143c; }
QPushButton#delete_button:hover { background-color: #b22222; }
""")
self.delete_button.setObjectName("delete_button")

# --- SLOT (Fungsi Logika) ---

def add_task(self):
"""Slot untuk menambahkan tugas dari input ke dalam daftar."""
task_text = self.task_entry.text().strip()
if task_text:
# Tambahkan tanggal dan jam saat ini
now = datetime.now().strftime("%Y-%m-%d %H:%M")
full_task_text = f"[{now}] {task_text}"
item = QListWidgetItem(full_task_text)
self.task_listbox.addItem(item)
self.task_entry.clear()
self.save_tasks() # Simpan setiap kali ada penambahan tugas
else:
QMessageBox.warning(self, "Peringatan", "Kolom tugas tidak boleh kosong!")
self.task_entry.setFocus()

def delete_task(self):
"""Slot untuk menghapus tugas yang dipilih."""
current_item = self.task_listbox.currentItem()
if current_item:
confirm = QMessageBox.question(self, "Konfirmasi Hapus",
f"Apakah Anda yakin ingin menghapus tugas:\n'{current_item.text()}'?",
QMessageBox.Yes | QMessageBox.No)
if confirm == QMessageBox.Yes:
row = self.task_listbox.row(current_item)
self.task_listbox.takeItem(row)
self.save_tasks() # Simpan setelah menghapus
else:
QMessageBox.critical(self, "Error", "Pilih tugas yang ingin dihapus terlebih dahulu.")

def mark_task_done(self):
"""Slot untuk menandai tugas yang dipilih sebagai selesai."""
current_item = self.task_listbox.currentItem()
if current_item:
font = current_item.font()
current_text = current_item.text()

# Toggle status selesai
if not font.strikeOut():
font.setStrikeOut(True)
if not current_text.startswith("✓ "):
current_item.setText("✓ " + current_text)
else:
font.setStrikeOut(False)
if current_text.startswith("✓ "):
current_item.setText(current_text.replace("✓ ", "", 1))
current_item.setFont(font)
self.task_listbox.setCurrentItem(None)
self.save_tasks() # Simpan setelah mengubah status
else:
QMessageBox.critical(self, "Error", "Pilih tugas untuk ditandai sebagai selesai.")

# --- Fungsi untuk Menyimpan dan Memuat Tugas ---
def save_tasks(self):
"""Menyimpan semua tugas di listbox ke dalam file JSON."""
tasks_data = []
for i in range(self.task_listbox.count()):
item = self.task_listbox.item(i)
text = item.text()
is_done = item.font().strikeOut()
tasks_data.append({"text": text, "done": is_done})
try:
with open(TASKS_FILE, "w") as f:
json.dump(tasks_data, f, indent=4)
except Exception as e:
print(f"Gagal menyimpan tugas: {e}")

def load_tasks(self):
"""Memuat tugas dari file JSON saat aplikasi dibuka."""
if not os.path.exists(TASKS_FILE):
return # Jika file tidak ada, tidak melakukan apa-apa

try:
with open(TASKS_FILE, "r") as f:
tasks_data = json.load(f)
for task_info in tasks_data:
item = QListWidgetItem(task_info["text"])
if task_info["done"]:
font = item.font()
font.setStrikeOut(True)
item.setFont(font)
self.task_listbox.addItem(item)
except json.JSONDecodeError:
print(f"Peringatan: Tidak dapat membaca file {TASKS_FILE}. File mungkin rusak.")
except Exception as e:
print(f"Terjadi error saat memuat tugas: {e}")

def closeEvent(self, event):
"""Dipanggil secara otomatis saat jendela akan ditutup."""
self.save_tasks()
event.accept()

# --- Titik Masuk Utama Program ---
if __name__ == "__main__":
app = QApplication(sys.argv)
main_app = TodoListApp()
main_app.show()
sys.exit(app.exec_())


Kesimpulan

Anda baru saja melihat bagaimana Python dan PyQt5 dapat disatukan untuk menciptakan aplikasi desktop yang bermanfaat dan terlihat profesional. Anda telah belajar tentang struktur dasar aplikasi, tata letak, interaktivitas tombol, hingga cara menyimpan data secara permanen Ulasan PythonCode ID dalam Membangun Aplikasi To-Do List Modern dengan Python kiranya dapat membantu Anda dalam penguasaan python tingkat lanjut

Dari sini, kemungkinannya tidak terbatas. Anda bisa menambahkan fitur baru seperti prioritas tugas, kategori, atau bahkan notifikasi pengingat. Selamat mencoba dan selamat berkarya ampai jumpa di artikel PyCoding ID berikutnya







Posting Komentar

0 Komentar