Ev Tipi İnternet Kafe Projesi [Python]

Programlama ve Script dilleri konusunda bilgi paylaşım alanıdır.
Cevapla
Kullanıcı avatarı
TRWE_2012
Zettabyte1
Zettabyte1
Mesajlar: 15614
Kayıt: 25 Eyl 2013, 13:38
cinsiyet: Erkek
Teşekkür etti: 2712 kez
Teşekkür edildi: 5626 kez

Ev Tipi İnternet Kafe Projesi [Python]

Mesaj gönderen TRWE_2012 »

Resim
KOD İÇERİKLERİ :

Versiyon-1 :

Kod: Tümünü seç

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# =============================================================================
# Project      : VB6 -> Python Conversion  (FINAL PROJECT)
# Module       : Home Internet Cafe Timer  — Mini AkınSoft
# Description  : Tracks internet session time and calculates billing cost.
#                - Start  : records start time, begins live elapsed counter
#                - Stop   : records end time, calculates duration + total cost
#                - Settings menu : set hourly rate (validated min/max bounds)
#                - Live ticker   : duration + running cost updates every second
#                - Cost formula  : (elapsed_seconds / 3600) * hourly_rate
# Platform     : GNU/Linux Mint 22.2 MATE x64  |  Windows 11 24H2 x64
# Python       : 3.8+  (stdlib only: tkinter, datetime)
# =============================================================================

import os
import sys

# ---------------------------------------------------------------------------
# VENV BOOTSTRAPPER  (v1.1 - robust)
# ---------------------------------------------------------------------------
VENV_DIR       = "/home/linuxmaster/python-toolchain"
_SENTINEL_FLAG = "_VENV_BOOTSTRAP_DONE"
_candidates    = [
    os.path.join(VENV_DIR, "bin", "python3"),
    os.path.join(VENV_DIR, "bin", "python"),
    os.path.join(VENV_DIR, "Scripts", "python.exe"),
]

def _venv_is_healthy() -> bool:
    lib = os.path.join(VENV_DIR, "lib")
    if os.path.isdir(lib):
        for e in os.listdir(lib):
            if os.path.isdir(os.path.join(lib, e, "site-packages")):
                return True
    return os.path.isdir(os.path.join(VENV_DIR, "Lib", "site-packages"))

def _bootstrap_venv() -> None:
    if os.environ.get(_SENTINEL_FLAG) == "1":
        return
    inside = os.path.normcase(os.path.realpath(sys.executable)).startswith(
        os.path.normcase(os.path.realpath(VENV_DIR)))
    if inside or not _venv_is_healthy():
        return
    for c in _candidates:
        if os.path.isfile(c):
            os.environ[_SENTINEL_FLAG] = "1"
            os.execv(c, [c] + sys.argv)

_bootstrap_venv()

# ---------------------------------------------------------------------------
# IMPORTS
# ---------------------------------------------------------------------------
import tkinter as tk
from tkinter import messagebox, simpledialog
from datetime import datetime

# ---------------------------------------------------------------------------
# CONSTANTS
# ---------------------------------------------------------------------------
WINDOW_TITLE  = "Internet Timer"
TICK_MS       = 1000
DEFAULT_RATE  = 200_000
MIN_RATE      = 1
MAX_RATE      = 99_999_999
CURRENCY      = "TL"

# ---------------------------------------------------------------------------
# HELPERS
# ---------------------------------------------------------------------------

def format_duration(seconds: int) -> str:
    h = seconds // 3600
    m = (seconds % 3600) // 60
    s = seconds % 60
    return f"{h} hour  {m} minute  {s} second"

def format_money(amount: float) -> str:
    return f"{int(amount):,} {CURRENCY}".replace(",", ".")

def calc_cost(seconds: int, hourly_rate: int) -> float:
    return (seconds / 3600.0) * hourly_rate

# ---------------------------------------------------------------------------
# MAIN APPLICATION
# ---------------------------------------------------------------------------

