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....?
Peralatan yang Dibutuhkan Membangun Aplikasi To-Do List Modern dengan Python
Sebelum memulai, pastikan "peralatan" Anda sudah siap. Anda hanya memerlukan dua hal:
- Python: Pastikan Python sudah terinstal di komputer Anda.
- 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 diQListWidget
, mengubahnya menjadi format data yang mudah dibaca bernama JSON, lalu menyimpannya ke dalam sebuah file bernamatasks_data.json
.
- Memuat Tugas: Saat aplikasi pertama kali dijalankan, kita memanggil fungsi
load_tasks()
. Fungsi ini akan mencari filetasks_data.json
. Jika ada, ia akan membaca isinya dan menampilkan kembali semua tugas yang tersimpan ke dalamQListWidget
, 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.
![]() |
Tutorial Todo List sederhana |
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. Baca juga artikel menarik Aplikasi Peramal Cuaca
Selamat mencoba dan selamat berkarya ampai jumpa di artikel PyCoding ID berikutnya
0 Komentar