From f2a9b8021e9607d09c8e28178fb3680cf6b96e81 Mon Sep 17 00:00:00 2001 From: Mobina Date: Fri, 29 May 2026 00:10:41 +0330 Subject: [PATCH] editon1 --- src/main/java/sbu/javafx/Main.java | 6 +- src/main/java/sbu/javafx/MusicApp.java | 33 ++++- src/main/java/sbu/javafx/MusicController.java | 124 ++++++++++++++---- src/main/resources/image/icon.png | Bin 0 -> 3791 bytes src/main/resources/sbu/javafx/App-view.fxml | 2 +- 5 files changed, 139 insertions(+), 26 deletions(-) create mode 100644 src/main/resources/image/icon.png diff --git a/src/main/java/sbu/javafx/Main.java b/src/main/java/sbu/javafx/Main.java index 8330187..bdbf4d9 100644 --- a/src/main/java/sbu/javafx/Main.java +++ b/src/main/java/sbu/javafx/Main.java @@ -4,6 +4,7 @@ import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; +import javafx.scene.image.Image; import javafx.stage.Stage; public class Main extends Application { @@ -19,7 +20,7 @@ public class Main extends Application { new Song("Blinding Lights", "The Weeknd","/musics/The-Weeknd-Blinding-Lights-128.mp3"), new Song("Comme des enfants", "Coert De Pirate","/musics/Coeur-De-Pirate-Comme-des-enfants-128.mp3"), new Song("Slow Down", "GRAE", "/musics/GRAE-Slow-Down-128.mp3"), - new Song("Cigarettes out the Window", "TV Girl", "/music/TV-Girl-Cigarettes-out-the-Window-128.mp3"), + new Song("Cigarettes out the Window", "TV Girl", "/musics/TV-Girl-Cigarettes-out-the-Window-128.mp3"), new Song("deja vu", "Olivia Rodirgo", "/musics/Olivia-Rodrigo-deja-vu-320.mp3"), new Song("The Line", "Twoenty One Pilots", "/musics/Twenty-One-Pilots-The-Line-128.mp3"), new Song("Bones", "Imagine Dragons", "/musics/Imagine-Dragons-Bones-128.mp3"), @@ -37,6 +38,9 @@ public class Main extends Application { primaryStage.setTitle("Music Player"); primaryStage.setScene(scene); + primaryStage.getIcons().add( + new Image(getClass().getResourceAsStream("/image/icon.png")) + ); primaryStage.setResizable(false); primaryStage.show(); } diff --git a/src/main/java/sbu/javafx/MusicApp.java b/src/main/java/sbu/javafx/MusicApp.java index a50badc..819aebe 100644 --- a/src/main/java/sbu/javafx/MusicApp.java +++ b/src/main/java/sbu/javafx/MusicApp.java @@ -2,7 +2,9 @@ package sbu.javafx; import javafx.application.Application; import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; import javafx.scene.Scene; +import javafx.scene.image.Image; import javafx.stage.Stage; import java.io.IOException; @@ -13,9 +15,38 @@ public class MusicApp extends Application { public void start(Stage stage) throws IOException { FXMLLoader fxmlLoader = new FXMLLoader(MusicApp.class.getResource("App-view.fxml")); - Scene scene = new Scene(fxmlLoader.load()); + Parent root = fxmlLoader.load(); + + MusicController controller = fxmlLoader.getController(); + + controller.musicsListView.getItems().addAll( + new Song("Blinding Lights", "The Weeknd","/musics/The-Weeknd-Blinding-Lights-128.mp3"), + new Song("Comme des enfants", "Coert De Pirate","/musics/Coeur-De-Pirate-Comme-des-enfants-128.mp3"), + new Song("Slow Down", "GRAE", "/musics/GRAE-Slow-Down-128.mp3"), + new Song("Cigarettes out the Window", "TV Girl", "/musics/TV-Girl-Cigarettes-out-the-Window-128.mp3"), + new Song("deja vu", "Olivia Rodirgo", "/musics/Olivia-Rodrigo-deja-vu-320.mp3"), + new Song("The Line", "Twoenty One Pilots", "/musics/Twenty-One-Pilots-The-Line-128.mp3"), + new Song("Bones", "Imagine Dragons", "/musics/Imagine-Dragons-Bones-128.mp3"), + new Song("Bunker", "Balthazar", "/musics/Balthazar-Bunker-128.mp3"), + new Song("As It Was", "Harry Styles", "/musics/Harry-Styles-As-It-Was-320.mp3") + ); + + controller.setupListView(controller.musicsListView); + controller.setupListView(controller.playlistListView); + + Scene scene = new Scene(root, 500, 600); + + scene.getStylesheets().add( + getClass().getResource("/css/dark.css").toExternalForm() + ); + stage.setTitle("Music Player"); + stage.getIcons().add( + new Image(getClass().getResourceAsStream("/image/icon.png")) + ); stage.setScene(scene); + stage.setResizable(false); + //TODO: add icon to the stage stage.show(); } diff --git a/src/main/java/sbu/javafx/MusicController.java b/src/main/java/sbu/javafx/MusicController.java index e2e24e2..a56a319 100644 --- a/src/main/java/sbu/javafx/MusicController.java +++ b/src/main/java/sbu/javafx/MusicController.java @@ -35,6 +35,12 @@ public class MusicController { @FXML Button themeToggleBtn; @FXML + Button nextBtn; + @FXML + Button preveBtn; + @FXML + Button repeatBtn; + @FXML private Label messageLabel; private boolean isDarkMode=true; private boolean isPlaying=false; @@ -76,6 +82,46 @@ public class MusicController { playPauseBtn.setGraphic(playIcon); + nextBtn.setOnAction(e ->{ + + player.pause(); + + if(isOpen) { + currentSong=playlistListView.getItems().get(findIndex(playlistListView,currentSong)+1); + setPlayer(currentSong).play(); + }else{ + currentSong=musicsListView.getItems().get(findIndex(musicsListView,currentSong)+1); + setPlayer(currentSong).play(); + } + }); + + preveBtn.setOnAction(e ->{ + + player.pause(); + + if(isOpen) { + currentSong=playlistListView.getItems().get(findIndex(playlistListView,currentSong)-1); + setPlayer(currentSong).play(); + }else{ + currentSong=musicsListView.getItems().get(findIndex(musicsListView,currentSong)-1); + setPlayer(currentSong).play(); + } + }); + + repeatBtn.setOnAction(e->{ + if(!isRepeat){ + repeatBtn.setStyle( + "-fx-border-color: blue;" + + "-fx-border-width: 2px;" + + "-fx-border-radius: 100em;" + ); + isRepeat=true; + }else{ + repeatBtn.setStyle("-fx-border-color: transparent;"); + isRepeat=false; + } + }); + } public void setupListView(ListView listView) { @@ -131,11 +177,11 @@ public class MusicController { @FXML public void toggleTheme(ActionEvent event) { if (isDarkMode) { - themeToggleBtn.setText("Light"); + themeToggleBtn.setText("Dark"); changeTheme(); isDarkMode = false; } else { - themeToggleBtn.setText("Dark"); + themeToggleBtn.setText("Light"); changeTheme(); isDarkMode = true; } @@ -162,42 +208,64 @@ public class MusicController { //TODO: Implement the logic to play a song. This method should update the UI to show which song is currently playing. - @FXML - public void handlePlayAction() { - //Update labels, change button icons, etc. - } + public MediaPlayer setPlayer(Song song) {//این تابع برای ست کردن مدیای در حال پخشه - public void play(ActionEvent event, Song song){ - - currentSong=song; nowPlayingLabel.setText(song.getName()); - if (!isPlaying) - playPause(event); - - // کد پخش موسیقی path = getClass() .getResource(song.getPath()) .toExternalForm(); media = new Media(path); player = new MediaPlayer(media); + //این برا اینه که تموم شد بره بعدی + player.setOnEndOfMedia(() -> { + if(isRepeat){ + player.seek(player.getStartTime()); + player.play(); + } + else + nextBtn.fire(); + }); + + return player; + } + + public void play(ActionEvent event, Song song){ + + currentSong = song; + + if(player != null){ + player.stop(); + } + + setPlayer(currentSong); + player.play(); + + isPlaying = true; + + playPauseBtn.setGraphic(pauseIcon); } @FXML public void playPause(ActionEvent a){ + + if(player == null){ + return; + } + if(isPlaying){ playPauseBtn.setGraphic(playIcon); - isPlaying=false; - //کد توقف player.pause(); + isPlaying = false; - } - else{ + } else { playPauseBtn.setGraphic(pauseIcon); - isPlaying=true; + + player.play(); + isPlaying = true; } } @@ -236,12 +304,12 @@ public class MusicController { public void openPlaylistWindow(ActionEvent e) { - if(isPlaying) + if(isPlaying) { playPause(e); + } if(!isOpen){ - - // باز کردن پلی‌لیست + // باز کردن پلی لیست if(playlistListView.getItems().isEmpty()){ Alert alert = new Alert(Alert.AlertType.WARNING); @@ -266,9 +334,7 @@ public class MusicController { playlistListView.setManaged(true); } else { - // برگشت به صفحه اصلی - isOpen = false; openPlaylistBtn.setText("Open Playlist"); @@ -280,6 +346,18 @@ public class MusicController { playlistListView.setManaged(false); } } + + public int findIndex(ListView listView, Song song){ + for(int i = 0; i < listView.getItems().size(); i++){ + + if(listView.getItems().get(i).equals(song)){ + return i; + } + } + + return -1; } +} + diff --git a/src/main/resources/image/icon.png b/src/main/resources/image/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f5b8da9261f9a55cab0615042fdfd5602655e418 GIT binary patch literal 3791 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 -