Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # gui_app.py
- import tkinter as tk
- from tkinter import messagebox, ttk
- # Import kelas-kelas backend kita
- # Pastikan file perpustakaan_backend.py ada di folder yang sama
- from perpustakaan_backend import Perpustakaan, Pustakawan, StatusItem, StatusTransaksi
- class AppPerpustakaan:
- # ... (kode __init__ dan buat_tampilan_utama tetap sama) ...
- """
- Kelas utama untuk aplikasi GUI Sistem Perpustakaan.
- Ini bertindak sebagai 'View' dan 'Controller' sederhana.
- """
- def __init__(self, root):
- self.root = root
- self.root.title("Sistem Manajemen Perpustakaan")
- self.root.geometry("900x1200")
- # 1. Inisialisasi Backend
- # Kita buat satu objek perpustakaan dan pustakawan yang akan dipakai
- try:
- nama_file_db = "Tkinter/perpus_data.pkl"
- self.perpustakaan_utama = Perpustakaan(nama_file_db) # Muat data jika ada
- except Exception as e:
- messagebox.showerror("Startup Error", f"Gagal memuat data: {e}")
- self.perpustakaan_utama = Perpustakaan(nama_file_db) # Coba buat baru
- self.pustakawan_andi = Pustakawan("P-001", "Andi")
- # Inisialisasi data awal jika perpustakaan kosong (untuk demo)
- if not self.perpustakaan_utama.daftar_item:
- print("INFO: Menambahkan data item awal untuk demo...")
- self.pustakawan_andi.tambah_item_ke_koleksi(self.perpustakaan_utama, "Buku", "BK-001", "OOP Python", pengarang="Dr. Inovatif")
- self.pustakawan_andi.tambah_item_ke_koleksi(self.perpustakaan_utama, "Majalah", "MGZ-001", "Quanta", edisi="Okt 2025")
- self.pustakawan_andi.tambah_item_ke_koleksi(self.perpustakaan_utama, "Buku", "BK-002", "Sains Data", pengarang="Prof. Analitika")
- # 2. Setup Tampilan Utama
- self.buat_tampilan_utama()
- def buat_tampilan_utama(self):
- # Judul Utama
- judul = tk.Label(self.root, text="Sistem Perpustakaan", font=("Helvetica", 18, "bold"))
- judul.pack(pady=10) # Pack untuk judul
- # Buat Notebook (Tabs) untuk memisahkan fungsionalitas
- self.tab_kontrol = ttk.Notebook(self.root)
- self.tab1 = ttk.Frame(self.tab_kontrol)
- self.tab2 = ttk.Frame(self.tab_kontrol)
- self.tab_kontrol.add(self.tab1, text='Manajemen Koleksi & Member')
- self.tab_kontrol.add(self.tab2, text='Transaksi Peminjaman')
- self.tab_kontrol.pack(expand=True, fill="both", padx=10, pady=10)
- # Panggil fungsi untuk membangun konten tiap tab
- self.buat_tab_manajemen(self.tab1)
- self.buat_tab_transaksi(self.tab2)
- # Tombol Simpan & Keluar
- # Kita letakkan di bawah, jadi kita buat framenya dulu
- frame_bawah = tk.Frame(self.root)
- frame_bawah.pack(side=tk.BOTTOM, fill="x", pady=10)
- tombol_simpan = tk.Button(frame_bawah, text="Simpan Data & Keluar", command=self.simpan_dan_keluar)
- tombol_simpan.pack(pady=5, padx=10)
- def buat_tab_manajemen(self, tab):
- # ... (kode buat_tab_manajemen tetap sama) ...
- """Membangun konten untuk Tab 1."""
- # --- Frame Atas (Form Member & Daftar Item) ---
- frame_atas = tk.Frame(tab)
- frame_atas.pack(side=tk.TOP, fill="x", pady=5)
- # Buat frame kiri untuk menampung dua form
- frame_kiri_forms = tk.Frame(frame_atas)
- frame_kiri_forms.pack(side=tk.LEFT, fill="y", padx=5, anchor='n')
- # --- Frame Kiri Atas: Form Tambah Anggota ---
- frame_tambah_member = tk.LabelFrame(frame_kiri_forms, text="Form Tambah Anggota Baru", padx=10, pady=10)
- frame_tambah_member.pack(side=tk.TOP, fill="y", padx=5, anchor='n')
- # Layout .grid() untuk form
- label_nama = tk.Label(frame_tambah_member, text="Nama:")
- label_nama.grid(row=0, column=0, sticky="e", padx=5)
- self.entry_nama = tk.Entry(frame_tambah_member, width=30)
- self.entry_nama.grid(row=0, column=1, padx=5, pady=5)
- label_alamat = tk.Label(frame_tambah_member, text="Alamat:")
- label_alamat.grid(row=1, column=0, sticky="e", padx=5)
- self.entry_alamat = tk.Entry(frame_tambah_member, width=30)
- self.entry_alamat.grid(row=1, column=1, padx=5, pady=5)
- tombol_submit_member = tk.Button(frame_tambah_member, text="Daftarkan", command=self.daftar_member_baru)
- tombol_submit_member.grid(row=2, column=1, sticky="w", padx=5, pady=10)
- # --- Frame Kiri Bawah: Form Tambah Item ---
- frame_tambah_item = tk.LabelFrame(frame_kiri_forms, text="Form Tambah Item Baru", padx=10, pady=10)
- frame_tambah_item.pack(side=tk.TOP, fill="y", padx=5, anchor='n', pady=10)
- # Widget untuk form tambah item
- label_tipe = tk.Label(frame_tambah_item, text="Tipe Item:")
- label_tipe.grid(row=0, column=0, sticky="e", padx=5)
- self.combo_tipe_item = ttk.Combobox(frame_tambah_item, values=["Buku", "Majalah"], width=27, state="readonly")
- self.combo_tipe_item.grid(row=0, column=1, padx=5, pady=5)
- self.combo_tipe_item.bind("<<ComboboxSelected>>", self.on_tipe_item_changed)
- label_item_id = tk.Label(frame_tambah_item, text="ID Item:")
- label_item_id.grid(row=1, column=0, sticky="e", padx=5)
- self.entry_item_id = tk.Entry(frame_tambah_item, width=30)
- self.entry_item_id.grid(row=1, column=1, padx=5, pady=5)
- label_item_judul = tk.Label(frame_tambah_item, text="Judul:")
- label_item_judul.grid(row=2, column=0, sticky="e", padx=5)
- self.entry_item_judul = tk.Entry(frame_tambah_item, width=30)
- self.entry_item_judul.grid(row=2, column=1, padx=5, pady=5)
- # Label dan Entry dinamis (Pengarang/Edisi)
- self.label_khusus = tk.Label(frame_tambah_item, text="Pengarang/Edisi:")
- self.label_khusus.grid(row=3, column=0, sticky="e", padx=5)
- self.entry_khusus = tk.Entry(frame_tambah_item, width=30)
- self.entry_khusus.grid(row=3, column=1, padx=5, pady=5)
- tombol_submit_item = tk.Button(frame_tambah_item, text="Tambahkan Item", command=self.tambah_item_baru)
- tombol_submit_item.grid(row=4, column=1, sticky="w", padx=5, pady=10)
- # Panggil on_tipe_item_changed untuk set default
- self.combo_tipe_item.set("Buku") # Set default
- self.on_tipe_item_changed(None) # Panggil manual untuk set label
- # --- Frame Kanan Atas: Daftar Koleksi Item ---
- frame_daftar_koleksi_item = tk.LabelFrame(frame_atas, text="Daftar Koleksi Item", padx=10, pady=10)
- frame_daftar_koleksi_item.pack(side=tk.LEFT, fill="both", expand=True, padx=5)
- tombol_refresh_daftar_koleksi_item = tk.Button(frame_daftar_koleksi_item, text="Refresh Daftar Buku", command=self.refresh_daftar_buku)
- tombol_refresh_daftar_koleksi_item.pack(pady=5, anchor='w')
- self.tree_buku = ttk.Treeview(frame_daftar_koleksi_item, columns=("ID", "Judul", "Status"), show="headings")
- self.tree_buku.heading("ID", text="ID Item")
- self.tree_buku.heading("Judul", text="Judul")
- self.tree_buku.heading("Status", text="Status")
- self.tree_buku.column("ID", width=80)
- self.tree_buku.column("Judul", width=200)
- self.tree_buku.column("Status", width=100)
- self.tree_buku.pack(fill="both", expand=True)
- # --- Frame Tengah (Daftar Member) ---
- frame_daftar_member = tk.LabelFrame(tab, text="Daftar Member", padx=10, pady=10)
- frame_daftar_member.pack(side=tk.TOP, fill="both", expand=True, pady=10)
- frame_tombol_member = tk.Frame(frame_daftar_member)
- frame_tombol_member.pack(fill="x")
- tombol_refresh_member = tk.Button(frame_tombol_member, text="Refresh Daftar Member", command=self.refresh_daftar_member)
- tombol_refresh_member.pack(side=tk.LEFT, pady=5, anchor='w')
- tombol_riwayat_member = tk.Button(frame_tombol_member, text="Tampilkan Riwayat Member Terpilih", command=self.tampilkan_riwayat_terpilih)
- tombol_riwayat_member.pack(side=tk.LEFT, pady=5, padx=10, anchor='w')
- self.tree_member = ttk.Treeview(frame_daftar_member, columns=("ID", "Nama", "Alamat"), show="headings")
- self.tree_member.heading("ID", text="ID Member")
- self.tree_member.heading("Nama", text="Nama")
- self.tree_member.heading("Alamat", text="Alamat")
- self.tree_member.column("ID", width=120)
- self.tree_member.column("Nama", width=200)
- self.tree_member.column("Alamat", width=300)
- self.tree_member.pack(fill="both", expand=True)
- # --- Frame Bawah (Riwayat Transaksi) ---
- frame_riwayat = tk.LabelFrame(tab, text="Riwayat Transaksi Member", padx=10, pady=10)
- frame_riwayat.pack(side=tk.BOTTOM, fill="both", expand=True, pady=5)
- self.label_riwayat_member = tk.Label(frame_riwayat, text="Pilih member dari tabel di atas dan klik 'Tampilkan Riwayat'", font=("Helvetica", 9, "italic"))
- self.label_riwayat_member.pack(anchor='w')
- self.tree_riwayat = ttk.Treeview(frame_riwayat, columns=("ID Trx", "Item", "Tgl Pinjam", "Tgl Kembali", "Status", "Denda"), show="headings")
- self.tree_riwayat.heading("ID Trx", text="ID Transaksi")
- self.tree_riwayat.heading("Item", text="Judul Item")
- self.tree_riwayat.heading("Tgl Pinjam", text="Tgl Pinjam")
- self.tree_riwayat.heading("Tgl Kembali", text="Batas Kembali")
- self.tree_riwayat.heading("Status", text="Status")
- self.tree_riwayat.heading("Denda", text="Denda")
- self.tree_riwayat.column("ID Trx", width=120)
- self.tree_riwayat.column("Item", width=200)
- self.tree_riwayat.column("Tgl Pinjam", width=100)
- self.tree_riwayat.column("Tgl Kembali", width=100)
- self.tree_riwayat.column("Status", width=80)
- self.tree_riwayat.column("Denda", width=100)
- self.tree_riwayat.pack(fill="both", expand=True, pady=5)
- # Langsung refresh data saat tab dibuat
- self.refresh_daftar_buku()
- self.refresh_daftar_member()
- def buat_tab_transaksi(self, tab):
- """Membangun konten untuk Tab 2."""
- # Tambahkan tombol refresh di atas
- frame_atas_trx = tk.Frame(tab)
- frame_atas_trx.pack(fill="x", padx=5, pady=5)
- tombol_refresh_trx = tk.Button(frame_atas_trx, text="Refresh Semua List Transaksi", command=self.refresh_list_transaksi)
- tombol_refresh_trx.pack(anchor='w')
- # Gunakan PanedWindow agar bisa di-resize
- pane = ttk.PanedWindow(tab, orient=tk.HORIZONTAL)
- pane.pack(fill="both", expand=True, padx=5, pady=5)
- # --- Frame Kiri: Peminjaman ---
- frame_pinjam = tk.LabelFrame(pane, text="Form Peminjaman", padx=10, pady=10)
- pane.add(frame_pinjam, weight=1)
- label_pinjam_member = tk.Label(frame_pinjam, text="Pilih ID Member:")
- label_pinjam_member.grid(row=0, column=0, sticky="e", padx=5)
- # Ubah Entry menjadi Combobox
- self.combo_pinjam_member_id = ttk.Combobox(frame_pinjam, width=27, state="readonly")
- self.combo_pinjam_member_id.grid(row=0, column=1, padx=5, pady=5)
- label_pinjam_item = tk.Label(frame_pinjam, text="Pilih ID Item (Tersedia):")
- label_pinjam_item.grid(row=1, column=0, sticky="e", padx=5)
- # Ubah Entry menjadi Combobox
- self.combo_pinjam_item_id = ttk.Combobox(frame_pinjam, width=27, state="readonly")
- self.combo_pinjam_item_id.grid(row=1, column=1, padx=5, pady=5)
- tombol_pinjam = tk.Button(frame_pinjam, text="Pinjamkan Item", command=self.lakukan_peminjaman)
- tombol_pinjam.grid(row=2, column=1, sticky="w", padx=5, pady=10)
- # --- Frame Kanan: Pengembalian ---
- frame_kembali = tk.LabelFrame(pane, text="Form Pengembalian", padx=10, pady=10)
- pane.add(frame_kembali, weight=1)
- label_kembali_trx = tk.Label(frame_kembali, text="Pilih ID Transaksi (Aktif):")
- label_kembali_trx.grid(row=0, column=0, sticky="e", padx=5)
- # Ubah Entry menjadi Combobox
- self.combo_kembali_trx_id = ttk.Combobox(frame_kembali, width=27, state="readonly")
- self.combo_kembali_trx_id.grid(row=0, column=1, padx=5, pady=5)
- tombol_kembali = tk.Button(frame_kembali, text="Kembalikan Item", command=self.lakukan_pengembalian)
- tombol_kembali.grid(row=2, column=1, sticky="w", padx=5, pady=10)
- # Panggil refresh list saat tab dibuat
- self.refresh_list_transaksi()
- def daftar_member_baru(self):
- """Callback untuk tombol 'Daftarkan'."""
- print("DEBUG: Tombol Daftar Member Ditekan")
- # 1. Ambil data dari widget Entry
- nama = self.entry_nama.get()
- alamat = self.entry_alamat.get()
- # 2. Validasi input (sederhana)
- if not nama or not alamat:
- messagebox.showwarning("Input Tidak Lengkap", "Nama dan Alamat tidak boleh kosong!")
- return # Hentikan fungsi
- # 3. Panggil logika backend (dari perpustakaan_backend.py)
- try:
- # Ini adalah inti integrasi: GUI memanggil method backend
- # Menggunakan self.perpustakaan_utama (dari __init__) bukan self.perpus
- member_baru = self.pustakawan_andi.lakukan_pendaftaran(self.perpustakaan_utama, nama, alamat)
- # 4. Beri umpan balik ke pengguna
- messagebox.showinfo("Pendaftaran Berhasil",
- f"Member baru berhasil ditambahkan!\n"
- f"Nama: {member_baru.nama}\n"
- f"ID: {member_baru.member_id}")
- # 5. Kosongkan form
- self.entry_nama.delete(0, tk.END)
- self.entry_alamat.delete(0, tk.END)
- # 6. Refresh daftar member
- self.refresh_daftar_member()
- # Refresh juga combobox member di tab transaksi
- self.refresh_list_transaksi()
- except Exception as e:
- messagebox.showerror("Pendaftaran Gagal", f"Terjadi error: {e}")
- def refresh_daftar_buku(self):
- # ... (kode refresh_daftar_buku tetap sama) ...
- """Callback untuk me-refresh data di Treeview."""
- # Hapus data lama
- for i in self.tree_buku.get_children():
- self.tree_buku.delete(i)
- # Ambil data baru dari backend dan masukkan ke treeview
- # Menggunakan self.perpustakaan_utama (dari __init__) bukan self.perpus
- for item in self.perpustakaan_utama.daftar_item:
- info = item.get_info()
- self.tree_buku.insert("", tk.END, values=(info["ID"], info["Judul"], info["Status"]))
- def refresh_daftar_member(self):
- # ... (kode refresh_daftar_member tetap sama) ...
- """Callback untuk me-refresh data di Treeview Member."""
- # Hapus data lama
- for i in self.tree_member.get_children():
- self.tree_member.delete(i)
- # Ambil data baru dari backend dan masukkan ke treeview
- for member in self.perpustakaan_utama.daftar_member:
- # Mengambil _alamat, idealnya ada getter
- self.tree_member.insert("", tk.END, values=(member.member_id, member.nama, member._alamat))
- def lakukan_peminjaman(self):
- """Callback untuk tombol Pinjamkan Item."""
- # Ambil data dari Combobox
- member_id = self.combo_pinjam_member_id.get()
- item_id = self.combo_pinjam_item_id.get()
- if not member_id or not item_id:
- messagebox.showwarning("Input Tidak Lengkap", "ID Member dan ID Item harus diisi.")
- return
- try:
- trx_baru = self.pustakawan_andi.lakukan_peminjaman(self.perpustakaan_utama, member_id, item_id)
- messagebox.showinfo("Peminjaman Berhasil",
- f"Transaksi {trx_baru.transaksi_id} sukses.\n"
- f"Item '{trx_baru.item.judul}' dipinjam oleh {trx_baru.member.nama}.")
- # Kosongkan form
- # Gunakan .set('') untuk Combobox
- self.combo_pinjam_member_id.set('')
- self.combo_pinjam_item_id.set('')
- # Refresh daftar buku karena statusnya berubah
- self.refresh_daftar_buku()
- # Refresh list transaksi
- self.refresh_list_transaksi()
- except Exception as e:
- messagebox.showerror("Peminjaman Gagal", f"Terjadi error: {e}")
- def lakukan_pengembalian(self):
- """Callback untuk tombol Kembalikan Item."""
- # Ambil data dari Combobox
- trx_id = self.combo_kembali_trx_id.get()
- if not trx_id:
- messagebox.showwarning("Input Tidak Lengkap", "ID Transaksi harus diisi.")
- return
- try:
- # Cek denda sebelum transaksi diselesaikan
- transaksi = self.perpustakaan_utama.cari_transaksi(trx_id)
- if not transaksi:
- raise Exception(f"Transaksi {trx_id} tidak ditemukan.")
- if transaksi.status != StatusTransaksi.AKTIF:
- raise Exception(f"Transaksi {trx_id} sudah tidak aktif/selesai.")
- # Hitung denda
- denda = transaksi.hitung_denda()
- # Lakukan pengembalian
- self.pustakawan_andi.lakukan_pengembalian(self.perpustakaan_utama, trx_id)
- pesan_denda = f"Denda: Rp {denda:,.2f}" if denda > 0 else "Tidak ada denda."
- messagebox.showinfo("Pengembalian Berhasil",
- f"Transaksi {trx_id} sukses dikembalikan.\n{pesan_denda}")
- # Gunakan .set('') untuk Combobox
- self.combo_kembali_trx_id.set('')
- # Refresh daftar buku karena statusnya berubah
- self.refresh_daftar_buku()
- # Refresh list transaksi
- self.refresh_list_transaksi()
- # Refresh riwayat jika sedang ditampilkan
- self.tampilkan_riwayat_terpilih(auto_refresh=True)
- except Exception as e:
- messagebox.showerror("Pengembalian Gagal", f"Terjadi error: {e}")
- def tampilkan_riwayat_terpilih(self, auto_refresh=False):
- # ... (kode tampilkan_riwayat_terpilih tetap sama) ...
- """Callback untuk tombol Tampilkan Riwayat."""
- selected_item = self.tree_member.focus()
- if not selected_item:
- # Jika auto_refresh (dipanggil dari fungsi lain) dan tidak ada yg dipilih, abaikan
- if not auto_refresh:
- messagebox.showwarning("Pilihan Kosong", "Pilih salah satu member dari tabel untuk melihat riwayat.")
- return
- item_data = self.tree_member.item(selected_item)
- member_id = item_data['values'][0]
- member_nama = item_data['values'][1]
- member = self.perpustakaan_utama.cari_member(member_id)
- if not member:
- messagebox.showerror("Error", f"Data member {member_id} tidak ditemukan di backend.")
- return
- # Update label riwayat
- self.label_riwayat_member.config(text=f"Menampilkan riwayat untuk: {member_nama} (ID: {member_id})")
- # Bersihkan tree riwayat
- for i in self.tree_riwayat.get_children():
- self.tree_riwayat.delete(i)
- # Ambil data riwayat
- riwayat = member.get_riwayat_peminjaman(self.perpustakaan_utama)
- if not riwayat:
- self.tree_riwayat.insert("", tk.END, values=("", "Tidak ada riwayat peminjaman.", "", "", "", ""))
- return
- # Tampilkan data riwayat baru
- for trx in riwayat:
- item = trx.item
- # Pastikan denda ter-update
- denda = trx.hitung_denda() if trx.status == StatusTransaksi.TERLAMBAT else trx._denda
- self.tree_riwayat.insert("", tk.END, values=(
- trx.transaksi_id,
- item.judul,
- trx._tgl_pinjam.strftime('%Y-%m-%d'),
- trx._tgl_kembali.strftime('%Y-%m-%d'),
- trx.status.value,
- f"Rp{denda:,.2f}"
- ))
- def on_tipe_item_changed(self, event):
- """Mengubah label form berdasarkan pilihan Combobox."""
- tipe_terpilih = self.combo_tipe_item.get()
- if tipe_terpilih == "Buku":
- self.label_khusus.config(text="Pengarang:")
- elif tipe_terpilih == "Majalah":
- self.label_khusus.config(text="Edisi:")
- self.entry_khusus.delete(0, tk.END)
- def tambah_item_baru(self):
- """Callback untuk tombol 'Tambahkan Item'."""
- print("DEBUG: Tombol Tambah Item Ditekan")
- # 1. Ambil data dari form
- tipe = self.combo_tipe_item.get()
- item_id = self.entry_item_id.get()
- judul = self.entry_item_judul.get()
- khusus = self.entry_khusus.get()
- # 2. Validasi input
- if not all([tipe, item_id, judul, khusus]):
- messagebox.showwarning("Input Tidak Lengkap", "Semua field harus diisi!")
- return
- # 3. Siapkan kwargs untuk factory
- kwargs = {}
- if tipe == "Buku":
- kwargs['pengarang'] = khusus
- elif tipe == "Majalah":
- kwargs['edisi'] = khusus
- # 4. Panggil logika backend
- try:
- self.pustakawan_andi.tambah_item_ke_koleksi(
- self.perpustakaan_utama,
- tipe.lower(),
- item_id,
- judul,
- **kwargs
- )
- # 5. Beri umpan balik
- messagebox.showinfo("Penambahan Berhasil", f"{tipe} '{judul}' berhasil ditambahkan ke koleksi.")
- # 6. Kosongkan form
- self.entry_item_id.delete(0, tk.END)
- self.entry_item_judul.delete(0, tk.END)
- self.entry_khusus.delete(0, tk.END)
- # 7. Refresh daftar buku
- self.refresh_daftar_buku()
- # Refresh juga combobox item di tab transaksi
- self.refresh_list_transaksi()
- except Exception as e:
- messagebox.showerror("Penambahan Gagal", f"Terjadi error: {e}")
- def update_combobox_member(self):
- """Mengambil semua ID member dan mengupdate combobox peminjaman."""
- try:
- member_ids = [member.member_id for member in self.perpustakaan_utama.daftar_member]
- self.combo_pinjam_member_id['values'] = member_ids
- except Exception as e:
- print(f"Error updating member combobox: {e}")
- def update_combobox_item_tersedia(self):
- """Mengambil semua ID item yang TERSEDIA dan mengupdate combobox peminjaman."""
- try:
- item_ids = [item.item_id for item in self.perpustakaan_utama.daftar_item if item.status == StatusItem.TERSEDIA]
- self.combo_pinjam_item_id['values'] = item_ids
- except Exception as e:
- print(f"Error updating item combobox: {e}")
- def update_combobox_transaksi_aktif(self):
- """Mengambil semua ID transaksi yang AKTIF dan mengupdate combobox pengembalian."""
- try:
- trx_ids = [trx.transaksi_id for trx in self.perpustakaan_utama.daftar_transaksi if trx.status == StatusTransaksi.AKTIF]
- self.combo_kembali_trx_id['values'] = trx_ids
- except Exception as e:
- print(f"Error updating transaksi combobox: {e}")
- def refresh_list_transaksi(self):
- """Satu fungsi untuk me-refresh semua combobox di tab transaksi."""
- print("DEBUG: Merefresh semua list transaksi...")
- self.update_combobox_member()
- self.update_combobox_item_tersedia()
- self.update_combobox_transaksi_aktif()
- def simpan_dan_keluar(self):
- # ... (kode simpan_dan_keluar tetap sama) ...
- """Callback untuk tombol simpan."""
- try:
- self.perpustakaan_utama.simpan_data()
- messagebox.showinfo("Sukses", "Data berhasil disimpan!")
- self.root.destroy() # Menutup jendela
- except Exception as e:
- messagebox.showerror("Gagal Menyimpan", f"Terjadi error: {e}")
- # --- Titik Mulai Eksekusi ---
- if __name__ == "__main__":
- root_window = tk.Tk()
- app = AppPerpustakaan(root_window)
- root_window.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment