我正在做一个有趣的小项目,我正在制作一个本地音乐应用程序(有点像Spotify),我希望音乐轨道的滑块(MusicSlider)能够捕捉到我点击鼠标的位置。我知道你可以使用isMoveToPointEnabled = true来实现这一点,但是由于我有一个非常混乱的timer_tick(Update)函数等等,我还没有找到一种方法来使它正常工作。
我试了这么久,我的小脑袋想出来的都不管用。
问题是:每当我点击滑块像我应该做的,它立即只是snaps回来。
代码真的很乱,因为我不擅长编写干净的代码,而且代码经历了很多头脑 Storm ,我还没有花时间去修复它。
下面是代码:
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Music_Application.MVVM.View;
using System.Globalization;
using Music_Application.MVVM.ViewModel;
using Microsoft.Win32;
using System.Windows.Controls.Primitives;
using System.Windows.Media.Animation;
using System.Threading;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
namespace Music_Application
{
public partial class MainWindow : Window
{
bool songProgressDrag;
public bool fadeIn;
public bool fadeOut;
public double i;
StreamWriter? sw;
StreamReader? sr;
System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer();
public MainWindow()
{
InitializeComponent();
VolumeSlider.Value = Read(VolumeSlider.Value, "./Data/VolumeSave.txt");
MusicPlayer.mediaPlayer.Open(new Uri("./Example Items/Music/NeverGonnaGiveYouUp.mp3", UriKind.RelativeOrAbsolute));
MusicSlider.AddHandler(MouseLeftButtonDownEvent, new MouseButtonEventHandler(WhenMovingMusicSlider), true);
MusicSlider.AddHandler(MouseLeftButtonUpEvent, new MouseButtonEventHandler(SyncMusicProgressToSlider), true);
timer.Interval = TimeSpan.FromSeconds(0.01);
timer.Tick += Update;
timer.Start();
}
private void SongProgress_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double>? e)
{
UpdateSongProgress();
}
private void ChooseSong(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "MP3 files (*.mp3)|*.mp3|All files (*.*)|*.*";
openFileDialog.Multiselect = false;
if (openFileDialog.ShowDialog() == true)
{
MusicPlayer.mediaPlayer.Open(new Uri(openFileDialog.FileName));
TagLib.File tagFile = TagLib.File.Create(openFileDialog.FileName);
TagLib.IPicture coverArt = tagFile.Tag.Pictures[0];
if(coverArt != null)
{
MemoryStream ms = new MemoryStream(coverArt.Data.Data);
ms.Seek(0, SeekOrigin.Begin);
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = ms;
bitmap.EndInit();
SongCover.ImageSource = bitmap;
}
SongName.Text = tagFile.Tag.Title;
ArtistName.Text = tagFile.Tag.FirstAlbumArtist;
MusicPlayer.mediaPlayer.Open(new Uri(openFileDialog.FileName, UriKind.RelativeOrAbsolute));
if (MusicPlayer.isPlaying)
{
MusicPlayer.mediaPlayer.Play();
}
MusicSlider.Value = 0;
while(!MusicPlayer.mediaPlayer.NaturalDuration.HasTimeSpan)
{
}
}
}
bool nisse;
private void SyncMusicProgressToSlider(object sender, MouseButtonEventArgs e)
{
while(MusicPlayer.mediaPlayer.Position != TimeSpan.FromSeconds(MusicSlider.Value))
{
MusicPlayer.mediaPlayer.Position = TimeSpan.FromSeconds(MusicSlider.Value);
}
songProgressDrag = false;
}
private void WhenMovingMusicSlider(object sender, MouseButtonEventArgs e)
{
songProgressDrag = true;
}
void Update(object? sender, EventArgs e)
{
if (MusicPlayer.mediaPlayer.NaturalDuration.HasTimeSpan)
{
if (!songProgressDrag && MusicPlayer.isPlaying)
{
MusicSlider.Value = MathF.Round((float)MusicPlayer.mediaPlayer.Position.TotalSeconds);
}
if (MusicPlayer.repeat && MusicSlider.Value == MusicSlider.Maximum && !songProgressDrag)
{
MusicPlayer.mediaPlayer.Position -= MusicPlayer.mediaPlayer.Position;
MusicSlider.Value = 0;
}
if (!MusicPlayer.repeat && MusicSlider.Value == MusicSlider.Maximum && !songProgressDrag)
{
MusicPlayer.mediaPlayer.Position -= MusicPlayer.mediaPlayer.Position;
MusicSlider.Value = 0;
PlayButton.IsChecked = false;
}
}
PlayButton.IsChecked = MusicPlayer.isPlaying;
if (MusicPlayer.isPlaying)
{
PauseIcon.Visibility = Visibility.Visible;
PlayIcon.Visibility = Visibility.Hidden;
}
else
{
PauseIcon.Visibility = Visibility.Hidden;
PlayIcon.Visibility = Visibility.Visible;
}
if (fadeIn)
{
if (MusicPlayer.mediaPlayer.Volume < VolumeSlider.Value / 100)
{
i += VolumeSlider.Value / 100 / 12;
MusicPlayer.mediaPlayer.Volume = i;
}
else
{
MusicPlayer.mediaPlayer.Volume = VolumeSlider.Value / 100;
fadeIn = false;
}
}
if (fadeOut)
{
if (MusicPlayer.mediaPlayer.Volume > 0)
{
i -= VolumeSlider.Value / 100 / 12;
MusicPlayer.mediaPlayer.Volume = i;
}
else
{
MusicPlayer.mediaPlayer.Volume = 0;
MusicPlayer.Pause();
MusicSlider.Value = MathF.Round((float)MusicPlayer.mediaPlayer.Position.TotalSeconds);
fadeOut = false;
}
}
UpdateSongProgress();
}
private void UpdateSongProgress()
{
MusicSlider.Maximum = Convert.ToDouble(MathF.Round((float)MusicPlayer.mediaPlayer.NaturalDuration.TimeSpan.TotalSeconds));
TimeSpan length = TimeSpan.FromSeconds(MathF.Round((float)Convert.ToDouble(MusicPlayer.mediaPlayer.NaturalDuration.TimeSpan.TotalSeconds)));
TimeSpan progress = TimeSpan.FromSeconds(MusicSlider.Value);
string songLength = string.Format("{0:D2}:{1:D2}",
length.Minutes,
length.Seconds);
string songProgress = string.Format("{0:D2}:{1:D2}",
progress.Minutes,
progress.Seconds);
if (songLength.Length == 5 && songLength.StartsWith("0"))
{
SongValueTotal.Text = songLength.Remove(0, 1);
}
else if (songLength.Length == 5 && !songLength.StartsWith("0"))
{
SongValueTotal.Text = songLength;
}
else if (songLength.Length == 8 && songLength.StartsWith("0"))
{
SongValueTotal.Text = songLength.Remove(0, 1);
}
else if (songLength.Length == 8 && !songLength.StartsWith("0"))
{
SongValueTotal.Text = songLength;
}
if (songProgress.Length == 5 && songProgress.StartsWith("0"))
{
SongValueProgress.Text = songProgress.Remove(0, 1);
}
else if (songProgress.Length == 5 && !songProgress.StartsWith("0"))
{
SongValueProgress.Text = songProgress;
}
else if (songProgress.Length == 8 && songProgress.StartsWith("0"))
{
SongValueTotal.Text = songLength.Remove(0, 1);
}
else if (songProgress.Length == 8 && !songProgress.StartsWith("0"))
{
SongValueTotal.Text = songLength;
}
}
private void VolumeChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
MusicPlayer.mediaPlayer.Volume = VolumeSlider.Value / 100;
}
public void Pause(object sender, RoutedEventArgs e)
{
PauseIcon.Visibility = Visibility.Hidden;
PlayIcon.Visibility = Visibility.Visible;
MusicPlayer.isPlaying = false;
fadeOut = true;
fadeIn = false;
i = VolumeSlider.Value / 100;
}
public void Play(object sender, RoutedEventArgs e)
{
PauseIcon.Visibility = Visibility.Visible;
PlayIcon.Visibility = Visibility.Hidden;
if (MusicPlayer.mediaPlayer.NaturalDuration.HasTimeSpan)
{
MusicPlayer.Play();
}
MusicPlayer.isPlaying = true;
fadeIn = true;
fadeOut = false;
i = 0;
}
public void RepeatOn(object sender, RoutedEventArgs e)
{
RepeatButtonDot.Visibility = Visibility.Visible;
MusicPlayer.repeat = true;
}
public void RepeatOff(object sender, RoutedEventArgs e)
{
RepeatButtonDot.Visibility = Visibility.Hidden;
MusicPlayer.repeat = false;
}
protected override void OnClosed(EventArgs e)
{
Write(VolumeSlider.Value, "./Data/VolumeSave.txt");
base.OnClosed(e);
Application.Current.Shutdown();
}
private void Write(object sender, string url)
{
sw = new StreamWriter(url);
sw.WriteLine(sender.ToString());
sw.Close();
}
private double Read(object sender, string url)
{
sr = new StreamReader(url);
sender = Convert.ToDouble(sr.ReadLine());
sr.Close();
return (double)sender;
}
private void FillHomeButton(object sender, RoutedEventArgs e)
{
HomeButtonSelected.Visibility = Visibility.Visible;
HomeButtonUnselected.Visibility = Visibility.Hidden;
HomeButtonText.Foreground = System.Windows.Media.Brushes.White;
}
private void UnfillHomeButton(object sender, RoutedEventArgs e)
{
HomeButtonUnselected.Visibility = Visibility.Visible;
HomeButtonSelected.Visibility = Visibility.Hidden;
HomeButtonText.Foreground = new SolidColorBrush(System.Windows.Media.Color.FromRgb(70,70,70)); /*(Brush) new BrushConverter().ConvertFrom("#b3b3b3");*/
}
private void ExitPlaylistCustomizer(object sender, RoutedEventArgs e)
{
CustomizePlaylistPopup.Visibility = Visibility.Hidden;
}
}
public static partial class MusicPlayer
{
public static bool isPlaying;
public static bool repeat;
public static MediaPlayer mediaPlayer = new MediaPlayer();
public static void Play()
{
var mainWindow = (MainWindow)Application.Current.MainWindow;
if (mediaPlayer.NaturalDuration.HasTimeSpan)
{
mediaPlayer.Play();
}
isPlaying = true;
}
public static void Pause()
{
mediaPlayer.Pause();
isPlaying = false;
}
}
}
另外,这里是我在xaml中的滑块,如果你需要的话:
<Slider IsManipulationEnabled="True" TickFrequency="1" x:Name="MusicSlider" ValueChanged="SongProgress_ValueChanged" IsSnapToTickEnabled="True" IsMoveToPointEnabled="True" Style="{StaticResource Horizontal_Slider}"
VerticalAlignment="Center" Margin="50,0,50,0"/>
1条答案
按热度按时间ugmeyewa1#
通过单击滑块轨道移动滑块似乎不会触发
MouseLeftButtonDownEvent
。因此,计时器逻辑可能会在触发MouseLeftButtonUpEvent
之前还原滑块的值。我不知道这个问题的直接解决方案。也许通过
ValueChanged
事件同步滑块值和媒体播放器会更好。