forked from AdvancedProgramming1404/HW-07-JavaFX
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5fcfe8a953 | ||
|
|
772c9ed3f6 |
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -11,21 +11,31 @@
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<junit.version>5.10.2</junit.version> </properties>
|
||||
<junit.version>5.10.2</junit.version>
|
||||
|
||||
<maven.compiler.release>21</maven.compiler.release>
|
||||
<javafx.version>21.0.4</javafx.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-controls</artifactId>
|
||||
<version>21</version>
|
||||
<version>${javafx.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-fxml</artifactId>
|
||||
<version>21</version>
|
||||
<version>${javafx.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-media</artifactId>
|
||||
<version>${javafx.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<!-- JUnit -->
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
@@ -36,39 +46,30 @@
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency> </dependencies>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<source>23</source>
|
||||
<target>23</target>
|
||||
<release>${maven.compiler.release}</release>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-maven-plugin</artifactId>
|
||||
<version>0.0.8</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<!-- Default configuration for running with: mvn clean javafx:run -->
|
||||
<id>default-cli</id>
|
||||
<configuration>
|
||||
<mainClass>sbu.javafx/sbu.javafx.MusicApp</mainClass>
|
||||
<launcher>app</launcher>
|
||||
<jlinkZipName>app</jlinkZipName>
|
||||
<jlinkImageName>app</jlinkImageName>
|
||||
<noManPages>true</noManPages>
|
||||
<stripDebug>true</stripDebug>
|
||||
<noHeaderFiles>true</noHeaderFiles>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<mainClass>sbu.javafx/sbu.javafx.MusicApp</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -2,7 +2,10 @@ package sbu.javafx;
|
||||
|
||||
import javafx.application.Application;
|
||||
|
||||
public class Launcher{
|
||||
public static void main(String[] args) {
|
||||
// TODO: Launch the JavaFX application by calling Application.launch(Main.class) }
|
||||
}
|
||||
public class Launcher
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
Application.launch(MusicApp.class, args);
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,8 @@ import javafx.stage.Stage;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class MusicApp extends Application {
|
||||
|
||||
public class MusicApp extends Application
|
||||
{
|
||||
@Override
|
||||
public void start(Stage stage) throws IOException
|
||||
{
|
||||
@@ -16,8 +16,7 @@ public class MusicApp extends Application {
|
||||
Scene scene = new Scene(fxmlLoader.load());
|
||||
stage.setTitle("Music Player");
|
||||
stage.setScene(scene);
|
||||
//TODO: add icon to the stage
|
||||
stage.setResizable(false);
|
||||
stage.show();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,384 @@
|
||||
package sbu.javafx;
|
||||
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.control.ListView;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.media.Media;
|
||||
import javafx.scene.media.MediaPlayer;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
public class MusicController {
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
// TODO: Define your UI components using the @FXML annotation.
|
||||
public class MusicController
|
||||
{
|
||||
@FXML private VBox rootPane;
|
||||
@FXML private Label titleLabel;
|
||||
@FXML private Label nowPlayingLabel;
|
||||
|
||||
//TODO: Implement the logic to play a song. This method should update the UI to show which song is currently playing.
|
||||
@FXML private Button playBtn1;
|
||||
@FXML private Button playBtn2;
|
||||
@FXML private Button playBtn3;
|
||||
|
||||
@FXML private ImageView playIcon1;
|
||||
@FXML private ImageView playIcon2;
|
||||
@FXML private ImageView playIcon3;
|
||||
|
||||
@FXML private Button stopBtn1;
|
||||
@FXML private Button stopBtn2;
|
||||
@FXML private Button stopBtn3;
|
||||
|
||||
private final List<String> playlist = new ArrayList<>();
|
||||
private MediaPlayer mediaPlayer;
|
||||
|
||||
private boolean darkTheme = false;
|
||||
|
||||
private String currentPlayingSongFile = null;
|
||||
private boolean isPlaying = false;
|
||||
|
||||
private boolean isSong1Playing = false;
|
||||
private boolean isSong2Playing = false;
|
||||
private boolean isSong3Playing = false;
|
||||
|
||||
|
||||
private Image playImage;
|
||||
private Image pauseImage;
|
||||
private Image stopImage;
|
||||
|
||||
private final String song1 = "Careless Whisper";
|
||||
private final String song2 = "Adore You";
|
||||
private final String song3 = "Wildflower";
|
||||
|
||||
private final String song1File = "/sbu/javafx/audio/careless_whisper.mp3";
|
||||
private final String song2File = "/sbu/javafx/audio/adore_you.mp3";
|
||||
private final String song3File = "/sbu/javafx/audio/wildflower.mp3";
|
||||
|
||||
@FXML
|
||||
public void handlePlayAction() {
|
||||
//Update labels, change button icons, etc.
|
||||
private void initialize()
|
||||
{
|
||||
playImage = loadImage("/sbu/javafx/images/play.png");
|
||||
pauseImage = loadImage("/sbu/javafx/images/pause.png");
|
||||
stopImage = loadImage("/sbu/javafx/images/stop.png");
|
||||
|
||||
updateAllButtonIcons();
|
||||
updateNowPlaying("None");
|
||||
applyLightTheme();
|
||||
}
|
||||
|
||||
//TODO: Logic to add a specific song to the user's playlist.
|
||||
@FXML public void handlePlay1() { togglePlay(song1, song1File, playIcon1, 1); }
|
||||
@FXML public void handlePlay2() { togglePlay(song2, song2File, playIcon2, 2); }
|
||||
@FXML public void handlePlay3() { togglePlay(song3, song3File, playIcon3, 3); }
|
||||
|
||||
public void addToPlaylist(String songName) {
|
||||
//Add the song to a list or update a ListView.
|
||||
@FXML public void handleStop1() { stopSong(1); }
|
||||
@FXML public void handleStop2() { stopSong(2); }
|
||||
@FXML public void handleStop3() { stopSong(3); }
|
||||
|
||||
@FXML public void handleAdd1() { addToPlaylist(song1); }
|
||||
@FXML public void handleAdd2() { addToPlaylist(song2); }
|
||||
@FXML public void handleAdd3() { addToPlaylist(song3); }
|
||||
|
||||
@FXML
|
||||
public void handleViewPlaylist()
|
||||
{
|
||||
Stage stage = new Stage();
|
||||
VBox root = new VBox(10);
|
||||
root.setStyle("-fx-padding: 16; -fx-background-color: white;");
|
||||
Label title = new Label("My Playlist");
|
||||
title.setStyle("-fx-font-size: 18px; -fx-font-weight: bold;");
|
||||
ListView<String> listView = new ListView<>();
|
||||
listView.getItems().addAll(playlist);
|
||||
root.getChildren().addAll(title, listView);
|
||||
Scene scene = new Scene(root, 300, 400);
|
||||
stage.setScene(scene);
|
||||
stage.setTitle("Playlist");
|
||||
stage.show();
|
||||
}
|
||||
|
||||
// TODO:This method should open a new window or change the current scene to display the "Playlist" page.
|
||||
|
||||
public void openPlaylistWindow() {
|
||||
//Create a new stage and show the playlist UI.
|
||||
@FXML
|
||||
public void handleToggleTheme()
|
||||
{
|
||||
darkTheme = !darkTheme;
|
||||
if (darkTheme) applyDarkTheme(); else applyLightTheme();
|
||||
}
|
||||
}
|
||||
|
||||
private void togglePlay(String songName, String resourcePath, ImageView icon, int songIndex)
|
||||
{
|
||||
boolean shouldPlay = false;
|
||||
|
||||
switch(songIndex)
|
||||
{
|
||||
case 1: shouldPlay = !isSong1Playing; break;
|
||||
case 2: shouldPlay = !isSong2Playing; break;
|
||||
case 3: shouldPlay = !isSong3Playing; break;
|
||||
}
|
||||
|
||||
if (shouldPlay)
|
||||
{
|
||||
playOrResumeSong(songName, resourcePath, icon, songIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
pauseSong(songIndex);
|
||||
}
|
||||
updateAllButtonIcons();
|
||||
}
|
||||
|
||||
private void playOrResumeSong(String songName, String resourcePath, ImageView icon, int songIndex)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (mediaPlayer != null && isPlaying && !resourcePath.equals(currentPlayingSongFile))
|
||||
{
|
||||
stopPlayback();
|
||||
updateAllButtonIcons();
|
||||
}
|
||||
|
||||
if (mediaPlayer != null && !isPlaying && resourcePath.equals(currentPlayingSongFile))
|
||||
{
|
||||
mediaPlayer.play();
|
||||
isPlaying = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mediaPlayer != null)
|
||||
{
|
||||
mediaPlayer.stop();
|
||||
mediaPlayer.dispose();
|
||||
}
|
||||
|
||||
URL url = getClass().getResource(resourcePath);
|
||||
if (url == null)
|
||||
{
|
||||
updateNowPlaying(songName + " (file not found)");
|
||||
setSongStatus(songIndex, false);
|
||||
return;
|
||||
}
|
||||
|
||||
Media media = new Media(url.toExternalForm());
|
||||
mediaPlayer = new MediaPlayer(media);
|
||||
|
||||
currentPlayingSongFile = resourcePath;
|
||||
isPlaying = true;
|
||||
|
||||
mediaPlayer.setOnEndOfMedia(() ->
|
||||
{
|
||||
stopPlayback();
|
||||
updateNowPlaying("None");
|
||||
setSongStatus(songIndex, false);
|
||||
updateAllButtonIcons();
|
||||
});
|
||||
|
||||
mediaPlayer.setOnError(() ->
|
||||
{
|
||||
stopPlayback();
|
||||
updateNowPlaying(songName + " (error)");
|
||||
setSongStatus(songIndex, false);
|
||||
updateAllButtonIcons();
|
||||
});
|
||||
|
||||
mediaPlayer.play();
|
||||
}
|
||||
|
||||
setSongStatus(songIndex, true);
|
||||
updateNowPlaying(songName);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
stopPlayback();
|
||||
updateNowPlaying(songName + " (error)");
|
||||
setSongStatus(songIndex, false);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void pauseSong(int songIndex)
|
||||
{
|
||||
if (mediaPlayer != null && isPlaying && currentPlayingSongFile != null)
|
||||
{
|
||||
String targetFile = "";
|
||||
switch(songIndex)
|
||||
{
|
||||
case 1: targetFile = song1File; break;
|
||||
case 2: targetFile = song2File; break;
|
||||
case 3: targetFile = song3File; break;
|
||||
}
|
||||
|
||||
if (currentPlayingSongFile.equals(targetFile))
|
||||
{
|
||||
mediaPlayer.pause();
|
||||
isPlaying = false;
|
||||
setSongStatus(songIndex, false);
|
||||
updateNowPlaying("Paused: " + getSongNameByIndex(songIndex));
|
||||
updateAllButtonIcons();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void stopSong(int songIndex)
|
||||
{
|
||||
if (mediaPlayer != null && isPlaying)
|
||||
{
|
||||
String targetFile = "";
|
||||
switch(songIndex)
|
||||
{
|
||||
case 1: targetFile = song1File; break;
|
||||
case 2: targetFile = song2File; break;
|
||||
case 3: targetFile = song3File; break;
|
||||
}
|
||||
|
||||
if (currentPlayingSongFile != null && currentPlayingSongFile.equals(targetFile))
|
||||
{
|
||||
mediaPlayer.stop();
|
||||
mediaPlayer.dispose();
|
||||
mediaPlayer = null;
|
||||
isPlaying = false;
|
||||
currentPlayingSongFile = null;
|
||||
setSongStatus(songIndex, false);
|
||||
updateNowPlaying("None");
|
||||
updateAllButtonIcons();
|
||||
}
|
||||
else
|
||||
{
|
||||
setSongStatus(songIndex, false);
|
||||
updateAllButtonIcons();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setSongStatus(songIndex, false);
|
||||
updateAllButtonIcons();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void stopPlayback()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (mediaPlayer != null)
|
||||
{
|
||||
mediaPlayer.stop();
|
||||
mediaPlayer.dispose();
|
||||
mediaPlayer = null;
|
||||
}
|
||||
}
|
||||
catch (Exception ignored) { }
|
||||
|
||||
isPlaying = false;
|
||||
currentPlayingSongFile = null;
|
||||
isSong1Playing = false;
|
||||
isSong2Playing = false;
|
||||
isSong3Playing = false;
|
||||
}
|
||||
|
||||
private void setSongStatus(int songIndex, boolean status)
|
||||
{
|
||||
switch(songIndex)
|
||||
{
|
||||
case 1: isSong1Playing = status; break;
|
||||
case 2: isSong2Playing = status; break;
|
||||
case 3: isSong3Playing = status; break;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean getSongStatus(int songIndex)
|
||||
{
|
||||
switch(songIndex)
|
||||
{
|
||||
case 1: return isSong1Playing;
|
||||
case 2: return isSong2Playing;
|
||||
case 3: return isSong3Playing;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
private String getSongNameByIndex(int songIndex)
|
||||
{
|
||||
switch(songIndex)
|
||||
{
|
||||
case 1: return song1;
|
||||
case 2: return song2;
|
||||
case 3: return song3;
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
public void addToPlaylist(String songName)
|
||||
{
|
||||
if (!playlist.contains(songName))
|
||||
{
|
||||
playlist.add(songName);
|
||||
System.out.println(songName + " added to playlist.");
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.println(songName + " is already in the playlist.");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNowPlaying(String text)
|
||||
{
|
||||
if (nowPlayingLabel != null) {nowPlayingLabel.setText("Now Playing: " + text);}
|
||||
}
|
||||
|
||||
private void updateAllButtonIcons()
|
||||
{
|
||||
updateIconButton(playIcon1, isSong1Playing, song1File);
|
||||
updateIconButton(playIcon2, isSong2Playing, song2File);
|
||||
updateIconButton(playIcon3, isSong3Playing, song3File);
|
||||
}
|
||||
|
||||
private void updateIconButton(ImageView icon, boolean isPlayingCurrent, String currentSongFile)
|
||||
{
|
||||
if (icon == null) return;
|
||||
|
||||
if (isPlaying && currentPlayingSongFile != null && currentPlayingSongFile.equals(currentSongFile))
|
||||
{
|
||||
if (icon.getImage() != pauseImage) {icon.setImage(pauseImage);}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (icon.getImage() != playImage) {icon.setImage(playImage);}
|
||||
}
|
||||
}
|
||||
|
||||
private Image loadImage(String resourcePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
URL url = getClass().getResource(resourcePath);
|
||||
if (url == null)
|
||||
{
|
||||
System.err.println("Image not found: " + resourcePath);
|
||||
return null;
|
||||
}
|
||||
return new Image(url.toExternalForm());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("Error loading image: " + resourcePath + " - " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void applyDarkTheme()
|
||||
{
|
||||
if (rootPane != null) rootPane.setStyle("-fx-padding: 24; -fx-background-color: #121212;");
|
||||
if (titleLabel != null) titleLabel.setStyle("-fx-font-size: 26px; -fx-font-weight: bold; -fx-text-fill: white;");
|
||||
if (nowPlayingLabel != null) nowPlayingLabel.setStyle("-fx-padding: 12;" + "-fx-background-color: #1E1E1E;" + "-fx-background-radius: 10;" + "-fx-border-color: #444444;" + "-fx-border-radius: 10;" + "-fx-text-fill: white;");
|
||||
}
|
||||
|
||||
private void applyLightTheme()
|
||||
{
|
||||
if (rootPane != null) rootPane.setStyle("-fx-padding: 24; -fx-background-color: #F8F8F8;");
|
||||
if (titleLabel != null) titleLabel.setStyle("-fx-font-size: 26px; -fx-font-weight: bold; -fx-text-fill: #222222;");
|
||||
if (nowPlayingLabel != null) nowPlayingLabel.setStyle("-fx-padding: 12;" + "-fx-background-color: white;" + "-fx-background-radius: 10;" + "-fx-border-color: rgba(0,0,0,0.15);" + "-fx-border-radius: 10;" + "-fx-text-fill: black;");
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,228 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.geometry.Pos?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.Separator?>
|
||||
<?import javafx.scene.image.Image?>
|
||||
<?import javafx.scene.image.ImageView?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<VBox xmlns="http://javafx.com/fxml" alignment="CENTER" spacing="10">
|
||||
|
||||
<!-- TODO: Add your code here! -->
|
||||
<VBox fx:id="rootPane"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
fx:controller="sbu.javafx.MusicController"
|
||||
alignment="TOP_CENTER"
|
||||
spacing="18"
|
||||
prefWidth="520"
|
||||
prefHeight="720"
|
||||
style="-fx-padding: 24; -fx-background-color: #F8F8F8;">
|
||||
|
||||
</VBox>
|
||||
<padding>
|
||||
<Insets top="24" right="24" bottom="24" left="24"/>
|
||||
</padding>
|
||||
|
||||
<Label fx:id="titleLabel"
|
||||
text="JavaFX Music Player"
|
||||
style="-fx-font-size: 26px; -fx-font-weight: bold; -fx-text-fill: #222222;" />
|
||||
|
||||
<Label fx:id="nowPlayingLabel"
|
||||
text="Now Playing: None"
|
||||
maxWidth="Infinity"
|
||||
alignment="CENTER"
|
||||
style="-fx-padding: 12; -fx-background-color: white; -fx-background-radius: 10; -fx-border-color: rgba(0,0,0,0.15); -fx-border-radius: 10; -fx-text-fill: black;" />
|
||||
|
||||
<HBox spacing="14" alignment="CENTER">
|
||||
<Button fx:id="themeBtn"
|
||||
onAction="#handleToggleTheme"
|
||||
prefWidth="56"
|
||||
prefHeight="56"
|
||||
style="-fx-background-radius: 28;">
|
||||
<graphic>
|
||||
<ImageView fitWidth="26" fitHeight="26" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@images/theme.png"/>
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
|
||||
<Button fx:id="playlistBtn"
|
||||
onAction="#handleViewPlaylist"
|
||||
prefWidth="56"
|
||||
prefHeight="56"
|
||||
style="-fx-background-radius: 28;">
|
||||
<graphic>
|
||||
<ImageView fitWidth="26" fitHeight="26" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@images/playlist.png"/>
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
</HBox>
|
||||
|
||||
<Separator />
|
||||
|
||||
<VBox spacing="12" VBox.vgrow="ALWAYS">
|
||||
|
||||
<!-- Song 1 -->
|
||||
<HBox alignment="CENTER_LEFT"
|
||||
spacing="14"
|
||||
style="-fx-padding: 14; -fx-background-color: white; -fx-background-radius: 12; -fx-border-color: #EAEAEA; -fx-border-radius: 12;">
|
||||
<VBox spacing="2" HBox.hgrow="ALWAYS">
|
||||
<Label text="Careless Whisper" style="-fx-font-weight: bold; -fx-font-size: 16px;" />
|
||||
<Label text="George Michael • 5:02" style="-fx-text-fill: #777777; -fx-font-size: 12px;" />
|
||||
</VBox>
|
||||
|
||||
<Button fx:id="playBtn1"
|
||||
onAction="#handlePlay1"
|
||||
prefWidth="46"
|
||||
prefHeight="46"
|
||||
style="-fx-background-radius: 23;">
|
||||
<graphic>
|
||||
<ImageView fx:id="playIcon1" fitWidth="20" fitHeight="20" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@images/play.png"/>
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
|
||||
<Button fx:id="stopBtn1"
|
||||
onAction="#handleStop1"
|
||||
prefWidth="46"
|
||||
prefHeight="46"
|
||||
style="-fx-background-radius: 23;">
|
||||
<graphic>
|
||||
<ImageView fx:id="stopIcon1" fitWidth="20" fitHeight="20" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@images/stop.png"/>
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
|
||||
<Button onAction="#handleAdd1"
|
||||
prefWidth="46"
|
||||
prefHeight="46"
|
||||
style="-fx-background-radius: 23;">
|
||||
<graphic>
|
||||
<ImageView fitWidth="20" fitHeight="20" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@images/add.png"/>
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
</HBox>
|
||||
|
||||
<!-- Song 2 -->
|
||||
<HBox alignment="CENTER_LEFT"
|
||||
spacing="14"
|
||||
style="-fx-padding: 14; -fx-background-color: white; -fx-background-radius: 12; -fx-border-color: #EAEAEA; -fx-border-radius: 12;">
|
||||
<VBox spacing="2" HBox.hgrow="ALWAYS">
|
||||
<Label text="Adore You" style="-fx-font-weight: bold; -fx-font-size: 16px;" />
|
||||
<Label text="Harry Styles • 3:27" style="-fx-text-fill: #777777; -fx-font-size: 12px;" />
|
||||
</VBox>
|
||||
|
||||
<Button fx:id="playBtn2"
|
||||
onAction="#handlePlay2"
|
||||
prefWidth="46"
|
||||
prefHeight="46"
|
||||
style="-fx-background-radius: 23;">
|
||||
<graphic>
|
||||
<ImageView fx:id="playIcon2" fitWidth="20" fitHeight="20" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@images/play.png"/>
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
|
||||
<Button fx:id="stopBtn2"
|
||||
onAction="#handleStop2"
|
||||
prefWidth="46"
|
||||
prefHeight="46"
|
||||
style="-fx-background-radius: 23;">
|
||||
<graphic>
|
||||
<ImageView fx:id="stopIcon2" fitWidth="20" fitHeight="20" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@images/stop.png"/>
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
|
||||
<Button onAction="#handleAdd2"
|
||||
prefWidth="46"
|
||||
prefHeight="46"
|
||||
style="-fx-background-radius: 23;">
|
||||
<graphic>
|
||||
<ImageView fitWidth="20" fitHeight="20" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@images/add.png"/>
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
</HBox>
|
||||
|
||||
<!-- Song 3 -->
|
||||
<HBox alignment="CENTER_LEFT"
|
||||
spacing="14"
|
||||
style="-fx-padding: 14; -fx-background-color: white; -fx-background-radius: 12; -fx-border-color: #EAEAEA; -fx-border-radius: 12;">
|
||||
<VBox spacing="2" HBox.hgrow="ALWAYS">
|
||||
<Label text="Wildflower" style="-fx-font-weight: bold; -fx-font-size: 16px;" />
|
||||
<Label text="Billie Eilish • 4:15" style="-fx-text-fill: #777777; -fx-font-size: 12px;" />
|
||||
</VBox>
|
||||
|
||||
<Button fx:id="playBtn3"
|
||||
onAction="#handlePlay3"
|
||||
prefWidth="46"
|
||||
prefHeight="46"
|
||||
style="-fx-background-radius: 23;">
|
||||
<graphic>
|
||||
<ImageView fx:id="playIcon3" fitWidth="20" fitHeight="20" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@images/play.png"/>
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
|
||||
<Button fx:id="stopBtn3"
|
||||
onAction="#handleStop3"
|
||||
prefWidth="46"
|
||||
prefHeight="46"
|
||||
style="-fx-background-radius: 23;">
|
||||
<graphic>
|
||||
<ImageView fx:id="stopIcon3" fitWidth="20" fitHeight="20" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@images/stop.png"/>
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
|
||||
<Button onAction="#handleAdd3"
|
||||
prefWidth="46"
|
||||
prefHeight="46"
|
||||
style="-fx-background-radius: 23;">
|
||||
<graphic>
|
||||
<ImageView fitWidth="20" fitHeight="20" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@images/add.png"/>
|
||||
</image>
|
||||
</ImageView>
|
||||
</graphic>
|
||||
</Button>
|
||||
</HBox>
|
||||
|
||||
</VBox>
|
||||
|
||||
<Label text="SBU JavaFX Project - 2026"
|
||||
style="-fx-text-fill: #AAAAAA; -fx-font-size: 10px;" />
|
||||
|
||||
</VBox>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,15 @@
|
||||
.root
|
||||
{
|
||||
-fx-background-color: #1e1e1e;
|
||||
}
|
||||
|
||||
.label
|
||||
{
|
||||
-fx-text-fill: white;
|
||||
}
|
||||
|
||||
.button
|
||||
{
|
||||
-fx-background-color: #444;
|
||||
-fx-text-fill: white;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
.root
|
||||
{
|
||||
-fx-background-color: white;
|
||||
}
|
||||
|
||||
.label
|
||||
{
|
||||
-fx-text-fill: black;
|
||||
}
|
||||
|
||||
.button
|
||||
{
|
||||
-fx-background-color: #e0e0e0;
|
||||
-fx-text-fill: black;
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
Reference in New Issue
Block a user