class InternetTimerApp:

    def __init__(self, master: tk.Tk) -> None:
        self.master       = master
        self._running     = False
        self._start_dt    = None
        self._after_id    = None
        self._hourly_rate = DEFAULT_RATE

        master.title(WINDOW_TITLE)
        master.resizable(False, False)

        self._build_menu()
        self._build_ui()
        self._center_window()
        master.protocol("WM_DELETE_WINDOW", self._on_quit)
        self._refresh_rate_display()

    # ------------------------------------------------------------------
    # MENU
    # ------------------------------------------------------------------

    def _build_menu(self) -> None:
        menubar  = tk.Menu(self.master)
        settings = tk.Menu(menubar, tearoff=0)
        settings.add_command(label="Set Hourly Rate ...", command=self._op_set_rate)
        settings.add_separator()
        settings.add_command(label="Quit",                command=self._on_quit)
        menubar.add_cascade(label="Settings", menu=settings)
        self.master.config(menu=menubar)

    # ------------------------------------------------------------------
    # UI
    # ------------------------------------------------------------------

    def _build_ui(self) -> None:
        FL = ("Helvetica", 10, "bold")
        FE = ("Courier",   12)
        FR = ("Courier",   13, "bold")
        FB = ("Helvetica", 11, "bold")

        outer = tk.Frame(self.master, padx=14, pady=12)
        outer.pack()

        # ---- TOP SECTION ----
        top = tk.Frame(outer)
        top.pack(fill=tk.X, pady=(0, 10))

        # Left — buttons
        bf = tk.Frame(top, padx=6, pady=6, relief=tk.GROOVE, bd=2)
        bf.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 16))

        self.btn_start = tk.Button(
            bf, text="Start", width=10, font=FB,
            bg="#d4edda", activebackground="#a8d5b5",
            relief=tk.RAISED, bd=3, command=self._op_start)
        self.btn_start.pack(pady=(6, 8))

        self.btn_stop = tk.Button(
            bf, text="Stop", width=10, font=FB,
            bg="#f8d7da", activebackground="#e8a0a8",
            relief=tk.RAISED, bd=3, state=tk.DISABLED,
            command=self._op_stop)
        self.btn_stop.pack(pady=(0, 6))

        # Right — time fields
        rf = tk.Frame(top)
        rf.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        for lbl_text, var_attr, bg in [
            ("Start time:",  "var_start",    "#ffffff"),
            ("End time:",    "var_end",      "#ffffff"),
            ("Duration:",    "var_duration", "#fffbe6"),
        ]:
            tk.Label(rf, text=lbl_text, font=FL, anchor="w").pack(fill=tk.X)
            var = tk.StringVar(value="")
            setattr(self, var_attr, var)
            tk.Entry(rf, textvariable=var, font=FE, state="readonly",
                     readonlybackground=bg, width=28,
                     relief=tk.SUNKEN).pack(fill=tk.X, pady=(0, 8))

        # ---- SEPARATOR ----
        tk.Frame(outer, height=2, bg="#aaaaaa").pack(fill=tk.X, pady=8)

        # ---- BOTTOM SECTION ----
        bottom = tk.Frame(outer)
        bottom.pack(fill=tk.X)

        for lbl_text, var_attr, bg in [
            ("Hourly rate:",   "var_rate",  "#eaf4fb"),
            ("Total amount:",  "var_total", "#fff0e6"),
        ]:
            row = tk.Frame(bottom)
            row.pack(fill=tk.X, pady=(0, 5))
            tk.Label(row, text=lbl_text, font=FL,
                     width=14, anchor="w").pack(side=tk.LEFT)
            var = tk.StringVar(value="")
            setattr(self, var_attr, var)
            tk.Entry(row, textvariable=var, font=FR, state="readonly",
                     readonlybackground=bg, width=20,
                     relief=tk.SUNKEN).pack(side=tk.LEFT)

        # ---- STATUS BAR ----
        self.lbl_status = tk.Label(
            self.master,
            text="  Ready — press Start to begin session.",
            anchor="w", relief=tk.SUNKEN,
            font=("Courier", 9), fg="#444444", bg="#e8e8e8",
        )
        self.lbl_status.pack(fill=tk.X, side=tk.BOTTOM)

    # ------------------------------------------------------------------
    # SETTINGS
    # ------------------------------------------------------------------

    def _op_set_rate(self) -> None:
        raw = simpledialog.askstring(
            "Set Hourly Rate",
            f"Enter hourly rate ({MIN_RATE:,} – {MAX_RATE:,} {CURRENCY}):\n"
            f"Current rate: {self._hourly_rate:,} {CURRENCY}",
            initialvalue=str(self._hourly_rate),
            parent=self.master,
        )
        if raw is None:
            return
        try:
            value = int(raw.strip().replace(".", "").replace(",", ""))
        except ValueError:
            messagebox.showwarning("Invalid Rate",
                "Please enter a whole number.", parent=self.master)
            return
        if not (MIN_RATE <= value <= MAX_RATE):
            messagebox.showwarning(
                "Out of Range",
                f"Hourly rate must be between "
                f"{MIN_RATE:,} and {MAX_RATE:,} {CURRENCY}.",
                parent=self.master,
            )
            return
        self._hourly_rate = value
        self._refresh_rate_display()
        self._set_status(f"Hourly rate updated: {value:,} {CURRENCY}")

    def _refresh_rate_display(self) -> None:
        self.var_rate.set(format_money(self._hourly_rate))

    # ------------------------------------------------------------------
    # START / STOP
    # ------------------------------------------------------------------

    def _op_start(self) -> None:
        if self._running:
            return
        self._start_dt = datetime.now()
        self._running  = True
        self.var_start.set(self._start_dt.strftime("%H:%M:%S"))
        self.var_end.set("")
        self.var_duration.set("")
        self.var_total.set("")
        self.btn_start.config(state=tk.DISABLED)
        self.btn_stop.config(state=tk.NORMAL)
        self._set_status("Session running ...")
        self._tick()

    def _op_stop(self) -> None:
        if not self._running:
            return
        if self._after_id is not None:
            self.master.after_cancel(self._after_id)
            self._after_id = None
        self._running   = False
        end_dt          = datetime.now()
        elapsed_sec     = int((end_dt - self._start_dt).total_seconds())
        cost            = calc_cost(elapsed_sec, self._hourly_rate)
        self.var_end.set(end_dt.strftime("%H:%M:%S"))
        self.var_duration.set(format_duration(elapsed_sec))
        self.var_total.set(format_money(cost))
        self.btn_start.config(state=tk.NORMAL)
        self.btn_stop.config(state=tk.DISABLED)
        self._set_status(
            f"Session ended.  Duration: {format_duration(elapsed_sec)}"
            f"  |  Total: {format_money(cost)}"
        )

    # ------------------------------------------------------------------
    # LIVE TICKER
    # ------------------------------------------------------------------

    def _tick(self) -> None:
        if not self._running:
            return
        elapsed_sec = int((datetime.now() - self._start_dt).total_seconds())
        self.var_duration.set(format_duration(elapsed_sec))
        self.var_total.set(format_money(calc_cost(elapsed_sec, self._hourly_rate)))
        self._after_id = self.master.after(TICK_MS, self._tick)

    # ------------------------------------------------------------------
    # MISC
    # ------------------------------------------------------------------

    def _set_status(self, text: str) -> None:
        self.lbl_status.config(text=f"  {text}")

    def _on_quit(self) -> None:
        if self._running:
            if not messagebox.askyesno(
                "Session Active",
                "A session is currently running.\n\n"
                "Quit without stopping the session?",
                icon=messagebox.WARNING, parent=self.master,
            ):
                return
        if self._after_id is not None:
            self.master.after_cancel(self._after_id)
        self.master.destroy()

    def _center_window(self) -> None:
        self.master.update_idletasks()
        w  = self.master.winfo_width()
        h  = self.master.winfo_height()
        sw = self.master.winfo_screenwidth()
        sh = self.master.winfo_screenheight()
        self.master.geometry(f"+{(sw - w) // 2}+{(sh - h) // 2}")


