Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding script of Pomodoro Timer With GUI #383

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions Pomodoro Timer with GUI/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Pomodoro Timer with GUI

This project is a graphical user interface (GUI) application for a Pomodoro Timer, implemented in Python using the Tkinter library. The Pomodoro Timer helps users manage their work and break periods effectively based on the Pomodoro Technique. The application also includes visual features such as a progress bar and an image carousel.

## Features

- **Timer Functionality**:
- Work sessions (25 minutes by default).
- Short breaks (5 minutes after every cycle).
- Long breaks (15 minutes after every 8 cycles).

- **Progress Bar**:
- Displays the current progress of the work session.

- **Buttons**:
- **Start**: Starts the timer.
- **Pause**: Pauses the timer.
- **Reset**: Resets the timer to the initial state.

- **Notifications**:
- Alerts the user when transitioning between work and break periods.

## Prerequisites

- Python 3.x
- Required Python libraries:
- `tkinter` (built into Python standard library)
- `Pillow` (for image processing)

Install `Pillow` using pip if not already installed:
```bash
pip install pillow
```

## File Structure

- **`pomodoroTimerWithGUI.py`**: Main Python script containing the implementation.
- **Images**: A set of PNG images used in the image carousel. Place these images in the specified directory (`./Pomodoro Timer with GUI/images`).
- `0.png`
- `1.png`
- `2.png`
- ...
- `9.png`

## How to Run

1. Ensure you have Python and the required libraries installed.
2. Place the required images in the directory `./Pomodoro Timer with GUI/images`.
3. Run the script:
```bash
python pomodoroTimerWithGUI.py
```

## How to Use

1. **Start**: Click the "Start" button to begin the timer. The timer will start with a 25-minute work session by default.
2. **Pause**: Click the "Pause" button to pause the timer. The image carousel will also pause.
3. **Reset**: Click the "Reset" button to reset the timer to its initial state (work session of 25 minutes).
4. **Progress Bar**: Observe the progress bar at the top of the window to monitor session progress.
5. **Notifications**: Receive alerts when it’s time to switch between work and break periods.

## Customization

- **Timer Durations**: Modify the `work_time`, `short_break`, and `long_break` variables in the `PomodoroTimer` class to adjust the durations.
- **Images**: Replace the images in the `./Pomodoro Timer with GUI/images` directory with your own images. Ensure they are named `0.png`, `1.png`, ..., `10.png` and have the appropriate dimensions.
- **UI Appearance**: Customize fonts, colors, or layout by modifying the Tkinter widgets in the script.





Binary file added Pomodoro Timer with GUI/images/0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Pomodoro Timer with GUI/images/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Pomodoro Timer with GUI/images/2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Pomodoro Timer with GUI/images/3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Pomodoro Timer with GUI/images/4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Pomodoro Timer with GUI/images/5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Pomodoro Timer with GUI/images/6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Pomodoro Timer with GUI/images/7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Pomodoro Timer with GUI/images/8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Pomodoro Timer with GUI/images/9.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
229 changes: 229 additions & 0 deletions Pomodoro Timer with GUI/pomodoroTimerWithGUI.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
import tkinter as tk
from tkinter import messagebox
from PIL import Image, ImageTk
from tkinter import ttk
import time


class PomodoroTimer:
def __init__(self, root):
# Initialize the main window
self.root = root
self.root.title("Pomodoro Timer")

# Initialize time settings (in seconds)
self.work_time = 25 * 60 # Work time 25 minutes
self.short_break = 5 * 60 # Short break time 5 minutes
self.long_break = 15 * 60 # Long break time 15 minutes
self.current_time = self.work_time # Default to work time

self.is_running = False # Track if the timer is running
self.cycle_count = 0 # Track the count of work and rest cycles
self.work = True # Track if the timer is work-timer

# Create UI elements
self.label = tk.Label(
root, text="Pomodoro Timer", font=("Helvetica", 20)
) # Title label
self.label.pack(pady=10)

self.timer_label = tk.Label(
root, text=self.format_time(self.current_time), font=("Helvetica", 48)
) # Countdown label
self.timer_label.pack(pady=10)

# Use Frame container to manage button layout
progress_frame = tk.Frame(root)
progress_frame.pack(
side=tk.TOP, pady=10
) # Place the button container at the bottom of the window

# Create progress bar
self.progress = ttk.Progressbar(
progress_frame, orient="horizontal", length=300, mode="determinate"
)
self.progress.pack(side=tk.LEFT, pady=5, padx=20)
self.progress["maximum"] = (
100 # Set the maximum value of the progress bar to 100
)

# adjust the location of progress
empty_image = ImageTk.PhotoImage(
Image.open("C:/Users/Ming/Desktop/empty.png").resize((300, 9))
)
empty_image_label = tk.Label(progress_frame, image=empty_image)
empty_image_label.pack(pady=0, padx=10)

# Use Frame container to manage button layout
button_frame = tk.Frame(root)
button_frame.pack(
side=tk.BOTTOM, pady=10
) # Place the button container at the bottom of the window
button_width = 20

self.start_button = tk.Button(
button_frame,
text="Start",
font=("Helvetica", 14),
width=button_width,
command=self.start_timer,
)
self.start_button.pack(side=tk.LEFT, padx=5)

