mini clock tool
This commit is contained in:
+29
@@ -0,0 +1,29 @@
|
||||
### IntelliJ IDEA ###
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
<component name="ArtifactManager">
|
||||
<artifact type="jar" name="WatchTheClock:jar">
|
||||
<output-path>$PROJECT_DIR$/out/artifacts/WatchTheClock_jar</output-path>
|
||||
<root id="archive" name="WatchTheClock.jar">
|
||||
<element id="module-output" name="WatchTheClock" />
|
||||
</root>
|
||||
</artifact>
|
||||
</component>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/WatchTheClock.iml" filepath="$PROJECT_DIR$/WatchTheClock.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
Main-Class: Main
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,131 @@
|
||||
import javax.sound.sampled.*;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
public class AlarmLogic {
|
||||
private JTextField hoursField;
|
||||
private JTextField minutesField;
|
||||
private JButton activateButton;
|
||||
private JCheckBox soundCheckbox;
|
||||
private Timer timer;
|
||||
private boolean isActive;
|
||||
private Clip alertSound;
|
||||
|
||||
public AlarmLogic(JTextField hours, JTextField minutes,
|
||||
JButton activateBtn, JCheckBox soundCb) {
|
||||
this.hoursField = hours;
|
||||
this.minutesField = minutes;
|
||||
this.activateButton = activateBtn;
|
||||
this.soundCheckbox = soundCb;
|
||||
this.isActive = false;
|
||||
|
||||
// Sound laden
|
||||
try {
|
||||
AudioInputStream audioStream = AudioSystem.getAudioInputStream(
|
||||
getClass().getResource("/alert.wav"));
|
||||
alertSound = AudioSystem.getClip();
|
||||
alertSound.open(audioStream);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Timer für Überprüfung jede Sekunde
|
||||
timer = new Timer(1000, e -> checkAlarm());
|
||||
}
|
||||
|
||||
public void toggleActivation() {
|
||||
if (!isActive) {
|
||||
// Überprüfe Eingaben
|
||||
try {
|
||||
int hours = Integer.parseInt(hoursField.getText());
|
||||
int minutes = Integer.parseInt(minutesField.getText());
|
||||
|
||||
if (hours >= 0 && hours <= 23 && minutes >= 0 && minutes <= 59) {
|
||||
isActive = true;
|
||||
activateButton.setText("Deactivate");
|
||||
activateButton.setBackground(new Color(244, 67, 54));
|
||||
setFieldsEditable(false);
|
||||
timer.start();
|
||||
} else {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
"Bitte gültige Zeit eingeben!\nStunden: 0-23\nMinuten: 0-59",
|
||||
"Ungültige Zeit",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
} catch (NumberFormatException ex) {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
"Bitte nur Zahlen eingeben!",
|
||||
"Ungültige Eingabe",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
} else {
|
||||
deactivateAlarm();
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAlarm() {
|
||||
LocalTime now = LocalTime.now();
|
||||
int currentHour = now.getHour();
|
||||
int currentMinute = now.getMinute();
|
||||
|
||||
int targetHour = Integer.parseInt(hoursField.getText());
|
||||
int targetMinute = Integer.parseInt(minutesField.getText());
|
||||
|
||||
if (currentHour == targetHour && currentMinute == targetMinute) {
|
||||
// Alarm auslösen
|
||||
if (soundCheckbox.isSelected() && alertSound != null) {
|
||||
alertSound.loop(Clip.LOOP_CONTINUOUSLY);
|
||||
}
|
||||
|
||||
String currentTime = now.format(DateTimeFormatter.ofPattern("HH:mm"));
|
||||
Object[] options = {"OK", "+5 min"};
|
||||
int choice = JOptionPane.showOptionDialog(null,
|
||||
"Es ist " + currentTime + "!",
|
||||
"Alarm",
|
||||
JOptionPane.DEFAULT_OPTION,
|
||||
JOptionPane.INFORMATION_MESSAGE,
|
||||
null,
|
||||
options,
|
||||
options[0]);
|
||||
|
||||
if (choice == 0) { // OK
|
||||
deactivateAlarm();
|
||||
} else if (choice == 1) { // +5 min
|
||||
if (alertSound != null) {
|
||||
alertSound.stop();
|
||||
alertSound.setFramePosition(0);
|
||||
}
|
||||
|
||||
// Neue Alarmzeit berechnen (+5 Minuten)
|
||||
LocalTime newAlarmTime = LocalTime.of(targetHour, targetMinute).plusMinutes(5);
|
||||
hoursField.setText(String.valueOf(newAlarmTime.getHour()));
|
||||
minutesField.setText(String.format("%02d", newAlarmTime.getMinute()));
|
||||
|
||||
// Zeige neue Alarmzeit an
|
||||
JOptionPane.showMessageDialog(null,
|
||||
"Neuer Alarm um " + newAlarmTime.format(DateTimeFormatter.ofPattern("HH:mm")),
|
||||
"Schlummerfunktion",
|
||||
JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void deactivateAlarm() {
|
||||
isActive = false;
|
||||
timer.stop();
|
||||
if (alertSound != null) {
|
||||
alertSound.stop();
|
||||
alertSound.setFramePosition(0);
|
||||
}
|
||||
activateButton.setText("Activate");
|
||||
activateButton.setBackground(new Color(76, 175, 80));
|
||||
setFieldsEditable(true);
|
||||
}
|
||||
|
||||
private void setFieldsEditable(boolean editable) {
|
||||
hoursField.setEditable(editable);
|
||||
minutesField.setEditable(editable);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
import javax.swing.*;
|
||||
import javax.sound.sampled.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class CountdownLogic {
|
||||
private JTextField hoursField;
|
||||
private JTextField minutesField;
|
||||
private JTextField secondsField;
|
||||
private JButton startButton;
|
||||
private JCheckBox soundCheckbox;
|
||||
private Timer timer;
|
||||
private long remainingTime;
|
||||
private boolean isRunning;
|
||||
private Clip alertSound;
|
||||
|
||||
public CountdownLogic(JTextField hours, JTextField minutes, JTextField seconds,
|
||||
JButton startBtn, JCheckBox soundCb) {
|
||||
this.hoursField = hours;
|
||||
this.minutesField = minutes;
|
||||
this.secondsField = seconds;
|
||||
this.startButton = startBtn;
|
||||
this.soundCheckbox = soundCb;
|
||||
this.isRunning = false;
|
||||
|
||||
// Sound laden
|
||||
try {
|
||||
AudioInputStream audioStream = AudioSystem.getAudioInputStream(
|
||||
getClass().getResource("/alert.wav"));
|
||||
alertSound = AudioSystem.getClip();
|
||||
alertSound.open(audioStream);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
timer = new Timer(1000, e -> updateCountdown());
|
||||
}
|
||||
|
||||
public void toggleStartStop() {
|
||||
if (!isRunning) {
|
||||
// Startzeit berechnen
|
||||
long hours = Long.parseLong(hoursField.getText());
|
||||
long minutes = Long.parseLong(minutesField.getText());
|
||||
long seconds = Long.parseLong(secondsField.getText());
|
||||
|
||||
remainingTime = hours * 3600 + minutes * 60 + seconds;
|
||||
|
||||
if (remainingTime > 0) {
|
||||
isRunning = true;
|
||||
startButton.setText("Pause");
|
||||
startButton.setBackground(new Color(255, 152, 0));
|
||||
timer.start();
|
||||
setFieldsEditable(false);
|
||||
}
|
||||
} else {
|
||||
isRunning = false;
|
||||
startButton.setText("Start");
|
||||
startButton.setBackground(new Color(76, 175, 80));
|
||||
timer.stop();
|
||||
setFieldsEditable(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCountdown() {
|
||||
if (remainingTime > 0) {
|
||||
remainingTime--;
|
||||
updateDisplay();
|
||||
} else {
|
||||
timer.stop();
|
||||
isRunning = false;
|
||||
startButton.setText("Start");
|
||||
startButton.setBackground(new Color(76, 175, 80));
|
||||
setFieldsEditable(true);
|
||||
|
||||
// Sound in Schleife starten wenn aktiviert
|
||||
if (soundCheckbox.isSelected() && alertSound != null) {
|
||||
alertSound.loop(Clip.LOOP_CONTINUOUSLY);
|
||||
}
|
||||
|
||||
// Benachrichtigung anzeigen und danach Sound stoppen
|
||||
JOptionPane.showMessageDialog(null,
|
||||
"Countdown beendet!",
|
||||
"Zeit abgelaufen",
|
||||
JOptionPane.INFORMATION_MESSAGE);
|
||||
|
||||
// Sound stoppen nach OK-Klick
|
||||
if (alertSound != null) {
|
||||
alertSound.stop();
|
||||
alertSound.setFramePosition(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateDisplay() {
|
||||
long hours = remainingTime / 3600;
|
||||
long minutes = (remainingTime % 3600) / 60;
|
||||
long seconds = remainingTime % 60;
|
||||
|
||||
hoursField.setText(String.valueOf(hours));
|
||||
minutesField.setText(String.format("%02d", minutes));
|
||||
secondsField.setText(String.format("%02d", seconds));
|
||||
}
|
||||
|
||||
private void setFieldsEditable(boolean editable) {
|
||||
hoursField.setEditable(editable);
|
||||
minutesField.setEditable(editable);
|
||||
secondsField.setEditable(editable);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
timer.stop();
|
||||
isRunning = false;
|
||||
startButton.setText("Start");
|
||||
startButton.setBackground(new Color(76, 175, 80));
|
||||
hoursField.setText("0");
|
||||
minutesField.setText("0");
|
||||
secondsField.setText("0");
|
||||
setFieldsEditable(true);
|
||||
}
|
||||
}
|
||||
+471
@@ -0,0 +1,471 @@
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.text.AttributeSet;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.DocumentFilter;
|
||||
import javax.swing.text.AbstractDocument;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import java.awt.Desktop;
|
||||
|
||||
public class Main {
|
||||
private static JFrame frame;
|
||||
private static String baseTitle = "WatchTheClock";
|
||||
private static String currentTitle = "";
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Setze den Anwendungsnamen für Windows
|
||||
System.setProperty("sun.java.command", baseTitle);
|
||||
|
||||
frame = new JFrame(baseTitle);
|
||||
|
||||
// Icon setzen
|
||||
try {
|
||||
Image icon = new ImageIcon(Main.class.getResource("/clock.png")).getImage();
|
||||
frame.setIconImage(icon);
|
||||
} catch (Exception e) {
|
||||
System.err.println("Icon konnte nicht geladen werden: " + e.getMessage());
|
||||
}
|
||||
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
frame.setSize(450, 300);
|
||||
frame.setMinimumSize(new Dimension(400, 280));
|
||||
frame.setLocationRelativeTo(null);
|
||||
|
||||
// Erstellt JTabbedPane für die verschiedenen Funktionen
|
||||
JTabbedPane tabbedPane = new JTabbedPane();
|
||||
frame.add(tabbedPane);
|
||||
|
||||
// Fügt die Tabs hinzu
|
||||
tabbedPane.addTab("Stopwatch", createStopwatchPanel());
|
||||
tabbedPane.addTab("Countdown", createCountdownPanel());
|
||||
tabbedPane.addTab("Alarm", createAlarmPanel());
|
||||
tabbedPane.addTab("Notes", createNotesPanel());
|
||||
tabbedPane.addTab("ToDo", createTodoPanel());
|
||||
|
||||
// Menüleiste erstellen
|
||||
JMenuBar menuBar = new JMenuBar();
|
||||
JMenu settingsMenu = new JMenu("⚙");
|
||||
JMenu helpMenu = new JMenu("?");
|
||||
|
||||
// Settings-Menü Items
|
||||
JCheckBoxMenuItem alwaysOnTopItem = new JCheckBoxMenuItem("Always on Top");
|
||||
alwaysOnTopItem.addActionListener(e -> frame.setAlwaysOnTop(alwaysOnTopItem.isSelected()));
|
||||
settingsMenu.add(alwaysOnTopItem);
|
||||
|
||||
// Titel-Menüpunkt
|
||||
JMenuItem titleItem = new JMenuItem("Titel ändern");
|
||||
titleItem.addActionListener(e -> changeTitleDialog());
|
||||
settingsMenu.add(titleItem);
|
||||
|
||||
// Info-Menüpunkt
|
||||
JMenuItem aboutItem = new JMenuItem("About");
|
||||
aboutItem.addActionListener(e -> {
|
||||
JEditorPane editorPane = new JEditorPane("text/html",
|
||||
"<html><div style='font-family: Arial; font-size: 10px;'>" +
|
||||
"WatchTheClock v0.1<br><br>" +
|
||||
"This tool is free to use and portable!<br><br>" +
|
||||
"Made by Jordan Henézi<br><br>" +
|
||||
"Last time updated: 08.01.2025<br><br>" +
|
||||
"Website: <a href='https://henezi.de'>henezi.de</a><br>" +
|
||||
"Support: watchtheclock@henezi.de<br><br>" +
|
||||
"Copyright © 2025" +
|
||||
"</div></html>");
|
||||
|
||||
editorPane.setEditable(false);
|
||||
editorPane.setBackground(new JLabel().getBackground());
|
||||
|
||||
// Links klickbar machen
|
||||
editorPane.addHyperlinkListener(event -> {
|
||||
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
try {
|
||||
String url = event.getURL().toString();
|
||||
if (!url.startsWith("mailto:")) {
|
||||
Desktop.getDesktop().browse(event.getURL().toURI());
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
JOptionPane.showMessageDialog(frame,
|
||||
editorPane,
|
||||
"About WatchTheClock",
|
||||
JOptionPane.INFORMATION_MESSAGE);
|
||||
});
|
||||
helpMenu.add(aboutItem);
|
||||
|
||||
menuBar.add(settingsMenu);
|
||||
menuBar.add(helpMenu);
|
||||
frame.setJMenuBar(menuBar);
|
||||
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
private static JPanel createStopwatchPanel() {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
|
||||
// Zeitanzeige mit mehr Platz
|
||||
JLabel timeLabel = new JLabel("00:00:00");
|
||||
timeLabel.setFont(new Font("Arial", Font.BOLD, 72));
|
||||
timeLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
|
||||
// Extra Panel für die Zeitanzeige mit weniger Padding oben
|
||||
JPanel timeLabelPanel = new JPanel(new BorderLayout());
|
||||
timeLabelPanel.add(timeLabel, BorderLayout.CENTER);
|
||||
timeLabelPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 20, 0)); // Reduziertes Top-Padding
|
||||
panel.add(timeLabelPanel, BorderLayout.CENTER);
|
||||
|
||||
// Buttons Panel
|
||||
JPanel buttonPanel = new JPanel(new FlowLayout());
|
||||
JButton startButton = new JButton("Start");
|
||||
JButton resetButton = new JButton("Reset");
|
||||
startButton.setBackground(new Color(76, 175, 80));
|
||||
resetButton.setBackground(new Color(244, 67, 54));
|
||||
buttonPanel.add(startButton);
|
||||
buttonPanel.add(resetButton);
|
||||
panel.add(buttonPanel, BorderLayout.SOUTH);
|
||||
|
||||
// Timeline Panel mit angepasster Größe
|
||||
JPanel timelinePanel = new JPanel();
|
||||
timelinePanel.setLayout(null);
|
||||
|
||||
JScrollPane scrollPane = new JScrollPane(timelinePanel,
|
||||
JScrollPane.VERTICAL_SCROLLBAR_NEVER,
|
||||
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
scrollPane.setBorder(BorderFactory.createTitledBorder("Timeline"));
|
||||
scrollPane.setPreferredSize(new Dimension(430, 85)); // Breite und Höhe angepasst
|
||||
|
||||
// Mausrad-Scrolling
|
||||
timelinePanel.addMouseWheelListener(e -> {
|
||||
JScrollBar horizontalBar = scrollPane.getHorizontalScrollBar();
|
||||
int delta = e.getWheelRotation() * 50; // Scroll-Geschwindigkeit
|
||||
int newValue = horizontalBar.getValue() + delta;
|
||||
newValue = Math.max(0, Math.min(newValue, horizontalBar.getMaximum()));
|
||||
horizontalBar.setValue(newValue);
|
||||
});
|
||||
|
||||
// Fügt den MouseWheelListener auch zum ScrollPane hinzu
|
||||
scrollPane.addMouseWheelListener(e -> {
|
||||
JScrollBar horizontalBar = scrollPane.getHorizontalScrollBar();
|
||||
int delta = e.getWheelRotation() * 50;
|
||||
int newValue = horizontalBar.getValue() + delta;
|
||||
newValue = Math.max(0, Math.min(newValue, horizontalBar.getMaximum()));
|
||||
horizontalBar.setValue(newValue);
|
||||
});
|
||||
|
||||
panel.add(scrollPane, BorderLayout.NORTH);
|
||||
|
||||
// Stopwatch Logik
|
||||
StopwatchLogic stopwatch = new StopwatchLogic(timeLabel, timelinePanel, startButton);
|
||||
startButton.addActionListener(e -> stopwatch.toggleStartStop());
|
||||
resetButton.addActionListener(e -> stopwatch.reset());
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private static JPanel createCountdownPanel() {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
// Zeit-Eingabe Panel
|
||||
JPanel inputPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 0));
|
||||
|
||||
// Stunden Input
|
||||
JPanel hoursPanel = new JPanel(new BorderLayout());
|
||||
JLabel hoursLabel = new JLabel("Hours", SwingConstants.CENTER);
|
||||
JTextField hoursField = new JTextField("0", 3);
|
||||
hoursField.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
hoursField.setFont(new Font("Arial", Font.BOLD, 24));
|
||||
hoursPanel.add(hoursLabel, BorderLayout.NORTH);
|
||||
hoursPanel.add(hoursField, BorderLayout.CENTER);
|
||||
|
||||
// Minuten Input
|
||||
JPanel minutesPanel = new JPanel(new BorderLayout());
|
||||
JLabel minutesLabel = new JLabel("Minutes", SwingConstants.CENTER);
|
||||
JTextField minutesField = new JTextField("0", 3);
|
||||
minutesField.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
minutesField.setFont(new Font("Arial", Font.BOLD, 24));
|
||||
minutesPanel.add(minutesLabel, BorderLayout.NORTH);
|
||||
minutesPanel.add(minutesField, BorderLayout.CENTER);
|
||||
|
||||
// Sekunden Input
|
||||
JPanel secondsPanel = new JPanel(new BorderLayout());
|
||||
JLabel secondsLabel = new JLabel("Seconds", SwingConstants.CENTER);
|
||||
JTextField secondsField = new JTextField("0", 3);
|
||||
secondsField.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
secondsField.setFont(new Font("Arial", Font.BOLD, 24));
|
||||
secondsPanel.add(secondsLabel, BorderLayout.NORTH);
|
||||
secondsPanel.add(secondsField, BorderLayout.CENTER);
|
||||
|
||||
// Trennpunkte zwischen den Feldern
|
||||
JLabel separator1 = new JLabel(":", SwingConstants.CENTER);
|
||||
JLabel separator2 = new JLabel(":", SwingConstants.CENTER);
|
||||
separator1.setFont(new Font("Arial", Font.BOLD, 24));
|
||||
separator2.setFont(new Font("Arial", Font.BOLD, 24));
|
||||
|
||||
inputPanel.add(hoursPanel);
|
||||
inputPanel.add(separator1);
|
||||
inputPanel.add(minutesPanel);
|
||||
inputPanel.add(separator2);
|
||||
inputPanel.add(secondsPanel);
|
||||
|
||||
// Control Panel
|
||||
JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
|
||||
|
||||
// Start Button
|
||||
JButton startButton = new JButton("Start");
|
||||
startButton.setBackground(new Color(76, 175, 80));
|
||||
startButton.setPreferredSize(new Dimension(100, 35));
|
||||
|
||||
// Reset Button
|
||||
JButton resetButton = new JButton("Reset");
|
||||
resetButton.setBackground(new Color(244, 67, 54));
|
||||
resetButton.setPreferredSize(new Dimension(100, 35));
|
||||
|
||||
// Sound Checkbox
|
||||
JCheckBox soundCheckbox = new JCheckBox("Play sound");
|
||||
soundCheckbox.setSelected(true);
|
||||
|
||||
controlPanel.add(startButton);
|
||||
controlPanel.add(resetButton);
|
||||
controlPanel.add(soundCheckbox);
|
||||
|
||||
panel.add(inputPanel, BorderLayout.CENTER);
|
||||
panel.add(controlPanel, BorderLayout.SOUTH);
|
||||
|
||||
// Nur Zahlen in den Textfeldern erlauben
|
||||
DocumentFilter numberFilter = new DocumentFilter() {
|
||||
@Override
|
||||
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
|
||||
if (string.matches("\\d*")) {
|
||||
super.insertString(fb, offset, string, attr);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
|
||||
if (text.matches("\\d*")) {
|
||||
super.replace(fb, offset, length, text, attrs);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// FocusListener für automatische Null
|
||||
FocusAdapter focusAdapter = new FocusAdapter() {
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
JTextField field = (JTextField) e.getComponent();
|
||||
if (field.getText().trim().isEmpty()) {
|
||||
field.setText("0");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Anwenden auf alle Felder
|
||||
hoursField.addFocusListener(focusAdapter);
|
||||
minutesField.addFocusListener(focusAdapter);
|
||||
secondsField.addFocusListener(focusAdapter);
|
||||
|
||||
((AbstractDocument) hoursField.getDocument()).setDocumentFilter(numberFilter);
|
||||
((AbstractDocument) minutesField.getDocument()).setDocumentFilter(numberFilter);
|
||||
((AbstractDocument) secondsField.getDocument()).setDocumentFilter(numberFilter);
|
||||
|
||||
// Countdown Logik
|
||||
CountdownLogic countdown = new CountdownLogic(hoursField, minutesField, secondsField,
|
||||
startButton, soundCheckbox);
|
||||
startButton.addActionListener(e -> countdown.toggleStartStop());
|
||||
resetButton.addActionListener(e -> countdown.reset());
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private static JPanel createAlarmPanel() {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
// Zeit-Eingabe Panel
|
||||
JPanel inputPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 0));
|
||||
|
||||
// Stunden Input
|
||||
JPanel hoursPanel = new JPanel(new BorderLayout());
|
||||
JLabel hoursLabel = new JLabel("Hours", SwingConstants.CENTER);
|
||||
JTextField hoursField = new JTextField("0", 3);
|
||||
hoursField.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
hoursField.setFont(new Font("Arial", Font.BOLD, 24));
|
||||
hoursPanel.add(hoursLabel, BorderLayout.NORTH);
|
||||
hoursPanel.add(hoursField, BorderLayout.CENTER);
|
||||
|
||||
// Minuten Input
|
||||
JPanel minutesPanel = new JPanel(new BorderLayout());
|
||||
JLabel minutesLabel = new JLabel("Minutes", SwingConstants.CENTER);
|
||||
JTextField minutesField = new JTextField("0", 3);
|
||||
minutesField.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
minutesField.setFont(new Font("Arial", Font.BOLD, 24));
|
||||
minutesPanel.add(minutesLabel, BorderLayout.NORTH);
|
||||
minutesPanel.add(minutesField, BorderLayout.CENTER);
|
||||
|
||||
// Trennpunkte
|
||||
JLabel separator = new JLabel(":", SwingConstants.CENTER);
|
||||
separator.setFont(new Font("Arial", Font.BOLD, 24));
|
||||
|
||||
inputPanel.add(hoursPanel);
|
||||
inputPanel.add(separator);
|
||||
inputPanel.add(minutesPanel);
|
||||
|
||||
// Control Panel
|
||||
JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
|
||||
|
||||
JButton activateButton = new JButton("Activate");
|
||||
activateButton.setBackground(new Color(76, 175, 80));
|
||||
activateButton.setPreferredSize(new Dimension(100, 35));
|
||||
|
||||
JCheckBox soundCheckbox = new JCheckBox("Play sound");
|
||||
soundCheckbox.setSelected(true);
|
||||
|
||||
controlPanel.add(activateButton);
|
||||
controlPanel.add(soundCheckbox);
|
||||
|
||||
panel.add(inputPanel, BorderLayout.CENTER);
|
||||
panel.add(controlPanel, BorderLayout.SOUTH);
|
||||
|
||||
// Nur Zahlen in den Textfeldern erlauben
|
||||
DocumentFilter numberFilter = new DocumentFilter() {
|
||||
@Override
|
||||
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
|
||||
if (string.matches("\\d*")) {
|
||||
super.insertString(fb, offset, string, attr);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
|
||||
if (text.matches("\\d*")) {
|
||||
super.replace(fb, offset, length, text, attrs);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
((AbstractDocument) hoursField.getDocument()).setDocumentFilter(numberFilter);
|
||||
((AbstractDocument) minutesField.getDocument()).setDocumentFilter(numberFilter);
|
||||
|
||||
// Alarm Logik
|
||||
AlarmLogic alarm = new AlarmLogic(hoursField, minutesField, activateButton, soundCheckbox);
|
||||
activateButton.addActionListener(e -> alarm.toggleActivation());
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private static JPanel createNotesPanel() {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||
|
||||
// Erstellt das Textfeld
|
||||
JTextArea notesArea = new JTextArea();
|
||||
notesArea.setLineWrap(true);
|
||||
notesArea.setWrapStyleWord(true);
|
||||
notesArea.setFont(new Font("Arial", Font.PLAIN, 12));
|
||||
|
||||
// Fügt Scrollbalken hinzu
|
||||
JScrollPane scrollPane = new JScrollPane(notesArea);
|
||||
|
||||
panel.add(scrollPane, BorderLayout.CENTER);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private static JPanel createTodoPanel() {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
|
||||
|
||||
// ToDo Liste
|
||||
DefaultListModel<JCheckBox> todoListModel = new DefaultListModel<>();
|
||||
JList<JCheckBox> todoList = new JList<>(todoListModel);
|
||||
todoList.setCellRenderer(new CheckboxListCellRenderer());
|
||||
todoList.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
int index = todoList.locationToIndex(e.getPoint());
|
||||
if (index >= 0) {
|
||||
JCheckBox cb = todoListModel.getElementAt(index);
|
||||
cb.setSelected(!cb.isSelected());
|
||||
todoList.repaint();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Input Panel für neue ToDos
|
||||
JPanel inputPanel = new JPanel(new BorderLayout());
|
||||
JTextField todoInput = new JTextField();
|
||||
JButton addButton = new JButton("Add");
|
||||
addButton.setPreferredSize(new Dimension(60, 25));
|
||||
|
||||
// Optional: Tooltip hinzufügen
|
||||
addButton.setToolTipText("Add new todo item");
|
||||
|
||||
// Button zum Hinzufügen neuer ToDos
|
||||
ActionListener addTodo = e -> {
|
||||
String text = todoInput.getText().trim();
|
||||
if (!text.isEmpty()) {
|
||||
JCheckBox newTodo = new JCheckBox(text);
|
||||
todoListModel.addElement(newTodo);
|
||||
todoInput.setText("");
|
||||
}
|
||||
};
|
||||
|
||||
addButton.addActionListener(addTodo);
|
||||
todoInput.addActionListener(addTodo); // Erlaubt Enter-Taste
|
||||
|
||||
inputPanel.add(todoInput, BorderLayout.CENTER);
|
||||
inputPanel.add(addButton, BorderLayout.EAST);
|
||||
|
||||
// Button zum Entfernen erledigter ToDos
|
||||
JButton clearButton = new JButton("Clear completed");
|
||||
clearButton.addActionListener(e -> {
|
||||
for (int i = todoListModel.size() - 1; i >= 0; i--) {
|
||||
if (todoListModel.getElementAt(i).isSelected()) {
|
||||
todoListModel.removeElementAt(i);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Layout zusammensetzen
|
||||
panel.add(new JScrollPane(todoList), BorderLayout.CENTER);
|
||||
panel.add(inputPanel, BorderLayout.NORTH);
|
||||
panel.add(clearButton, BorderLayout.SOUTH);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
private static class CheckboxListCellRenderer extends JCheckBox implements ListCellRenderer<JCheckBox> {
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList<? extends JCheckBox> list, JCheckBox value,
|
||||
int index, boolean isSelected, boolean cellHasFocus) {
|
||||
setSelected(value.isSelected());
|
||||
setText(value.getText());
|
||||
setBackground(isSelected ? list.getSelectionBackground() : list.getBackground());
|
||||
setForeground(isSelected ? list.getSelectionForeground() : list.getForeground());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private static void changeTitleDialog() {
|
||||
String newTitle = JOptionPane.showInputDialog(frame,
|
||||
"Neuen Titel eingeben:",
|
||||
currentTitle);
|
||||
|
||||
if (newTitle != null) {
|
||||
currentTitle = newTitle.trim();
|
||||
updateWindowTitle();
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateWindowTitle() {
|
||||
if (currentTitle.isEmpty()) {
|
||||
frame.setTitle(baseTitle);
|
||||
} else {
|
||||
frame.setTitle(baseTitle + " - " + currentTitle);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
import javax.swing.*;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.awt.Color;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.awt.Font;
|
||||
import java.awt.Dimension;
|
||||
|
||||
public class StopwatchLogic {
|
||||
private JLabel timeLabel;
|
||||
private JPanel timelinePanel;
|
||||
private JButton startButton;
|
||||
private Timer timer;
|
||||
private long startTime;
|
||||
private long elapsedTime;
|
||||
private boolean isRunning;
|
||||
private List<TimeMarker> timeMarkers;
|
||||
|
||||
// Angepasste Konstanten für kompakteres Layout
|
||||
private static final int MIN_MARKER_DISTANCE = 70;
|
||||
private static final int START_X = 20;
|
||||
private static final int TIMELINE_HEIGHT = 65; // Reduziert von 75
|
||||
private static final int LINE_Y = 25; // Höher positioniert (war 30)
|
||||
private static final int ACTION_LABEL_Y = 3; // Höher positioniert (war 5)
|
||||
private static final int TIME_LABEL_Y = 40; // Höher positioniert (war 48)
|
||||
|
||||
public StopwatchLogic(JLabel timeLabel, JPanel timelinePanel, JButton startButton) {
|
||||
this.timeLabel = timeLabel;
|
||||
this.timelinePanel = timelinePanel;
|
||||
this.startButton = startButton;
|
||||
this.timeMarkers = new ArrayList<>();
|
||||
|
||||
timer = new Timer(10, e -> {
|
||||
if (isRunning) {
|
||||
elapsedTime = System.currentTimeMillis() - startTime;
|
||||
updateDisplay();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void toggleStartStop() {
|
||||
if (isRunning) {
|
||||
timer.stop();
|
||||
addTimeMarker("Pause");
|
||||
startButton.setText("Start");
|
||||
startButton.setBackground(new Color(76, 175, 80)); // Grün
|
||||
} else {
|
||||
if (elapsedTime == 0) {
|
||||
startTime = System.currentTimeMillis();
|
||||
addTimeMarker("Start");
|
||||
} else {
|
||||
startTime = System.currentTimeMillis() - elapsedTime;
|
||||
addTimeMarker("Resume");
|
||||
}
|
||||
timer.start();
|
||||
startButton.setText("Pause");
|
||||
startButton.setBackground(new Color(255, 152, 0)); // Orange
|
||||
}
|
||||
isRunning = !isRunning;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
timer.stop();
|
||||
isRunning = false;
|
||||
elapsedTime = 0;
|
||||
timeMarkers.clear();
|
||||
startButton.setText("Start");
|
||||
startButton.setBackground(new Color(76, 175, 80));
|
||||
updateDisplay();
|
||||
updateTimeline();
|
||||
}
|
||||
|
||||
private void updateDisplay() {
|
||||
long hours = (elapsedTime / 3600000);
|
||||
long minutes = (elapsedTime / 60000) % 60;
|
||||
long seconds = (elapsedTime / 1000) % 60;
|
||||
|
||||
timeLabel.setText(String.format("%02d:%02d:%02d", hours, minutes, seconds));
|
||||
}
|
||||
|
||||
private void addTimeMarker(String action) {
|
||||
TimeMarker marker = new TimeMarker(action, elapsedTime);
|
||||
timeMarkers.add(marker);
|
||||
updateTimeline();
|
||||
}
|
||||
|
||||
private void updateTimeline() {
|
||||
timelinePanel.removeAll();
|
||||
|
||||
int markerCount = timeMarkers.size();
|
||||
int minWidth = timelinePanel.getParent().getWidth() - 40;
|
||||
int requiredWidth = Math.max(minWidth, markerCount * MIN_MARKER_DISTANCE + 100);
|
||||
|
||||
int lastX = START_X;
|
||||
|
||||
for (int i = 0; i < timeMarkers.size(); i++) {
|
||||
TimeMarker currentMarker = timeMarkers.get(i);
|
||||
int x = START_X + (int)((currentMarker.time * (requiredWidth - 70)) / Math.max(elapsedTime, 1000));
|
||||
|
||||
if (x - lastX < MIN_MARKER_DISTANCE) {
|
||||
x = lastX + MIN_MARKER_DISTANCE;
|
||||
}
|
||||
|
||||
if (i % 2 == 0 && i < timeMarkers.size() - 1) {
|
||||
TimeMarker nextMarker = timeMarkers.get(i + 1);
|
||||
int nextX = START_X + (int)((nextMarker.time * (requiredWidth - 70)) / Math.max(elapsedTime, 1000));
|
||||
nextX = Math.max(nextX, x + MIN_MARKER_DISTANCE);
|
||||
|
||||
// Grüner Block
|
||||
JPanel timeBlock = new JPanel();
|
||||
timeBlock.setBackground(new Color(76, 175, 80, 50));
|
||||
timeBlock.setBounds(x, LINE_Y - 5, nextX - x, 10);
|
||||
timelinePanel.add(timeBlock);
|
||||
|
||||
// Dauer-Label
|
||||
long durationSeconds = (nextMarker.time - currentMarker.time) / 1000;
|
||||
String durationText = formatDurationDetailed(durationSeconds);
|
||||
JLabel durationLabel = new JLabel(durationText);
|
||||
durationLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
durationLabel.setFont(new Font("Arial", Font.PLAIN, 10));
|
||||
int labelWidth = 70;
|
||||
int labelX = x + (nextX - x) / 2 - labelWidth / 2;
|
||||
durationLabel.setBounds(labelX, LINE_Y + 5, labelWidth, 15);
|
||||
timelinePanel.add(durationLabel);
|
||||
}
|
||||
|
||||
// Aktion-Label (über der Linie)
|
||||
JLabel actionLabel = new JLabel(currentMarker.action);
|
||||
actionLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
actionLabel.setFont(new Font("Arial", Font.PLAIN, 11));
|
||||
actionLabel.setBounds(x - 30, ACTION_LABEL_Y, 60, 20);
|
||||
timelinePanel.add(actionLabel);
|
||||
|
||||
// Zeitstempel-Label (unter der Linie)
|
||||
JLabel timeLabel = new JLabel(currentMarker.getClockTime());
|
||||
timeLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
timeLabel.setFont(new Font("Arial", Font.PLAIN, 11));
|
||||
timeLabel.setBounds(x - 35, TIME_LABEL_Y, 70, 20);
|
||||
timelinePanel.add(timeLabel);
|
||||
|
||||
// Vertikaler Strich
|
||||
JPanel tick = new JPanel();
|
||||
tick.setBackground(Color.BLACK);
|
||||
tick.setBounds(x, LINE_Y - 5, 1, 10);
|
||||
timelinePanel.add(tick);
|
||||
|
||||
lastX = x;
|
||||
}
|
||||
|
||||
// Horizontale Linie
|
||||
JPanel line = new JPanel();
|
||||
line.setBackground(Color.GRAY);
|
||||
line.setBounds(START_X, LINE_Y, requiredWidth - 40, 1);
|
||||
timelinePanel.add(line);
|
||||
|
||||
timelinePanel.setPreferredSize(new Dimension(requiredWidth, TIMELINE_HEIGHT));
|
||||
timelinePanel.revalidate();
|
||||
timelinePanel.repaint();
|
||||
}
|
||||
|
||||
// Neue detaillierte Formatierungsmethode
|
||||
private String formatDurationDetailed(long seconds) {
|
||||
if (seconds >= 3600) {
|
||||
long hours = seconds / 3600;
|
||||
long minutes = (seconds % 3600) / 60;
|
||||
long secs = seconds % 60;
|
||||
if (minutes > 0 || secs > 0) {
|
||||
return String.format("%dh %02d:%02d", hours, minutes, secs);
|
||||
}
|
||||
return hours + "h";
|
||||
} else if (seconds >= 60) {
|
||||
long minutes = seconds / 60;
|
||||
long secs = seconds % 60;
|
||||
if (secs > 0) {
|
||||
return String.format("%d:%02dmin", minutes, secs);
|
||||
}
|
||||
return minutes + "min";
|
||||
} else {
|
||||
return seconds + "s";
|
||||
}
|
||||
}
|
||||
|
||||
private static class TimeMarker {
|
||||
private String action;
|
||||
private long time;
|
||||
private String clockTime;
|
||||
|
||||
public TimeMarker(String action, long time) {
|
||||
this.action = action;
|
||||
this.time = time;
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
|
||||
this.clockTime = sdf.format(new Date());
|
||||
}
|
||||
|
||||
public String getClockTime() {
|
||||
return clockTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user