# ---------------------------------------------------------------------------
# ENTRY POINT
# ---------------------------------------------------------------------------

def main() -> None:
    root = tk.Tk()
    InternetTimerApp(root)
    root.mainloop()
    input("\nPress ENTER to exit.")


if __name__ == "__main__":
    main()
Versiyon - 2

Kod: Tümünü seç

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# =============================================================================
# Project      : VB6 -> Python Conversion  (FINAL PROJECT)
# Module       : Home Internet Cafe Timer  — Mini AkınSoft
# Description  : Tracks internet session time and calculates billing cost.
#                - Start  : records start time, begins live elapsed counter
#                - Stop   : records end time, calculates duration + total cost
#                - Settings menu : set hourly rate (validated min/max bounds)
#                - Live ticker   : duration + running cost updates every second
#                - Cost formula  : (elapsed_seconds / 3600) * hourly_rate
# Platform     : GNU/Linux Mint 22.2 MATE x64  |  Windows 11 24H2 x64
# Python       : 3.8+  (stdlib only: tkinter, datetime)
# =============================================================================

import os
import sys

# ---------------------------------------------------------------------------
# VENV BOOTSTRAPPER  (v1.1 - robust)
# ---------------------------------------------------------------------------
VENV_DIR       = "/home/linuxmaster/python-toolchain"
_SENTINEL_FLAG = "_VENV_BOOTSTRAP_DONE"
_candidates    = [
    os.path.join(VENV_DIR, "bin", "python3"),
    os.path.join(VENV_DIR, "bin", "python"),
    os.path.join(VENV_DIR, "Scripts", "python.exe"),
]

