我创建了一个基于JavaFX的小型音乐播放器,其中包含材质设计功能。它工作正常,但问题是当我将光标移出窗口时,Seek在3秒后停止更新。为什么会这样?有人可以帮忙吗?
dashboardController.java
:
package lyrica;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXListView;
import com.jfoenix.controls.JFXProgressBar;
import com.jfoenix.controls.JFXSlider;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.stream.Stream;
import javafx.collections.ObservableMap;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.MultipleSelectionModel;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaPlayer.Status;
import javafx.stage.Stage;
import javafx.stage.Window;
import javafx.util.Duration;
import org.apache.commons.io.FilenameUtils;
/**
*
* @author debayan
*/
public class dashboardController implements Initializable {
static boolean isSongAlreadyPlaying = false;
static boolean isSongAsigned = false;
static boolean isSeekBeingChanged = false;
static String currentSongName = "";
static String currentAlbumName = "";
static String currentArtistName = "";
static Double currentSongDuration = 0.00;
static int currentSongIndex = 0;
MediaPlayer player = null;
@FXML
private JFXButton pauseStartButton;
@FXML
private JFXProgressBar pBarLoading;
@FXML
private JFXSlider songSeek;
@FXML
private JFXButton previousButton;
@FXML
private JFXButton nextButton;
@FXML
private Label albumLabel;
@FXML
private Label loadingMusicFilesLabel;
@FXML
private Label itsLonelyHereLabel;
@FXML
private JFXButton checkForSongsButton;
@FXML
private Label itsLonelyHere2Label;
@FXML
private JFXListView songListview;
@FXML
private Label songNameLabel;
@FXML
private JFXButton stopButton;
@FXML
private Label currentMusicLocationLabel;
@FXML
private Label totalMusicInfoLabel;
String fileNameAttr = "file://";
@Override
public void initialize(URL url, ResourceBundle rb)
{
if(System.getProperty("os.name").equals("Linux"))
{
fileNameAttr = "file://";
}
else
{
fileNameAttr = "file:///";
}
try
{
searchForSongs();
}
catch(Exception e)
{
e.printStackTrace();
}
refreshSeek();
}
public void refreshSeek()
{
Task task = new Task<Void>() {
@Override public Void call() {
while(true)
{
if(songSeek.isValueChanging())
{
double newSongTime = ((songSeek.getValue()/100)*currentSongDuration)*60000;
player.seek(Duration.millis(newSongTime));
}
else
{
if(isSongAsigned)
{
console.pln("asd");
double currentSongCurrentSeek = player.getCurrentTime().toMinutes();
double seekProgress = (currentSongCurrentSeek/currentSongDuration)*100;
songSeek.setValue(seekProgress);
}
}
try
{
Thread.sleep(150);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
};
new Thread(task).start();
}
@FXML
public void searchForSongs() throws IOException
{
pBarLoading.setOpacity(1);
loadingMusicFilesLabel.setOpacity(1);
try
{
File folder = new File(Lyrica.songDirectory);
File[] listOfFiles = folder.listFiles();
int i;
int tmpNoOfSongs = 0;
for(i = 0; i<listOfFiles.length ; i++)
{
if(listOfFiles[i].isFile())
{
String tmpFileNameExtension = FilenameUtils.getExtension(listOfFiles[i].getName());
if (tmpFileNameExtension.equalsIgnoreCase("mp3"))
{
Lyrica.songList.add(listOfFiles[i].getName());
tmpNoOfSongs++;
}
}
}
Lyrica.noOfSongs = tmpNoOfSongs;
console.pln(Integer.toString(Lyrica.noOfSongs));
console.pln("Song Names : ");
int j;
for(j=0; j<Lyrica.songList.size(); j++)
{
console.pln(Lyrica.songList.get(j).toString());
}
}
catch(Exception e)
{
e.printStackTrace();
}
pBarLoading.setOpacity(0);
loadingMusicFilesLabel.setOpacity(0);
if(Lyrica.noOfSongs == 0)
{
itsLonelyHereLabel.setOpacity(1);
itsLonelyHere2Label.setOpacity(1);
checkForSongsButton.setOpacity(1);
itsLonelyHere2Label.setText("We were not able to search for songs in '"+Lyrica.songDirectory+"' ...\nPlease copy some songs over there");
}
else
{
checkForSongsButton.setDisable(true);
songListview.getItems().clear();
songListview.getItems().add("Song Name");
int k;
for(k=0; k<Lyrica.songList.size(); k++)
{
String nameToBeAdded = Lyrica.songList.get(k).toString().replace(".mp3","");
nameToBeAdded = nameToBeAdded.replace(".MP3", "");
songListview.getItems().add(nameToBeAdded);
}
songListview.setOpacity(1);
}
}
@FXML
public void playSelectedSong()
{
int selected = (songListview.getSelectionModel().getSelectedIndex() - 1);
if(selected != -1)
{
console.pln("SELECTED : "+Lyrica.songList.get(selected));
playSong(Lyrica.songDirectory+"/"+Lyrica.songList.get(selected), Lyrica.songList.get(selected).toString(), selected);
}
}
public void playSong(String fileName,String fileNameWithoutLocation, int songIndex)
{
currentSongIndex = songIndex;
pauseStartButton.setText("Pause");
songSeek.setOpacity(1);
previousButton.setOpacity(1);
nextButton.setOpacity(1);
pauseStartButton.setOpacity(1);
stopButton.setOpacity(1);
String fname = "asds";
try
{
String songName = fileName;
String songNameToBeProcessed = "";
int i;
for(i = 0; i<songName.length(); i++)
{
if(songName.charAt(i) == '/' )
{
songNameToBeProcessed += "/";
}
else if(Character.toString(songName.charAt(i)).equals("\\"))
{
songNameToBeProcessed += Character.toString(songName.charAt(i));
}
else
{
if(songName.charAt(i) == ' ')
{
songNameToBeProcessed += "%20";
}
else
{
songNameToBeProcessed+=URLEncoder.encode(Character.toString(songName.charAt(i)), "UTF-8");
}
}
}
fname = songNameToBeProcessed;
console.pln(fname);
}
catch(Exception e)
{
e.printStackTrace();
}
console.pln("asdasd");
Media pick = new Media(fileNameAttr+fname);
String tmpcurrentSongName = fileNameWithoutLocation.replace(".mp3","");
currentSongName = tmpcurrentSongName.replace(".MP3","");
if(isSongAlreadyPlaying)
{
player.stop();
}
player = null;
boolean wasAvailable = false;
try
{
player = new MediaPlayer(pick);
wasAvailable = true;
}
catch(Exception e)
{
console.pln("Unable to play music file...");
wasAvailable = false;
}
player.setOnEndOfMedia(new Runnable() {
@Override
public void run() {
nextButtonClicked();
}
});
player.setOnReady(new Runnable() {
@Override
public void run() {
String tmpTitle = tmpcurrentSongName;
String tmpAlbum = "Unknown";
currentSongDuration = pick.getDuration().toMinutes();
double thisSongDuration = pick.getDuration().toMinutes();
String thisSongDurationString = Double.toString(thisSongDuration);
int x;
String finalDurationToBeShown = "";
boolean didPointCome = false;
for(x = 0;x<thisSongDurationString.length();x++)
{
if(Character.toString(thisSongDurationString.charAt(x)).equals("."))
{
didPointCome = true;
finalDurationToBeShown += ":";
finalDurationToBeShown += Character.toString(thisSongDurationString.charAt(x+1));
finalDurationToBeShown += Character.toString(thisSongDurationString.charAt(x+2));
break;
}
if(didPointCome == false)
{
finalDurationToBeShown += Character.toString(thisSongDurationString.charAt(x));
}
}
console.pln(finalDurationToBeShown);
totalMusicInfoLabel.setText(finalDurationToBeShown);
totalMusicInfoLabel.setOpacity(1);
console.pln("Song Duration :"+currentSongDuration);
try
{
tmpTitle = pick.getMetadata().get("title").toString();
}
catch(Exception e)
{
tmpTitle = tmpcurrentSongName;
}
try
{
tmpAlbum = pick.getMetadata().get("album").toString();
}
catch(Exception e)
{
tmpAlbum = "Unknown";
}
refreshSongInfo(tmpTitle, tmpAlbum);
console.pln(pick.getMetadata().toString());
}
});
player.play();
isSongAlreadyPlaying = true;
isSongAsigned = true;
}
@FXML
public void pauseStartButtonClicked(ActionEvent event)
{
if(isSongAlreadyPlaying)
{
pauseStartButton.setText("Resume");
isSongAlreadyPlaying = false;
player.pause();
}
else
{
if(isSongAsigned)
{
pauseStartButton.setText("Pause");
player.play();
isSongAlreadyPlaying = true;
}
}
}
public void refreshSongInfo(String titlePassed, String albumPassed)
{
songNameLabel.setText(titlePassed);
albumLabel.setText(albumPassed);
}
@FXML
public void stopButtonClicked(ActionEvent event)
{
if(isSongAsigned)
{
player.stop();
player = null;
isSongAlreadyPlaying = false;
isSongAsigned = false;
songSeek.setOpacity(0);
previousButton.setOpacity(0);
nextButton.setOpacity(0);
pauseStartButton.setOpacity(0);
stopButton.setOpacity(0);
pauseStartButton.setText("Start");
refreshSongInfo("Select A Song","To Be Played");
}
}
@FXML
public void quitButtonClicked(ActionEvent event)
{
console.pln("Quitting...");
System.exit(0);
}
@FXML
public void selectAnotherSongDirectory(ActionEvent event)
{
new mentionSongDirectory().setVisible(true);
Node node = (Node) event.getSource();
Stage s= (Stage) node.getScene().getWindow();
s.close();
}
@FXML
public void nextButtonClicked()
{
int newSongIndex;
String newSong;
String songDirectory;
if(currentSongIndex == Lyrica.songList.size() - 1)
{
// index 1
newSongIndex = 0;
newSong = Lyrica.songList.get(newSongIndex).toString();
songDirectory = Lyrica.songDirectory;
}
else
{
newSongIndex = currentSongIndex +1;
newSong = Lyrica.songList.get(newSongIndex).toString();
songDirectory = Lyrica.songDirectory;
}
console.pln("NEXT BUTTON CLICKED");
playSong(songDirectory+"/"+newSong,newSong,newSongIndex);
songListview.getSelectionModel().select(newSongIndex+1);
songListview.getFocusModel().focus(newSongIndex+1);
songListview.scrollTo(newSongIndex+1);
}
@FXML
public void previousButtonClicked()
{
int newSongIndex;
String newSong;
String songDirectory;
if(currentSongIndex == 0)
{
// index 1
newSongIndex = Lyrica.songList.size() - 1;
newSong = Lyrica.songList.get(newSongIndex).toString();
songDirectory = Lyrica.songDirectory;
}
else
{
newSongIndex = currentSongIndex -1;
newSong = Lyrica.songList.get(newSongIndex).toString();
songDirectory = Lyrica.songDirectory;
}
console.pln("PREVIOUS BUTTON CLICKED");
playSong(songDirectory+"/"+newSong,newSong,newSongIndex);
songListview.getSelectionModel().select(newSongIndex+1);
songListview.getFocusModel().focus(newSongIndex+1);
songListview.scrollTo(newSongIndex+1);
}
@FXML
public void aboutButtonClicked(ActionEvent event) throws Exception
{
if(player != null)
{
player.stop();
isSongAsigned = false;
isSongAlreadyPlaying = false;
}
new openFXML("about.fxml",true,event);
}
}
dashboard.fxml
<?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXListView?>
<?import com.jfoenix.controls.JFXProgressBar?>
<?import com.jfoenix.controls.JFXSlider?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane id="AnchorPane" prefHeight="590.0" prefWidth="995.0" xmlns="http://javafx.com/javafx/9" xmlns:fx="http://javafx.com/fxml/1" fx:controller="lyrica.dashboardController">
<children>
<JFXListView fx:id="songListview" layoutY="52.0" onMouseClicked="#playSelectedSong" opacity="0.0" prefHeight="454.0" prefWidth="999.0" />
<AnchorPane layoutX="-2.0" prefHeight="51.0" prefWidth="1001.0" style="-fx-background-color: #7c43bd;">
<children>
<Label layoutX="18.0" layoutY="12.0" text="Gramophy" textFill="WHITE">
<font>
<Font size="21.0" />
</font>
</Label>
<JFXButton fx:id="quitButton" layoutX="960.0" layoutY="12.0" onAction="#quitButtonClicked" ripplerFill="RED" text="X" textFill="RED" />
<JFXButton fx:id="aboutButton" layoutX="925.0" layoutY="12.0" onAction="#aboutButtonClicked" ripplerFill="#00c7ff" text="i" textFill="WHITE">
<font>
<Font name="System Bold" size="13.0" />
</font>
</JFXButton>
</children>
</AnchorPane>
<AnchorPane layoutY="506.0" prefHeight="84.0" prefWidth="999.0" style="-fx-background-color: #7c43bd;">
<children>
<Label fx:id="songNameLabel" layoutX="12.0" layoutY="15.0" prefHeight="26.0" prefWidth="352.0" text="Select A Song" textFill="WHITE">
<font>
<Font size="19.0" />
</font>
</Label>
<JFXButton fx:id="pauseStartButton" layoutX="756.0" layoutY="36.0" onAction="#pauseStartButtonClicked" opacity="0.0" prefHeight="33.0" prefWidth="98.0" text="Resume" textFill="WHITE">
<font>
<Font size="17.0" />
</font></JFXButton>
<JFXSlider fx:id="songSeek" layoutX="413.0" layoutY="13.0" opacity="0.0" prefHeight="16.0" prefWidth="520.0" />
<JFXButton fx:id="nextButton" layoutX="867.0" layoutY="36.0" onAction="#nextButtonClicked" opacity="0.0" prefHeight="33.0" prefWidth="77.0" text="Next" textFill="WHITE">
<font>
<Font size="17.0" />
</font></JFXButton>
<JFXButton fx:id="previousButton" layoutX="630.0" layoutY="36.0" onAction="#previousButtonClicked" opacity="0.0" text="Previous" textFill="WHITE">
<font>
<Font size="17.0" />
</font>
</JFXButton>
<Label fx:id="albumLabel" layoutX="12.0" layoutY="46.0" prefHeight="19.0" prefWidth="352.0" text="To Be Played" textFill="WHITE">
<font>
<Font size="15.0" />
</font>
</Label>
<JFXButton fx:id="stopButton" layoutX="549.0" layoutY="36.0" onAction="#stopButtonClicked" opacity="0.0" text="Stop" textFill="WHITE">
<font>
<Font size="17.0" />
</font>
</JFXButton>
<Label fx:id="currentMusicLocationLabel" layoutX="375.0" layoutY="14.0" opacity="0.0" text="0:00" textFill="WHITE" />
<Label fx:id="totalMusicInfoLabel" layoutX="940.0" layoutY="14.0" opacity="0.0" text="0:00" textFill="WHITE" />
</children>
</AnchorPane>
<JFXProgressBar fx:id="pBarLoading" layoutX="144.0" layoutY="202.0" opacity="0.0" prefHeight="0.0" prefWidth="427.0" />
<Label fx:id="loadingMusicFilesLabel" layoutX="276.0" layoutY="215.0" opacity="0.0" text="Loading music Files..." />
<Label fx:id="itsLonelyHereLabel" layoutX="14.0" layoutY="57.0" opacity="0.0" prefHeight="40.0" prefWidth="283.0" text="Its Lonely Here...">
<font>
<Font size="32.0" />
</font>
</Label>
<Label fx:id="itsLonelyHere2Label" layoutX="14.0" layoutY="97.0" opacity="0.0" prefHeight="40.0" prefWidth="452.0" text="We were not able to search for songs in DIRECTORY ... Please copy some songs over there You can also set a different location to search for songs :" />
<JFXButton fx:id="checkForSongsButton" layoutX="14.0" layoutY="137.0" onAction="#selectAnotherSongDirectory" opacity="0.0" ripplerFill="BLACK" text="Set Another Song Directory" />
</children>
</AnchorPane>