self.pause_button = tk.Button(
button_frame,
text="Pause",
font=("Helvetica", 14),
width=button_width,
command=self.pause_timer,
)
self.pause_button.pack(side=tk.LEFT, padx=5)

self.reset_button = tk.Button(
button_frame,
text="Reset",
font=("Helvetica", 14),
width=button_width,
command=self.reset_timer,
)
self.reset_button.pack(side=tk.LEFT, padx=5)

# Use Frame's pack attribute to center the button container
button_frame.pack(anchor="center")

self.update_timer() # Start updating the timer

self.current_image_index = 0 # set current image index
# input image
self.images = [
ImageTk.PhotoImage(
Image.open("./Pomodoro Timer with GUI/images/0.png").resize((864, 286))
),
ImageTk.PhotoImage(
Image.open("./Pomodoro Timer with GUI/images/1.png").resize((864, 286))
),
ImageTk.PhotoImage(
Image.open("./Pomodoro Timer with GUI/images/2.png").resize((864, 286))
),
ImageTk.PhotoImage(
Image.open("./Pomodoro Timer with GUI/images/3.png").resize((864, 286))
),
ImageTk.PhotoImage(
Image.open("./Pomodoro Timer with GUI/images/4.png").resize((864, 286))
),
ImageTk.PhotoImage(
Image.open("./Pomodoro Timer with GUI/images/5.png").resize((864, 286))
),
ImageTk.PhotoImage(
Image.open("./Pomodoro Timer with GUI/images/6.png").resize((864, 286))
),
ImageTk.PhotoImage(
Image.open("./Pomodoro Timer with GUI/images/7.png").resize((864, 286))
),
ImageTk.PhotoImage(
Image.open("./Pomodoro Timer with GUI/images/8.png").resize((864, 286))
),
ImageTk.PhotoImage(
Image.open("./Pomodoro Timer with GUI/images/9.png").resize((864, 286))
),
# ImageTk.PhotoImage(
# Image.open("C:/Users/Ming/Desktop/10.png").resize((864, 286))
# ),
]

self.image_label = tk.Label(root, image=self.images[self.current_image_index])
self.image_label.pack(pady=0, anchor="center")

def change_image(self): # Image switch function
if self.is_running:
# Update the current image index
self.current_image_index = (self.current_image_index + 1) % len(self.images)
# Update the image in the Label control
self.image_label.config(image=self.images[self.current_image_index])
# Switch to the next image after 100 milliseconds
self.root.after(100, self.change_image)

def format_time(self, seconds):
# Format the number of seconds into MM:SS format
mins = seconds // 60 # Number of minutes
secs = seconds % 60 # Number of seconds
return f"{mins:02}:{secs:02}"

def update_timer(self):
# Timer update logic
if self.is_running and self.current_time > 0:
self.current_time -= 1 # Decrease by 1 second every second
self.timer_label.config(
text=self.format_time(self.current_time)
) # Update the countdown display
if self.work:
self.update_progress() # Update the progress bar
self.root.after(1000, self.update_timer) # Call itself once a second
elif self.current_time == 0:
# Handling logic after the timer ends
self.is_running = False
self.cycle_count += 1 # Increase cycle count
self.notify_user() # Notify the user of the next step

def update_progress(self):
# Update the progress bar
progress_value = (self.current_time / self.work_time) * 100
self.progress["value"] = progress_value

def notify_user(self):
# Notify the user to enter different states based on cycle count
if self.work: # i
self.work = False
if self.cycle_count % 8 == 0: # Enter long rest every 8 cycles
self.current_time = self.long_break
messagebox.showinfo(
"Pomodoro Timer", "You did it. Time for a long break!"
)
else: # Otherwise, enter short rest
self.current_time = self.short_break
messagebox.showinfo("Pomodoro Timer", "You did it. Take a break!")
else:
self.work = True
self.current_time = self.work_time
messagebox.showinfo("Pomodoro Timer", "Time to fight!!!")

self.timer_label.config(
text=self.format_time(self.current_time)
) # Update display to new timing time

def start_timer(self):
# Start the timer
if not self.is_running: # If the timer is not running
self.is_running = True
self.update_timer() # Start the countdown
if self.work:
self.change_image()

def pause_timer(self):
# Pause the timer
self.is_running = False
self.current_image_index = 0
self.image_label.config(image=self.images[self.current_image_index])
messagebox.showinfo(
"Pomodoro Timer",
"PAUSE!!!\n But Charmeleon is still waiting your command!!!",
)

def reset_timer(self):
# Reset the timer to its initial state
self.is_running = False
self.current_time = self.work_time # Reset to work time
self.current_image_index = 0
self.image_label.config(image=self.images[self.current_image_index])
self.cycle_count = 0 # Reset cycle count
self.timer_label.config(
text=self.format_time(self.current_time)
) # Update display
self.progress["value"] = 0 # Reset progress bar
self.work = True


if __name__ == "__main__":
root = tk.Tk() # Create the main window
app = PomodoroTimer(root) # Initialize the Pomodoro Timer app
root.mainloop() # Start the main loop