def _venv_is_healthy() -> bool:
    lib = os.path.join(VENV_DIR, "lib")
    if os.path.isdir(lib):
        for e in os.listdir(lib):
            if os.path.isdir(os.path.join(lib, e, "site-packages")):
                return True
    return os.path.isdir(os.path.join(VENV_DIR, "Lib", "site-packages"))

def _bootstrap_venv() -> None:
    if os.environ.get(_SENTINEL_FLAG) == "1":
        return
    inside = os.path.normcase(os.path.realpath(sys.executable)).startswith(
        os.path.normcase(os.path.realpath(VENV_DIR)))
    if inside or not _venv_is_healthy():
        return
    for c in _candidates:
        if os.path.isfile(c):
            os.environ[_SENTINEL_FLAG] = "1"
            os.execv(c, [c] + sys.argv)

_bootstrap_venv()

# ---------------------------------------------------------------------------
# IMPORTS
# ---------------------------------------------------------------------------
import tkinter as tk
from tkinter import messagebox, simpledialog
from datetime import datetime
import socket

# ---------------------------------------------------------------------------
# CONSTANTS
# ---------------------------------------------------------------------------
WINDOW_TITLE  = "Internet Timer"
TICK_MS       = 1000
NET_CHECK_MS  = 3000            # network poll interval (3 seconds)
NET_HOST      = "8.8.8.8"      # Google DNS — reliable, lightweight
NET_PORT      = 53
NET_TIMEOUT   = 2               # seconds
DEFAULT_RATE  = 200_000
MIN_RATE      = 1
MAX_RATE      = 99_999_999
CURRENCY      = "TL"

# ---------------------------------------------------------------------------
# HELPERS
# ---------------------------------------------------------------------------

def is_connected() -> bool:
    """
    Return True if the machine can reach the internet.
    Uses a raw TCP connect to Google DNS (8.8.8.8:53).
    No DNS lookup is performed — result is purely connectivity-based.
    Works identically on GNU/Linux and Windows.
    """
    try:
        socket.setdefaulttimeout(NET_TIMEOUT)
        with socket.create_connection((NET_HOST, NET_PORT)):
            return True
    except OSError:
        return False

