+ Implemented the main.fxml and its controller (MusicController) #1

Open
farnam_jhn wants to merge 1 commits from develop into main
14 changed files with 235 additions and 27 deletions
Showing only changes of commit ee473f55e7 - Show all commits
+1 -1
View File
@@ -8,7 +8,7 @@
</list> </list>
</option> </option>
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_23" default="true" project-jdk-name="23" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_25" default="true" project-jdk-name="25" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" /> <output url="file://$PROJECT_DIR$/out" />
</component> </component>
</project> </project>
Generated
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
+5
View File
@@ -24,6 +24,11 @@
<artifactId>javafx-fxml</artifactId> <artifactId>javafx-fxml</artifactId>
<version>21</version> <version>21</version>
</dependency> </dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId>
<version>21</version>
</dependency>
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
+2 -1
View File
@@ -4,5 +4,6 @@ import javafx.application.Application;
public class Launcher{ public class Launcher{
public static void main(String[] args) { public static void main(String[] args) {
// TODO: Launch the JavaFX application by calling Application.launch(Main.class) } Application.launch(MusicApp.class);
}
} }
+8 -2
View File
@@ -2,21 +2,27 @@ package sbu.javafx;
import javafx.application.Application; import javafx.application.Application;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
import javafx.scene.image.Image;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.stage.Stage; import javafx.stage.Stage;
import java.awt.*;
import java.io.IOException; import java.io.IOException;
import java.util.Objects;
public class MusicApp extends Application { public class MusicApp extends Application {
@Override @Override
public void start(Stage stage) throws IOException public void start(Stage stage) throws IOException
{ {
FXMLLoader fxmlLoader = new FXMLLoader(MusicApp.class.getResource("App-view.fxml")); FXMLLoader fxmlLoader = new FXMLLoader(MusicApp.class.getResource("main.fxml"));
Scene scene = new Scene(fxmlLoader.load()); Scene scene = new Scene(fxmlLoader.load());
Image icon = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/icon.png")));
stage.getIcons().add(icon);
stage.setTitle("Music Player"); stage.setTitle("Music Player");
stage.setScene(scene); stage.setScene(scene);
//TODO: add icon to the stage
stage.show(); stage.show();
} }
+127 -15
View File
@@ -1,31 +1,143 @@
package sbu.javafx; package sbu.javafx;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.event.ActionEvent; import javafx.scene.control.Button;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent; import javafx.scene.control.ListView;
import javafx.scene.layout.VBox; import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import java.net.URL;
public class MusicController { public class MusicController {
// TODO: Define your UI components using the @FXML annotation. @FXML
private Button pausePlay;
//TODO: Implement the logic to play a song. This method should update the UI to show which song is currently playing.
@FXML @FXML
public void handlePlayAction() { private ListView<Song> songListView;
//Update labels, change button icons, etc.
@FXML
private ListView<Song> playlist;
@FXML
private Label nowPlayingLabel;
private MediaPlayer mediaPlayer;
private Song currentSong;
private boolean isPlaying = false;
@FXML
public void initialize() {
loadSongs();
} }
//TODO: Logic to add a specific song to the user's playlist. // Adds songs to ListView
private void loadSongs() {
// Songs paths (used URL so the songs can stay in the resources folder so in case of building to jar the songs remain in the app)
URL comeAsYouAre = getClass().getResource("/songs/comeAsYouAre.mp3");
URL childIWillHurtYou = getClass().getResource("/songs/childIWillHurtYou.mp3");
URL lucky = getClass().getResource("/songs/lucky.mp3");
URL fitterHappier = getClass().getResource("/songs/fitterHappier.mp3");
public void addToPlaylist(String songName) { songListView.getItems().addAll(
//Add the song to a list or update a ListView. new Song("Come As You Are", "Nirvana", "03:38", comeAsYouAre),
new Song("Child I Will Hurt You", "Crystal Castles", "03:33", childIWillHurtYou),
new Song("Lucky", "Radiohead","04:18", lucky),
new Song("Fitter Happier","Radiohead","01:57",fitterHappier)
);
} }
// TODO:This method should open a new window or change the current scene to display the "Playlist" page. private void playSelectedSong(Song song) {
try {
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.dispose();
}
public void openPlaylistWindow() { currentSong = song;
//Create a new stage and show the playlist UI.
mediaPlayer = new MediaPlayer(
new Media(song.getUrl().toString())
);
nowPlayingLabel.setText("Now Playing: " + song.getTitle() + " - " + song.getArtist());
pausePlay.setText("Pause");
isPlaying = true;
mediaPlayer.play();
} catch (Exception e) {
nowPlayingLabel.setText("Error: Cannot play file - " + e.getMessage());
}
} }
}
@FXML
public void togglePlayPause() {
if (mediaPlayer == null) return;
if (isPlaying) {
mediaPlayer.pause();
pausePlay.setText("Play");
isPlaying = false;
} else {
mediaPlayer.play();
isPlaying = true;
pausePlay.setText("Pause");
}
}
@FXML
public void addCurrentToPlaylist() {
if (currentSong != null) {
boolean alreadyExists = false;
for (Song song : playlist.getItems()) {
if (song.getUrl().toString().equals(currentSong.getUrl().toString())) {
alreadyExists = true;
break;
}
}
if (!alreadyExists) {
playlist.getItems().add(currentSong);
System.out.println("Added to playlist : " + currentSong.getTitle());
nowPlayingLabel.setText("Now Playing : " + currentSong.getTitle() + " - Added to playlist!");
} else {
System.out.println("Song already in playlist");
nowPlayingLabel.setText("Now Playing : " + currentSong.getTitle() + " - Already in playlist!");
}
}
}
@FXML
public void clearPlaylist() {
playlist.getItems().clear();
System.out.println("Playlist cleared");
}
@FXML
public void removeSelectedFromPlaylist() {
Song selectedSong = playlist.getSelectionModel().getSelectedItem();
if (selectedSong != null) {
playlist.getItems().remove(selectedSong);
System.out.println("Removed from playlist : " + selectedSong.getTitle());
}
}
@FXML
public void handleSongClick() {
// Get the selected song from the song ListView
Song selectedSong = songListView.getSelectionModel().getSelectedItem();
if (selectedSong != null) {
playSelectedSong(selectedSong);
}
}
@FXML
public void handleSongClickPlaylist(){
// Get the selected song from the playlist ListView
Song selectedSong = playlist.getSelectionModel().getSelectedItem();
if (selectedSong != null) {
playSelectedSong(selectedSong);
}
}
}
+27
View File
@@ -0,0 +1,27 @@
package sbu.javafx;
import java.net.URL;
public class Song {
private String title;
private String artist;
private String duration;
private URL url;
public Song(String title, String artist, String duration, URL url) {
this.title = title;
this.artist = artist;
this.duration = duration;
this.url = url;
}
public String getTitle() { return title; }
public String getArtist() { return artist; }
public String getDuration() { return duration; }
public URL getUrl() { return url; }
@Override
public String toString() {
return getTitle() + " - " + getArtist() + " (" + getDuration() + ")";
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/fxml" alignment="CENTER" spacing="10">
<!-- TODO: Add your code here! -->
</VBox>
+59
View File
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<AnchorPane prefHeight="600" prefWidth="800" xmlns="http://javafx.com/javafx/17.0.12"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="sbu.javafx.MusicController">
<TabPane prefHeight="600.0" prefWidth="800.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0"
AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0" AnchorPane.topAnchor="0">
<Tab text="Music Player">
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<VBox layoutX="10.0" layoutY="10.0" prefHeight="560.0" prefWidth="780.0" spacing="15"
AnchorPane.bottomAnchor="10" AnchorPane.leftAnchor="10"
AnchorPane.rightAnchor="10" AnchorPane.topAnchor="10">
<HBox alignment="CENTER" prefHeight="60.0" prefWidth="780.0">
<Label text="Music Player" textAlignment="CENTER">
<font>
<Font size="28.0"/>
</font>
</Label>
</HBox>
<VBox spacing="5" VBox.vgrow="ALWAYS">
<Label style="-fx-font-weight: bold; -fx-font-size: 14px;"
text="Available Songs"/>
<ListView fx:id="songListView" onMouseClicked="#handleSongClick"
prefHeight="400.0" prefWidth="780.0" VBox.vgrow="ALWAYS"/>
</VBox>
<HBox alignment="CENTER_LEFT" prefHeight="60.0" prefWidth="780.0" spacing="10">
<Label fx:id="nowPlayingLabel" style="-fx-font-weight: bold"
text="Now Playing: -"/>
<Region prefHeight="52.0" HBox.hgrow="ALWAYS"/>
<Button fx:id="pausePlay" onAction="#togglePlayPause" prefWidth="70"
text="Play"/>
<Button onAction="#addCurrentToPlaylist" fx:id="addToPlaylist" prefWidth="150" text="Add Current to Playlist"/>
</HBox>
</VBox>
</AnchorPane>
</Tab>
<Tab text="Playlist">
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<VBox layoutX="10.0" layoutY="10.0" prefHeight="560.0" prefWidth="780.0" spacing="15"
AnchorPane.bottomAnchor="10" AnchorPane.leftAnchor="10"
AnchorPane.rightAnchor="10" AnchorPane.topAnchor="10">
<Label style="-fx-font-weight: bold; -fx-font-size: 18px;" text="Playlist"/>
<ListView fx:id="playlist" onMouseClicked="#handleSongClickPlaylist" prefHeight="480.0" prefWidth="780.0" VBox.vgrow="ALWAYS"/>
<HBox alignment="CENTER_RIGHT" spacing="10">
<Button onAction="#clearPlaylist" text="Clear Playlist"/>
<Button onAction="#removeSelectedFromPlaylist" text="Remove Selected"/>
</HBox>
</VBox>
</AnchorPane>
</Tab>
</TabPane>
</AnchorPane>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.