Konten Sub Menu "Riwayat Kesehatan
Isi Menu "Profil Kesehatan"
(Konten Sub Menu "Riwayat Kesehatan")
4. Sub Menu "Riwayat Kesehatan"
Lanjut kita membuat konten Sub Menu "Riwayat Kesehatan"
Siap! Kita lanjut ke Sub Menu "Riwayat Kesehatan" sebagai bagian dari Menu Profil Kesehatan.
π― Tujuan Sub Menu "Riwayat Kesehatan":
- Mengizinkan pengguna untuk:
- Menambahkan catatan riwayat kesehatan (misalnya: penyakit kronis, alergi, operasi, dll)
- Melihat riwayat kesehatan yang telah disimpan
- Memperbarui catatan jika perlu (opsional, bisa ditambahkan nanti)
✅ Struktur File:
Kita buat file baru bernama: sub_menu_riwayat_kesehatan.py
π Path database:
DATABASE_PATH = "/storage/emulated/0/AppJadi/SmartNutriChefAI/Database/riwayat_kesehatan.db"
π§ Skema Tabel SQLite:
CREATE TABLE IF NOT EXISTS riwayat_kesehatan (
id INTEGER PRIMARY KEY AUTOINCREMENT,
deskripsi TEXT NOT NULL,
tanggal TEXT NOT NULL
);
✅ Isi File sub_menu_riwayat_kesehatan.py:
import tkinter as tk
from tkinter import messagebox
import sqlite3
from datetime import datetime
DATABASE_PATH = "/storage/emulated/0/AppJadi/SmartNutriChefAI/Database/riwayat_kesehatan.db"
def buat_tabel_riwayat():
conn = sqlite3.connect(DATABASE_PATH)
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS riwayat_kesehatan (
id INTEGER PRIMARY KEY AUTOINCREMENT,
deskripsi TEXT NOT NULL,
tanggal TEXT NOT NULL
)''')
conn.commit()
conn.close()
def simpan_riwayat(deskripsi):
tanggal = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
conn = sqlite3.connect(DATABASE_PATH)
c = conn.cursor()
c.execute("INSERT INTO riwayat_kesehatan (deskripsi, tanggal) VALUES (?, ?)", (deskripsi, tanggal))
conn.commit()
conn.close()
def ambil_riwayat():
conn = sqlite3.connect(DATABASE_PATH)
c = conn.cursor()
c.execute("SELECT deskripsi, tanggal FROM riwayat_kesehatan ORDER BY id DESC")
hasil = c.fetchall()
conn.close()
return hasil
def show_sub_menu_riwayat_kesehatan(root_frame):
from menu_profil_kesehatan import show_menu_profil_kesehatan # Hindari circular import
buat_tabel_riwayat()
for widget in root_frame.winfo_children():
widget.destroy()
# Judul
tk.Label(root_frame, text="Riwayat Kesehatan", font=("Arial", 18, "bold"), bg="green", fg="orange", pady=10).pack(pady=20)
# Form input
form_frame = tk.Frame(root_frame)
form_frame.pack(pady=10)
tk.Label(form_frame, text="Deskripsi Riwayat:", font=("Arial", 12)).grid(row=0, column=0, sticky="w", padx=5)
entry_riwayat = tk.Entry(form_frame, width=40)
entry_riwayat.grid(row=0, column=1, padx=5, pady=5)
def simpan_dan_bersih():
deskripsi = entry_riwayat.get().strip()
if deskripsi:
simpan_riwayat(deskripsi)
entry_riwayat.delete(0, tk.END)
tampilkan_riwayat()
else:
messagebox.showwarning("Validasi", "Deskripsi tidak boleh kosong.")
# Tombol simpan
tk.Button(root_frame, text="Simpan Riwayat", font=("Arial", 12), bg="#4CAF50", fg="white", command=simpan_dan_bersih).pack(pady=10)
# Label daftar riwayat
label_riwayat = tk.Label(root_frame, text="", justify="left", font=("Arial", 11), anchor="w")
label_riwayat.pack(padx=10, pady=10, fill="both")
def tampilkan_riwayat():
riwayat_list = ambil_riwayat()
if not riwayat_list:
label_riwayat.config(text="Belum ada riwayat kesehatan.")
else:
teks = "Riwayat Tersimpan:\n\n"
for deskripsi, tanggal in riwayat_list:
teks += f"- {deskripsi} ({tanggal})\n"
label_riwayat.config(text=teks)
tampilkan_riwayat()
# Tombol kembali
tk.Button(root_frame, text="Kembali", font=("Arial", 12), bg="gray", fg="white", command=lambda: show_menu_profil_kesehatan(root_frame)).pack(pady=30)
π Integrasi ke menu_profil_kesehatan.py
Tambahkan import:
from sub_menu_riwayat_kesehatan import show_sub_menu_riwayat_kesehatan
Lalu tambahkan tombol di bagian tombol submenu:
("Riwayat Kesehatan", show_sub_menu_riwayat_kesehatan),
✅ Fitur Disediakan:
- Menyimpan riwayat secara bertanggal
- Menampilkan daftar riwayat yang pernah disimpan
- Validasi input deskripsi
- Tampilan bersih, navigasi kembali ke menu sebelumnya
Jika kamu ingin menambahkan fitur edit/hapus riwayat, atau filter berdasarkan tanggal, saya siap bantu.
Lanjut ke submenu berikutnya?
Tolong perbesar kotak entry-nys 2 baris lagi ke bawah
Baik! Jika kamu ingin memperbesar kotak entry untuk input Riwayat Kesehatan agar bisa menampung lebih dari satu baris teks, maka gunakan widget Text alih-alih Entry, karena Entry hanya mendukung satu baris.
π§ Ubah bagian input Entry ke Text:
Di file sub_menu_riwayat_kesehatan.py, ubah bagian berikut:
π‘ Sebelumnya (dengan Entry satu baris):
entry_riwayat = tk.Entry(form_frame, width=40)
entry_riwayat.grid(row=0, column=1, padx=5, pady=5)
✅ Ganti jadi (dengan Text dua baris):
entry_riwayat = tk.Text(form_frame, width=40, height=3)
entry_riwayat.grid(row=0, column=1, padx=5, pady=5)
π§ Juga ubah fungsi simpan:
π‘ Sebelumnya (ambil dari Entry):
deskripsi = entry_riwayat.get().strip()
entry_riwayat.delete(0, tk.END)
✅ Ganti jadi (ambil dari Text):
deskripsi = entry_riwayat.get("1.0", tk.END).strip()
entry_riwayat.delete("1.0", tk.END)
π‘ Penjelasan:
Textdigunakan untuk input banyak barisheight=3artinya 3 baris tinggiget("1.0", tk.END)artinya ambil teks dari baris 1, kolom 0 sampai akhir
✅ Hasil:
- Kotak input jadi tinggi 3 baris
- Lebih nyaman untuk deskripsi panjang (misalnya penjelasan penyakit)
- Teks tetap bisa disimpan ke database seperti biasa
Kalau kamu ingin menambahkan scrollbar, validasi panjang deskripsi, atau fitur edit/hapus per item, saya siap bantu juga.
Lanjut ke submenu berikutnya?
Pada kode isi file sub_menu_riwayat_kesehatan.py berikut ini, tolong atur label "Deskripsi Riwayat" tepat berada rata kiri, dan kotak entry berada dibawahnya.
# Kode:
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import sqlite3
from datetime import datetime
DATABASE_PATH = "/storage/emulated/0/AppJadi/SmartNutriChefAI/Database/riwayat_kesehatan.db"
def buat_tabel_riwayat():
conn = sqlite3.connect(DATABASE_PATH)
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS riwayat_kesehatan (
id INTEGER PRIMARY KEY AUTOINCREMENT,
deskripsi TEXT NOT NULL,
tanggal TEXT NOT NULL
)''')
conn.commit()
conn.close()
def simpan_riwayat(deskripsi):
tanggal = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
conn = sqlite3.connect(DATABASE_PATH)
c = conn.cursor()
c.execute("INSERT INTO riwayat_kesehatan (deskripsi, tanggal) VALUES (?, ?)", (deskripsi, tanggal))
conn.commit()
conn.close()
def ambil_riwayat():
conn = sqlite3.connect(DATABASE_PATH)
c = conn.cursor()
c.execute("SELECT deskripsi, tanggal FROM riwayat_kesehatan ORDER BY id DESC")
hasil = c.fetchall()
conn.close()
return hasil
def show_sub_menu_riwayat_kesehatan(root_frame):
from menu_profil_kesehatan import show_menu_profil_kesehatan # Hindari circular import
buat_tabel_riwayat()
for widget in root_frame.winfo_children():
widget.destroy()
# Judul
tk.Label(root_frame, text="Riwayat Kesehatan", font=("Arial", 18, "bold"), bg="green", fg="orange", pady=10).pack(pady=20)
# Form input
form_frame = tk.Frame(root_frame)
form_frame.pack(pady=10)
tk.Label(form_frame, text="Deskripsi Riwayat:", font=("Arial", 12)).grid(row=0, column=0, sticky="w", padx=5)
entry_riwayat = tk.Text(form_frame, width=40, height=3)
entry_riwayat.grid(row=0, column=1, padx=5, pady=5)
def simpan_dan_bersih():
deskripsi = entry_riwayat.get("1.0", tk.END).strip()
if deskripsi:
simpan_riwayat(deskripsi)
entry_riwayat.delete("1.0", tk.END)
tampilkan_riwayat()
else:
messagebox.showwarning("Validasi", "Deskripsi tidak boleh kosong.")
# Tambahkan separator antar tombol (kecuali terakhir)
ttk.Separator(root_frame, orient='horizontal').pack(fill='x', padx=40, pady=2)
# Tombol simpan
tk.Button(root_frame, text="Simpan Riwayat", font=("Arial", 12), bg="#4CAF50", fg="white", command=simpan_dan_bersih).pack(pady=10)
# Label daftar riwayat
label_riwayat = tk.Label(root_frame, text="", justify="left", font=("Arial", 11), anchor="w")
label_riwayat.pack(padx=10, pady=10, fill="both")
def tampilkan_riwayat():
riwayat_list = ambil_riwayat()
if not riwayat_list:
label_riwayat.config(text="Belum ada riwayat kesehatan.")
else:
teks = "Riwayat Tersimpan:\n\n"
for deskripsi, tanggal in riwayat_list:
teks += f"- {deskripsi} ({tanggal})\n"
label_riwayat.config(text=teks)
tampilkan_riwayat()
# Tombol kembali
tk.Button(root_frame, text="Kembali", font=("Arial", 12), bg="gray", fg="white", command=lambda: show_menu_profil_kesehatan(root_frame)).pack(pady=30)
Untuk menyesuaikan tampilan agar:
- Label "Deskripsi Riwayat:" rata kiri (left aligned)
- Kotak
Textentry tepat berada di bawah label tersebut
Kita perlu mengganti layout grid menjadi layout pack dan mengatur perataan (alignment) dengan anchor="w" dan justify="left" pada label serta membungkus semuanya dalam satu Frame.
✅ Berikut adalah perbaikannya (dengan komentar penjelas):
Ubah bagian berikut dalam fungsi show_sub_menu_riwayat_kesehatan:
π Ganti bagian ini:
# Form input
form_frame = tk.Frame(root_frame)
form_frame.pack(pady=10)
tk.Label(form_frame, text="Deskripsi Riwayat:", font=("Arial", 12)).grid(row=0, column=0, sticky="w", padx=5)
entry_riwayat = tk.Text(form_frame, width=40, height=3)
entry_riwayat.grid(row=0, column=1, padx=5, pady=5)
✅ Dengan bagian ini:
# Form input
form_frame = tk.Frame(root_frame)
form_frame.pack(pady=10, fill="x")
# Label Deskripsi Riwayat
tk.Label(
form_frame,
text="Deskripsi Riwayat:",
font=("Arial", 12),
anchor="w",
justify="left"
).pack(anchor="w", padx=10)
# Kotak entry berada tepat di bawah label
entry_riwayat = tk.Text(form_frame, width=50, height=4)
entry_riwayat.pack(padx=10, pady=5)
π Hasil Perubahan:
- Label berada rata kiri, bukan sejajar samping.
- Kotak entry
Textberada tepat di bawahnya. - Gunakan
.pack(anchor="w")untuk meratakan ke kiri.
Jika kamu ingin tampilan yang lebih rapi dan terpusat di layar, kamu juga bisa tambahkan form_frame.pack(pady=10, anchor="center") agar isi form di tengah horizontal tapi tetap label rata kiri.
Siap untuk lanjut ke sub menu berikutnya?
Bantu buat bingkai (frame)nya bisa di scroll vertikal dan horizontal.
Baik! Untuk membuat bingkai (frame) yang bisa di-scroll secara vertikal dan horizontal dalam Tkinter, kita perlu menggabungkan beberapa komponen:
✅ Komponen utama:
Canvassebagai tempat menggambar konten.Scrollbarvertikal dan horizontal.Framedi dalamCanvassebagai tempat meletakkan widget sebenarnya.
π§ Implementasi pada sub_menu_riwayat_kesehatan.py:
Gantilah bagian show_sub_menu_riwayat_kesehatan() dengan struktur berikut ini:
✅ 1. Gunakan scrollable frame:
def show_sub_menu_riwayat_kesehatan(root_frame):
from menu_profil_kesehatan import show_menu_profil_kesehatan # Hindari circular import
buat_tabel_riwayat()
# Bersihkan isi frame utama
for widget in root_frame.winfo_children():
widget.destroy()
# ======== SCROLLABLE AREA ==========
canvas = tk.Canvas(root_frame)
canvas.pack(side="left", fill="both", expand=True)
scrollbar_y = tk.Scrollbar(root_frame, orient="vertical", command=canvas.yview)
scrollbar_y.pack(side="right", fill="y")
scrollbar_x = tk.Scrollbar(root_frame, orient="horizontal", command=canvas.xview)
scrollbar_x.pack(side="bottom", fill="x")
canvas.configure(yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set)
# Frame scrollable yang berada di dalam canvas
scrollable_frame = tk.Frame(canvas)
# Bind konfigurasi ukuran
scrollable_frame.bind(
"<Configure>",
lambda e: canvas.configure(
scrollregion=canvas.bbox("all")
)
)
# Tambahkan scrollable_frame ke canvas
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
# ===================================
# Judul
tk.Label(scrollable_frame, text="Riwayat Kesehatan", font=("Arial", 18, "bold"),
bg="green", fg="orange", pady=10).pack(pady=20)
# Form input
form_frame = tk.Frame(scrollable_frame)
form_frame.pack(pady=10, fill="x")
# Label & Text Entry
tk.Label(form_frame, text="Deskripsi Riwayat:", font=("Arial", 12),
anchor="w", justify="left").pack(anchor="w", padx=10)
entry_riwayat = tk.Text(form_frame, width=60, height=5, wrap="word")
entry_riwayat.pack(padx=10, pady=5)
# Fungsi simpan
def simpan_dan_bersih():
deskripsi = entry_riwayat.get("1.0", tk.END).strip()
if deskripsi:
simpan_riwayat(deskripsi)
entry_riwayat.delete("1.0", tk.END)
tampilkan_riwayat()
else:
messagebox.showwarning("Validasi", "Deskripsi tidak boleh kosong.")
ttk.Separator(scrollable_frame, orient='horizontal').pack(fill='x', padx=40, pady=2)
# Tombol Simpan
tk.Button(scrollable_frame, text="Simpan Riwayat", font=("Arial", 12),
bg="#4CAF50", fg="white", command=simpan_dan_bersih).pack(pady=10)
# Label Daftar Riwayat
label_riwayat = tk.Label(scrollable_frame, text="", justify="left",
font=("Arial", 11), anchor="w")
label_riwayat.pack(padx=10, pady=10, fill="both")
def tampilkan_riwayat():
riwayat_list = ambil_riwayat()
if not riwayat_list:
label_riwayat.config(text="Belum ada riwayat kesehatan.")
else:
teks = "Riwayat Tersimpan:\n\n"
for deskripsi, tanggal in riwayat_list:
teks += f"- {deskripsi} ({tanggal})\n"
label_riwayat.config(text=teks)
tampilkan_riwayat()
# Tombol Kembali
tk.Button(scrollable_frame, text="Kembali", font=("Arial", 12), bg="gray", fg="white",
command=lambda: show_menu_profil_kesehatan(root_frame)).pack(pady=30)
⚙️ Hasil Fungsional:
Frameyang dapat di-scroll vertikal dan horizontal.- Desain tetap fleksibel dan bisa menampilkan konten lebih panjang jika diperlukan.
Siap dilanjut ke sub menu berikutnya atau ingin ditambahkan fitur lain (edit, hapus, cari data riwayat)?
Sampai saat ini perubahan, penyempurnaan, dan tambahan file pada applikasi SmartNutriChefAI adalah:
1. menu_profil_kesehatan.py
Kode programnya adalah berikut:
# Menu Profil Kesehatan
import tkinter as tk
from tkinter import ttk
from sub_menu_data_diri import show_sub_menu_data_diri
from sub_menu_berat_tinggi_badan import show_sub_menu_berat_tinggi_badan
from sub_menu_indeks_massa_tubuh import show_sub_menu_indeks_massa_tubuh
from sub_menu_riwayat_kesehatan import show_sub_menu_riwayat_kesehatan
def show_menu_profil_kesehatan(root_frame):
from menu_utama import tampilkan_halaman_utama # Hindari circular import
for widget in root_frame.winfo_children():
widget.destroy()
# Judul
tk.Label(
root_frame,
text="Profil Kesehatan",
font=("Arial", 18, "bold"),
bg="green",
fg="orange",
padx=10,
pady=10
).pack(pady=20)
# Daftar submenu sebagai list tuple: (teks tombol, fungsi yang dipanggil)
submenus = [
("Data Diri", show_sub_menu_data_diri),
("Berat & Tinggi Badan", show_sub_menu_berat_tinggi_badan),
# Tambahkan submenu lain di sini, contoh:
# ("Kalori Harian", show_sub_menu_kalori_harian),
# ("Riwayat BMI", show_sub_menu_riwayat_bmi),
("Indeks Massa Tubuh \n(IMT)", show_sub_menu_indeks_massa_tubuh), # Tambahkan ini
("Riwayat Kesehatan", show_sub_menu_riwayat_kesehatan),
]
# Buat tombol-tombol sub menu
for teks, fungsi in submenus:
tk.Button(
root_frame,
text=teks,
font=("Arial", 12),
bg="light blue",
fg="black",
command=lambda f=fungsi: f(root_frame)
).pack(pady=10)
# Tambahkan separator antar tombol (kecuali terakhir)
ttk.Separator(root_frame, orient='horizontal').pack(fill='x', padx=40, pady=2)
# Tombol kembali
tk.Button(
root_frame,
text="Kembali ke Menu Utama",
font=("Arial", 12),
bg="gray",
fg="white",
command=lambda: tampilkan_halaman_utama(root_frame)
).pack(pady=30)
2. sub_menu_riwayat_kesehatan.py
Kode programnya adalah berikut:
Comments
Post a Comment