def format_duration(seconds: int) -> str:
    h = seconds // 3600
    m = (seconds % 3600) // 60
    s = seconds % 60
    return f"{h} hour  {m} minute  {s} second"

def format_money(amount: float) -> str:
    return f"{int(amount):,} {CURRENCY}".replace(",", ".")

def calc_cost(seconds: int, hourly_rate: int) -> float:
    return (seconds / 3600.0) * hourly_rate

# ---------------------------------------------------------------------------
# MAIN APPLICATION
# ---------------------------------------------------------------------------

class InternetTimerApp:

    def __init__(self, master: tk.Tk) -> None:
        self.master       = master
        self._running     = False
        self._start_dt    = None
        self._after_id    = None
        self._net_id      = None        # network monitor after() handle
        self._hourly_rate = DEFAULT_RATE

        master.title(WINDOW_TITLE)
        master.resizable(False, False)

        self._build_menu()
        self._build_ui()
        self._center_window()
        master.protocol("WM_DELETE_WINDOW", self._on_quit)
        self._refresh_rate_display()

    # ------------------------------------------------------------------
    # MENU
    # ------------------------------------------------------------------

    def _build_menu(self) -> None:
        menubar  = tk.Menu(self.master)
        settings = tk.Menu(menubar, tearoff=0)
        settings.add_command(label="Set Hourly Rate ...", command=self._op_set_rate)
        settings.add_separator()
        settings.add_command(label="Quit",                command=self._on_quit)
        menubar.add_cascade(label="Settings", menu=settings)
        self.master.config(menu=menubar)

    # ------------------------------------------------------------------
    # UI
    # ------------------------------------------------------------------

    def _build_ui(self) -> None:
        FL = ("Helvetica", 10, "bold")
        FE = ("Courier",   12)
        FR = ("Courier",   13, "bold")
        FB = ("Helvetica", 11, "bold")

        outer = tk.Frame(self.master, padx=14, pady=12)
        outer.pack()

        # ---- TOP SECTION ----
        top = tk.Frame(outer)
        top.pack(fill=tk.X, pady=(0, 10))

        # Left — buttons
        bf = tk.Frame(top, padx=6, pady=6, relief=tk.GROOVE, bd=2)
        bf.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 16))

        self.btn_start = tk.Button(
            bf, text="Start", width=10, font=FB,
            bg="#d4edda", activebackground="#a8d5b5",
            relief=tk.RAISED, bd=3, command=self._op_start)
        self.btn_start.pack(pady=(6, 8))

        self.btn_stop = tk.Button(
            bf, text="Stop", width=10, font=FB,
            bg="#f8d7da", activebackground="#e8a0a8",
            relief=tk.RAISED, bd=3, state=tk.DISABLED,
            command=self._op_stop)
        self.btn_stop.pack(pady=(0, 6))

        # Right — time fields
        rf = tk.Frame(top)
        rf.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        for lbl_text, var_attr, bg in [
            ("Start time:",  "var_start",    "#ffffff"),
            ("End time:",    "var_end",      "#ffffff"),
            ("Duration:",    "var_duration", "#fffbe6"),
        ]:
            tk.Label(rf, text=lbl_text, font=FL, anchor="w").pack(fill=tk.X)
            var = tk.StringVar(value="")
            setattr(self, var_attr, var)
            tk.Entry(rf, textvariable=var, font=FE, state="readonly",
                     readonlybackground=bg, width=28,
                     relief=tk.SUNKEN).pack(fill=tk.X, pady=(0, 8))

        # ---- SEPARATOR ----
        tk.Frame(outer, height=2, bg="#aaaaaa").pack(fill=tk.X, pady=8)

        # ---- BOTTOM SECTION ----
        bottom = tk.Frame(outer)
        bottom.pack(fill=tk.X)

        for lbl_text, var_attr, bg in [
            ("Hourly rate:",   "var_rate",  "#eaf4fb"),
            ("Total amount:",  "var_total", "#fff0e6"),
        ]:
            row = tk.Frame(bottom)
            row.pack(fill=tk.X, pady=(0, 5))
            tk.Label(row, text=lbl_text, font=FL,
                     width=14, anchor="w").pack(side=tk.LEFT)
            var = tk.StringVar(value="")
            setattr(self, var_attr, var)
            tk.Entry(row, textvariable=var, font=FR, state="readonly",
                     readonlybackground=bg, width=20,
                     relief=tk.SUNKEN).pack(side=tk.LEFT)

        # ---- STATUS BAR ----
        self.lbl_status = tk.Label(
            self.master,
            text="  Ready — press Start to begin session.",
            anchor="w", relief=tk.SUNKEN,
            font=("Courier", 9), fg="#444444", bg="#e8e8e8",
        )
        self.lbl_status.pack(fill=tk.X, side=tk.BOTTOM)

    # ------------------------------------------------------------------
    # SETTINGS
    # ------------------------------------------------------------------

    def _op_set_rate(self) -> None:
        raw = simpledialog.askstring(
            "Set Hourly Rate",
            f"Enter hourly rate ({MIN_RATE:,} – {MAX_RATE:,} {CURRENCY}):\n"
            f"Current rate: {self._hourly_rate:,} {CURRENCY}",
            initialvalue=str(self._hourly_rate),
            parent=self.master,
        )
        if raw is None:
            return
        try:
            value = int(raw.strip().replace(".", "").replace(",", ""))
        except ValueError:
            messagebox.showwarning("Invalid Rate",
                "Please enter a whole number.", parent=self.master)
            return
        if not (MIN_RATE <= value <= MAX_RATE):
            messagebox.showwarning(
                "Out of Range",
                f"Hourly rate must be between "
                f"{MIN_RATE:,} and {MAX_RATE:,} {CURRENCY}.",
                parent=self.master,
            )
            return
        self._hourly_rate = value
        self._refresh_rate_display()
        self._set_status(f"Hourly rate updated: {value:,} {CURRENCY}")

    def _refresh_rate_display(self) -> None:
        self.var_rate.set(format_money(self._hourly_rate))

    # ------------------------------------------------------------------
    # START / STOP
    # ------------------------------------------------------------------

    def _op_start(self) -> None:
        if self._running:
            return
        # Pre-check: warn if already offline before starting
        if not is_connected():
            messagebox.showwarning(
                "No Internet Connection",
                "No active internet connection was detected.\n\n"
                "Please connect to the internet before starting a session.",
                parent=self.master,
            )
            return
        self._start_dt = datetime.now()
        self._running  = True
        self.var_start.set(self._start_dt.strftime("%H:%M:%S"))
        self.var_end.set("")
        self.var_duration.set("")
        self.var_total.set("")
        self.btn_start.config(state=tk.DISABLED)
        self.btn_stop.config(state=tk.NORMAL)
        self._set_status("Session running ...")
        self._tick()
        self._net_poll()        # start network watchdog

    def _op_stop(self, reason: str = "manual") -> None:
        if not self._running:
            return
        # Cancel both timers
        for attr in ("_after_id", "_net_id"):
            h = getattr(self, attr, None)
            if h is not None:
                self.master.after_cancel(h)
                setattr(self, attr, None)
        self._running   = False
        end_dt          = datetime.now()
        elapsed_sec     = int((end_dt - self._start_dt).total_seconds())
        cost            = calc_cost(elapsed_sec, self._hourly_rate)
        self.var_end.set(end_dt.strftime("%H:%M:%S"))
        self.var_duration.set(format_duration(elapsed_sec))
        self.var_total.set(format_money(cost))
        self.btn_start.config(state=tk.NORMAL)
        self.btn_stop.config(state=tk.DISABLED)

        if reason == "disconnect":
            self._set_status(
                "Internet connection lost — session stopped automatically."
            )
        else:
            self._set_status(
                f"Session ended.  Duration: {format_duration(elapsed_sec)}"
                f"  |  Total: {format_money(cost)}"
            )

    # ------------------------------------------------------------------
    # LIVE TICKER
    # ------------------------------------------------------------------

    def _tick(self) -> None:
        if not self._running:
            return
        elapsed_sec = int((datetime.now() - self._start_dt).total_seconds())
        self.var_duration.set(format_duration(elapsed_sec))
        self.var_total.set(format_money(calc_cost(elapsed_sec, self._hourly_rate)))
        self._after_id = self.master.after(TICK_MS, self._tick)

    # ------------------------------------------------------------------
    # NETWORK WATCHDOG
    # ------------------------------------------------------------------

    def _net_poll(self) -> None:
        """
        Poll internet connectivity every NET_CHECK_MS milliseconds.
        Runs only while a session is active.
        When the connection drops, the session is stopped automatically
        and the user is notified with a clear warning dialog.
        """
        if not self._running:
            return
        if not is_connected():
            # Stop the session first, then show the dialog
            self._op_stop(reason="disconnect")
            messagebox.showwarning(
                "Internet Connection Lost",
                "The internet connection has been interrupted.\n\n"
                "The session has been stopped automatically.\n\n"
                "Reconnect and press Start to begin a new session.",
                parent=self.master,
            )
            return     # do NOT reschedule — session is over
        self._net_id = self.master.after(NET_CHECK_MS, self._net_poll)

    # ------------------------------------------------------------------
    # MISC
    # ------------------------------------------------------------------

    def _set_status(self, text: str) -> None:
        self.lbl_status.config(text=f"  {text}")

    def _on_quit(self) -> None:
        if self._running:
            if not messagebox.askyesno(
                "Session Active",
                "A session is currently running.\n\n"
                "Quit without stopping the session?",
                icon=messagebox.WARNING, parent=self.master,
            ):
                return
        for attr in ("_after_id", "_net_id"):
            h = getattr(self, attr, None)
            if h is not None:
                self.master.after_cancel(h)
        self.master.destroy()

    def _center_window(self) -> None:
        self.master.update_idletasks()
        w  = self.master.winfo_width()
        h  = self.master.winfo_height()
        sw = self.master.winfo_screenwidth()
        sh = self.master.winfo_screenheight()
        self.master.geometry(f"+{(sw - w) // 2}+{(sh - h) // 2}")


