"Slider" Lecteur multimedia
Bonjour,
je dois faire un lecteur multimedia dans un cours à l'école. J'ai un petit problème avec ma barre de temps qui suit la vidéo. J'utilise un dispatcher timer pour synchroniser ma petite barre avec ma vidéo, cependant étant donné que je change la valeur de la barre, la fonction _ValueChanged est appelé et mon vidéo a donc de petit "Lag". Voici mon code pour mieux me comprendre.
Code:
1 2 3 4
| private void dispatcherTimer_Tick(object sender, EventArgs e)
{
timeSlider.Value = mediaElement1.Position.TotalMilliseconds;
} |
Code:
1 2 3 4 5 6
| private void timeSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
int sliderValue = (int)timeSlider.Value;
TimeSpan ts = new TimeSpan(0, 0, 0, 0, sliderValue);
mediaElement1.Position = ts;
} |
Donc lorsque mon timer "Tick" il synchronise la barre avec la vidéo. Par la suite il appelle timeSlider_ValueChanged parce que ma valeur à changé et il synchronise par la suite la vidéo avec la barre. Donc parfois cela crée de petit "Lag".
Quelqu'un aurait des suggestions pour régler ce conflit?
Edit: Je travaille avec Visual Studio 2010
mediaelement et maj position du slider
bonjour joce21
Pourquoi passer par un timer et un dispatcherTimer alors que l'api WPF dispose dispose du MediaTimeLine et d'une horloge ad hoc utilisable par un MediaElement
De plus le "clock" du MediaElement dispose d'un controller pour l'interactivite.
Comme l'illustre le bout de code suivant:
code xaml du WinForm
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
<Window x:Class="WpfMediaPlayerCSharp.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<DockPanel>
<Grid DockPanel.Dock="Bottom">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="2"
Content="Stop"
Click="Stop_Click" />
<Button
Grid.Column="3"
Content="Play"
Click="Play_Click" />
<ToggleButton
Grid.Column="4"
Content="Mute"
IsChecked="{Binding ElementName=mediaElement,
Path=IsMuted}" />
<Slider
Grid.Column="5"
Minimum="0"
Maximum="1"
Value="{Binding ElementName=mediaElement, Path=Volume}"/>
</Grid>
<Slider
x:Name="progressSlider"
DockPanel.Dock="Bottom"
Minimum="0"
LargeChange="1000"
PreviewMouseLeftButtonDown="progressSlider_MouseDown"
PreviewMouseLeftButtonUp="progressSlider_MouseUp"/>
<MediaElement
x:Name="mediaElement"
DockPanel.Dock="Top"
Source="Resources\Bear.wmv"
LoadedBehavior="Manual"
MediaOpened="mediaElement_MediaOpened"
MediaEnded="mediaElement_MediaEnded"/>
</DockPanel>
</Window> |
code behind du winform:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
|
//1-Affecter l'horloge de la chronologie du MediaTimeLine au MediaElement
//2-S'abonner à l'evenement clock.CurrentTimeInvalidated de l'horloge
// pour mettre à jour la position du bouton slider
//3-Horloge dispose du controller qui permet de :
//- demarrer ,suspendre,reprendre interactivement la lectur du MediaMediaElement
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfMediaPlayerCSharp
{
/// <summary>
/// Logique d'interaction pour Window1.xaml
/// </summary>
public partial class Window1 : Window
{
private bool _userMovingSlider ;
public Window1()
{
InitializeComponent();
}
private void mediaElement_MediaOpened(object sender, RoutedEventArgs e)
{
//A l'ouverture du media fixer valeur max bouton slider
this.progressSlider.Maximum =
this.mediaElement.NaturalDuration.TimeSpan.TotalMilliseconds;
}
private void Play_Click(object sender, RoutedEventArgs e)
{
MediaClock clock=this.mediaElement.Clock;
//un media est en cours de lecture
if (clock !=null)
{
if (clock.IsPaused)
{
clock.Controller.Resume();
}
else
{
clock.Controller.Pause();
}
}
else //sinon
{
//aucun fichier charge =>return
if (this.mediaElement == null) return;
//sinon nouveau media => initialiser creer un MediaTimeline
//=> affecter son horloge au MediaElement
//=> s'abonner à event horloge
MediaTimeline timeline = new MediaTimeline(this.mediaElement.Source);
clock = timeline.CreateClock();
clock.CurrentTimeInvalidated += new EventHandler(Clock_CurrentTimeInvalidated);
this.mediaElement.Clock = clock;
}
}
private void Stop_Click(object sender, RoutedEventArgs e)
{
//mettre horloge à null
this.mediaElement.Clock = null;
}
private void mediaElement_MediaEnded(object sender, RoutedEventArgs e)
{
//mettre horloge à null
this.mediaElement.Clock = null;
}
private void Clock_CurrentTimeInvalidated(object sender, EventArgs e)
{
//si horloge null(aucun media en cours)
//ou user deplace bouton slider =>return
if (this.mediaElement.Clock == null || _userMovingSlider) return;
//sinon mise à jour position du slider
this.progressSlider.Value =
this.mediaElement.Clock.CurrentTime.Value.TotalMilliseconds;
}
private void progressSlider_MouseDown(object sender, MouseButtonEventArgs e)
{
//user deplace bouton slider
_userMovingSlider = true;
}
private void progressSlider_MouseUp(object sender, MouseButtonEventArgs e)
{
MediaClock clock=this.mediaElement.Clock;
//user a deplace puis relache bouton slider
//mais horloge non nulle(un media en cours de lecture)
//avancer horloger à la position du slider
if (clock !=null)
{
TimeSpan m_offset= TimeSpan.FromMilliseconds(this.progressSlider.Value);
clock.Controller.Seek(m_offset, TimeSeekOrigin.BeginTime);
}
//prepare prochaine interaction user
_userMovingSlider = false;
}
}
} |
bon code..........
event preview=event descendant ,event normal =du control remonte vers racine
bonjour joce21
voici un petit resume comme l'as dit Pol63 de la difference entre un event normal et un event preview.
1/tous les controls wpf possedent :
-un event normal de type Input :mousedown,keydown...
-et un event counter-part ou "contrepartie" : previewmousedown et previewkeydown.
2/Un preview event est declenche en premier par la racine et descend sur le controle qui a le focus et qui a ete actionne(mouse ou keyboard ).=> tunneling ou descente de l'event depuis la racine vers le controle .
2/Suivi de l'event normal qui est ensuite declenche par le control qui a le focus =>ensuite bubbling ou remonte depuis le controle vers la racine.
Conclusion pratique :
-quand on declenche un event de type input il y une contrepartie preview et vice-versa.
-le preview est genere "avant" dans le temps et dans "l'espace" car les controles parents le voient "descendre" avant le control qui a genere l'action.
-exactement le contraire pour l'event normal qui survient apres et vu par les childs avant les parents
exemple dans la douce langue de shakeaspeare donnee par un auteur de code:
Citation:
When you press a key with an element in focus, first the PreviewKeyDown event is
raised by the root element and tunnels down the tree to the actual element that was
in focus; then the KeyDown event is raised and bubbles back up to the root.
bon code...........