# ---------------------------------------------------------------------------
# ENTRY POINT
# ---------------------------------------------------------------------------

def main() -> None:
    root = tk.Tk()
    InternetTimerApp(root)
    root.mainloop()
    input("\nPress ENTER to exit.")


if __name__ == "__main__":
    main()
Güle güle kullanın, kullandıkça bu forum'u hatırlayın....!!! :-)
Kullanıcı avatarı
TRWE_2012
Zettabyte1
Zettabyte1
Mesajlar: 15614
Kayıt: 25 Eyl 2013, 13:38
cinsiyet: Erkek
Teşekkür etti: 2712 kez
Teşekkür edildi: 5626 kez

İnternet Kullanımı : 1 saat 15 dakika 59 saniye sonunda tutar (TL)

Mesaj gönderen TRWE_2012 »

Resim
Demek ki "İnternet kafe'de olsaydım bu kadar para cebimden çıkacaktı"...!

NOT :

Ağ bağlantı gerekmeyen versiyon 1 başka bir amaç ile kullanabilirsiniz.(şeytanın bile aklına gelmez bu amaç)

AMAÇ :

Günlük bilgisayar kullanım zamanının , parasal değeri nedir? (yani soyut bir olayı somut nicelik ile ölçüyorsunuz)
Cevapla

“Programlama ve Script dilleri” sayfasına dön