Mis à jour le mardi 23 mai 2017
  • 20 heures
  • Facile

Ce cours est visible gratuitement en ligne.

Ce cours existe en livre papier.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

TP : ZBiblio, la bibliothèque de films

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Pour mettre ce qu'on a vu en pratique, j'ai trouvé comme idée de TP une petite bibliothèque de films. Cette bibliothèque va bien sûr travailler surtout avec un objet de votre cru qui contiendra un film.

Bon, je ne vous en dis pas plus, passons au cahier des charges.

Le cahier des charges

Comme dans chaque TP, je vais quand même vous laisser faire ça vous-mêmes.

Donc je vais vous donner un cahier des charges, et quelques informations. Tout cela a pour but de vous guider et d'axer vos recherches et vos idées.

Eh oui, parce que les TP qu'on commence à attaquer sont d'une certaine envergure, vous allez vous confronter à des problèmes auxquels vous ne trouverez sûrement pas de solution dans ce TP (tout dépend de la manière dont vous abordez la situation). Il va donc sûrement falloir (si vous êtes un minimum courageux et que vous ne sautez pas directement à la solution) que vous fassiez quelques recherches sur Google (je ne fais pas de pub :-° ) ou alors dans la MSDN de Microsoft, une bibliothèque recensant toutes les fonctions intégrées au framework (une annexe ne tardera pas à sortir la concernant). Sinon, si votre problème n'a aucune solution, vous pouvez toujours demander une petite aide sur le forum du SdZ, section Autres langages, en faisant précéder le titre de votre sujet par [VB.NET], ça aide à les distinguer.

Bien, bien, excusez-moi, je m'égare, le cahier des charges donc.

Ce TP a pour but de vous faire développer une bibliothèque de films (vous pouvez bien sûr transformer des films en musiques, images…). Je vais vous laisser libre cours concernant le design et les méthodes de programmation. Je vous donne juste quelques conseils :

  • Les films dans la bibliothèque devront être listés dans une liste avec possibilité d'ouvrir la fiche d'un film pour plus d'informations.

  • La fiche d'un film contiendra des informations basiques : nom, acteurs, date de sortie, synopsis, tout ce que votre esprit pourra imaginer.

  • La possibilité de créer, modifier et supprimer un film (autrement dit la fiche d'un film).

  • Et pourquoi pas une fonction de recherche, dans de grandes collections de films.

Concernant la réalisation, je l'ai déjà dit, je le répète, vous faites comme vous voulez.
Quelques conseils cependant :

  • Un objet Film ou FicheFilm serait de rigueur pour contenir les informations d'une fiche de film.

  • Une collection pour contenir toutes vos fiches ne serait pas une mauvaise idée…

  • La sérialisation pour stocker vos films (je dis ça, je dis rien).

Alors bien évidemment, comme pour les autres TP, ne sautez pas directement à la solution. Essayez de chercher un minimum. Ce TP n'a rien de compliqué en soi, il va juste falloir que vous trouviez la bonne méthode pour agir entre les films et la liste. Bref, une réflexion qui a du bon.

Courage et à l'attaque. :)

La correction

Avant tout, je tiens à dire que la correction n'est pas universelle. Elle servira juste à ceux qui n'ont absolument pas réussi à manipuler les objets et autres collections à s'en tirer un minimum. Mais si vous n'avez rien compris à ce TP et si vous n'avez pas été capables d'en réaliser une ébauche, je ne saurais que vous conseiller de recommencer la lecture de la partie sur la POO.

Pour les autres, chaque situation étant différente, je vais tâcher de vous présenter un programme aussi concis et universel que possible.

Mon programme est composé de deux fenêtres. La première regroupant les fonctions de recherche, liste et visualisation d'une fiche. La seconde permettant la création et la modification d'une fiche.

Je vais déjà vous détailler les deux fenêtres aux figures suivantes.

Image utilisateur

Fenêtre principale. Name : ZBiblio

Image utilisateur

Fenêtre d'ajout/modification. Name : AjoutEditionFilm

Voici mes deux fenêtres. Quelques contrôles spécifiques. Un DateTimePickerpour la sélection de la date et un NumericUpDownpour la sélection de la note.

Vous avez sans doute remarqué les DropDownListpour les genres et le réalisateur. Elles sont là pour une fonctionnalité ultérieure qui permettra d'insérer les acteurs et genres déjà remplis sur des films pour permettre un choix rapide. Mais en attendant on peut s'en servir comme de simples textbox en utilisant la propriété Text.

Je vous demanderai de vous passer de moqueries sur mes interfaces :lol: , je n'ai jamais eu l'âme d'un designer. :(

Bien, bien, passons aux feuilles de code.

La classe Film
Public Class Film

    Private _Nom As String
    Public Property Nom As String
        Get
            Return _Nom
        End Get
        Set(ByVal value As String)
            _Nom = value
        End Set
    End Property

    Private _DateSortie As Date
    Public Property DateSortie As Date
        Get
            Return _DateSortie
        End Get
        Set(ByVal value As Date)
            _DateSortie = value
        End Set
    End Property

    Private _Realisateur As String
    Public Property Realisateur As String
        Get
            Return _Realisateur
        End Get
        Set(ByVal value As String)
            _Realisateur = value
        End Set
    End Property

    Private _Genre1 As String
    Public Property Genre1 As String
        Get
            Return _Genre1
        End Get
        Set(ByVal value As String)
            _Genre1 = value
        End Set
    End Property

    Private _Genre2 As String
    Public Property Genre2 As String
        Get
            Return _Genre2
        End Get
        Set(ByVal value As String)
            _Genre2 = value
        End Set
    End Property

    Private _Acteurs As String
    Public Property Acteurs As String
        Get
            Return _Acteurs
        End Get
        Set(ByVal value As String)
            _Acteurs = value
        End Set
    End Property

    Private _Synopsis As String
    Public Property Synopsis As String
        Get
            Return _Synopsis
        End Get
        Set(ByVal value As String)
            _Synopsis = value
        End Set
    End Property

    Private _RemarquePerso As String
    Public Property RemarquePerso As String
        Get
            Return _RemarquePerso
        End Get
        Set(ByVal value As String)
            _RemarquePerso = value
        End Set
    End Property

    Private _NotePerso As Integer
    Public Property NotePerso As Integer
        Get
            Return _NotePerso
        End Get
        Set(ByVal value As Integer)
            _NotePerso = value
        End Set
    End Property

    Public Sub New()

    End Sub

    Public Sub New(ByVal Nom As String, ByVal DateSortie As Date, ByVal Realisateur As String, ByVal Genre1 As String, ByVal Genre2 As String, ByVal Acteurs As String, ByVal Synopsis As String, ByVal RemarquePerso As String, ByVal NotePerso As Integer)
        _Nom = Nom
        _DateSortie = DateSortie
        _Realisateur = Realisateur
        _Genre1 = Genre1
        _Genre2 = Genre2
        _Acteurs = Acteurs
        _Synopsis = Synopsis
        _RemarquePerso = RemarquePerso
        _NotePerso = NotePerso
    End Sub

    Public Sub Update(ByVal Nom As String, ByVal DateSortie As Date, ByVal Realisateur As String, ByVal Genre1 As String, ByVal Genre2 As String, ByVal Acteurs As String, ByVal Synopsis As String, ByVal RemarquePerso As String, ByVal NotePerso As Integer)
        _Nom = Nom
        _DateSortie = DateSortie
        _Realisateur = Realisateur
        _Genre1 = Genre1
        _Genre2 = Genre2
        _Acteurs = Acteurs
        _Synopsis = Synopsis
        _RemarquePerso = RemarquePerso
        _NotePerso = NotePerso
    End Sub

    'Je surcharge le Tostring
    Public Overrides Function ToString() As String
        Return _Nom
    End Function

End Class

Beaucoup de lignes pour ce qui concerne les propriétés. Mais c'est un passage obligé. :)

Le constructeur a deux signatures (une signature étant une façon de l'appeler) grâce à une surcharge. Une avec arguments, l'autre sans.

Une méthode Update permettant la mise à jour en une ligne de tous les attributs de la fiche.

Et finalement une surcharge de ToString spécifiant qu'il faut retourner le nom du film lorsque j'utiliserai cette fonction.

La fenêtre principale : ZBiblio
Imports System.Xml.Serialization
Imports System.IO

Public Class ZBiblio

    Private _FenetreAjout As AjoutEditionFilm
    Private _FilmEnVisualisation As Film
    Private _ListeFilms As List(Of Film)
    Public Property ListeFilms As List(Of Film)
        Get
            Return _ListeFilms
        End Get
        Set(ByVal value As List(Of Film))
            _ListeFilms = value
        End Set
    End Property

    Private Sub ListeFilms_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        'Instancie une nouvelle liste
        _ListeFilms = New List(Of Film)

        'Récupère les infos
        Deserialisation()

        'MAJ la liste de films
        UpdateListe()

    End Sub

    Private Sub ListeFilms_FormClosing(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.FormClosing
        'Sérialise les films lors de la fermeture
        Serialisation()
    End Sub

    Private Sub LB_LISTE_FILMS_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LB_LISTE_FILMS.SelectedIndexChanged

        'On vérifie qu'on a sélectionné quelque chose
        If Not Me.LB_LISTE_FILMS.SelectedItem Is Nothing Then
            'Retrouve le film avec ce nom
            For Each FilmALister As Film In _ListeFilms
                If FilmALister.Nom = LB_LISTE_FILMS.SelectedItem.ToString Then
                    'L'insère dans une variable globale
                    Me._FilmEnVisualisation = FilmALister
                End If
            Next

            'On MAJ les infos de la fiche
            Me.LBL_TITRE.Text = Me._FilmEnVisualisation.Nom
            Me.LBL_DATE_SORTIE.Text = Me._FilmEnVisualisation.DateSortie.ToShortDateString 'La date seule
            Me.LBL_GENRE1.Text = Me._FilmEnVisualisation.Genre1
            Me.LBL_GENRE2.Text = Me._FilmEnVisualisation.Genre2
            Me.LBL_REALISATEUR.Text = Me._FilmEnVisualisation.Realisateur
            Me.LBL_ACTEURS.Text = Me._FilmEnVisualisation.Acteurs
            Me.LBL_SYNOPSIS.Text = Me._FilmEnVisualisation.Synopsis
            Me.LBL_AVIS_PERSONNEL.Text = Me._FilmEnVisualisation.RemarquePerso
            Me.LBL_NOTE.Text = Me._FilmEnVisualisation.NotePerso

        End If

    End Sub

    Public Sub UpdateListe()
        'On vide la liste et on la reremplit
        Me.LB_LISTE_FILMS.Items.Clear()
        'Parcourt les films de la bibliothèque
        For Each FilmALister As Film In _ListeFilms
            'Remplit la liste en se basant sur le nom (vu que j'ai surchargé ToString)
            'A le même effet que FilmALister.Nom sans la surcharge.
            Me.LB_LISTE_FILMS.Items.Add(FilmALister)
        Next
    End Sub

#Region "Boutons modif fiche"

    Private Sub BT_SUPPRIMER_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_SUPPRIMER.Click

        'Confirmation
        If MsgBox("Etes vous certain de vouloir supprimer ce film ?", vbYesNo, "Confirmation") Then
            'On le retire de la liste
            Me._ListeFilms.Remove(_FilmEnVisualisation)
        End If

        'MAJ
        UpdateListe()

    End Sub

    Private Sub BT_NOUVELLE_FICHE_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_NOUVELLE_FICHE.Click
        'Si nouveau film, on passe nothing
        _FenetreAjout = New AjoutEditionFilm(Nothing)
        _FenetreAjout.Show()
    End Sub

    Private Sub BT_MAJ_FICHE_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_MAJ_FICHE.Click
        'Si une MAJ, on passe le paramètre du film actuel
        _FenetreAjout = New AjoutEditionFilm(_FilmEnVisualisation)
        _FenetreAjout.Show()
    End Sub

#End Region

#Region "Sauvegarde et récupération"

    Private Sub Deserialisation()
        If File.Exists("BibliothequeFilm.xml") Then
            'On ouvre le fichier et récupère son flux
            Dim FluxDeFichier As Stream = File.OpenRead("BibliothequeFilm.xml")
            Dim Deserialiseur As New XmlSerializer(GetType(List(Of Film)))
            'Désérialisation et conversion de ce qu'on récupère dans le type « Film »
            _ListeFilms = Deserialiseur.Deserialize(FluxDeFichier)
            'Fermeture du flux
            FluxDeFichier.Close()
        End If
    End Sub

    Private Sub Serialisation()
        'On crée le fichier et récupère son flux
        Dim FluxDeFichier As FileStream = File.Create("BibliothequeFilm.xml")
        Dim Serialiseur As New XmlSerializer(GetType(List(Of Film)))
        'Sérialisation et écriture
        Serialiseur.Serialize(FluxDeFichier, _ListeFilms)
        'Fermeture du fichier
        FluxDeFichier.Close()
    End Sub

#End Region

#Region "Section recherche"

    Private Sub RemplissageChampsRecherche()
        'Fonction utilisée plus tard pour préremplir les DDL de genres, réalisateurs…
    End Sub

    Private Sub BT_RECHERCHE_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_RECHERCHE.Click
        Recherche()
    End Sub

    Private Sub BT_EFFACER_RECHERCHE_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_EFFACER_RECHERCHE.Click
        Me.TXT_TITRE.Text = ""
        Me.DDL_ACTEUR.Text = ""
        Me.DDL_ANNEE.Text = ""
        Me.DDL_GENRE.Text = ""
        Me.DDL_REALISATEUR.Text = ""

        UpdateListe()
    End Sub

    Private Sub Recherche()

        'On vide la liste et on la reremplit
        Me.LB_LISTE_FILMS.Items.Clear()
        'Parcourt les films de la bibliothèque
        For Each FilmALister As Film In _ListeFilms

            If Me.TXT_TITRE.Text <> "" Then
                If FilmALister.Nom.Contains(Me.TXT_TITRE.Text) Then
                    Me.LB_LISTE_FILMS.Items.Add(FilmALister)
                End If
            End If

            If Me.DDL_ACTEUR.Text <> "" Then
                If FilmALister.Acteurs.Contains(Me.DDL_ACTEUR.Text) Then
                    Me.LB_LISTE_FILMS.Items.Add(FilmALister)
                End If
            End If

            If Me.DDL_ANNEE.Text <> "" Then
                If CDate(FilmALister.DateSortie).Year = Me.DDL_ANNEE.Text Then
                    Me.LB_LISTE_FILMS.Items.Add(FilmALister)
                End If
            End If

            If Me.DDL_GENRE.Text <> "" Then
                If FilmALister.Genre1.Contains(Me.DDL_GENRE.Text) Or FilmALister.Genre2.Contains(Me.DDL_GENRE.Text) Then
                    Me.LB_LISTE_FILMS.Items.Add(FilmALister)
                End If
            End If

            If Me.DDL_REALISATEUR.Text <> "" Then
                If FilmALister.Realisateur.Contains(Me.DDL_REALISATEUR.Text) Then
                    Me.LB_LISTE_FILMS.Items.Add(FilmALister)
                End If
            End If

        Next

    End Sub

#End Region

End Class

Cette fenêtre contient les fonctions de sérialisation et désérialisation. En ce qui concerne la sérialisation, elle s'effectue automatiquement lors de la fermeture de la fenêtre (autrement dit du programme). La désérialisation, quant à elle, se lance au démarrage du programme en vérifiant bien évidemment la présence du fichier XML.

Une propriété permettant de modifier la variable _ListeFilms est publique de façon à pouvoir être appelée depuis l'autre fenêtre. Il en va de même pour la méthode Update.

Pour le reste, je pense que mes commentaires sont assez explicites. :D

Fenêtre d'ajout et de modification
Public Class AjoutEditionFilm

    Private _FilmAModifier As Film

    Sub New(ByVal FilmAModifier As Film)

        ' Cet appel est requis par le concepteur.
        InitializeComponent()

        ' Ajoutez une initialisation quelconque après l'appel InitializeComponent().

        'Récupère le film à modifier
        _FilmAModifier = FilmAModifier

    End Sub

    Private Sub AjoutEditionFilm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        If _FilmAModifier Is Nothing Then
            'S'il ne contient rien, on en crée un nouveau
        Else
            'Sinon on recupère les infos et on les entre dans les cases correspondantes
            Me.TXT_ACTEURS.Text = _FilmAModifier.Acteurs
            Me.TXT_AVIS_PERSONNEL.Text = _FilmAModifier.RemarquePerso
            Me.TXT_NOM.Text = _FilmAModifier.Nom
            Me.TXT_SYNOPSIS.Text = _FilmAModifier.Synopsis
            Me.DDL_GENRE1.Text = _FilmAModifier.Genre1
            Me.DDL_GENRE2.Text = _FilmAModifier.Genre2
            Me.DDL_REALISATEUR.Text = _FilmAModifier.Realisateur
            Me.NUM_NOTE.Value = _FilmAModifier.NotePerso
            Me.DT_DATE_SORTIE.Value = _FilmAModifier.DateSortie
        End If

    End Sub

    Private Sub BT_SAVE_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BT_SAVE.Click

        If _FilmAModifier Is Nothing Then
            'Enregistre notre film
            Dim MonFilm As New Film(Me.TXT_NOM.Text, Me.DT_DATE_SORTIE.Value, Me.DDL_REALISATEUR.Text, Me.DDL_GENRE1.Text, Me.DDL_GENRE2.Text, Me.TXT_ACTEURS.Text, Me.TXT_SYNOPSIS.Text, Me.TXT_AVIS_PERSONNEL.Text, Me.NUM_NOTE.Value)
            'On l'ajoute à la liste
            ZBiblio.ListeFilms.Add(MonFilm)
            MsgBox("Fiche correctement crée", vbOKOnly, "Confirmation")
        Else
            'Sinon on le modifie en récupérant son index dans la liste de la fenêtre parent
            ZBiblio.ListeFilms(ZBiblio.ListeFilms.IndexOf(_FilmAModifier)).Update(Me.TXT_NOM.Text, Me.DT_DATE_SORTIE.Value, Me.DDL_REALISATEUR.Text, Me.DDL_GENRE1.Text, Me.DDL_GENRE2.Text, Me.TXT_ACTEURS.Text, Me.TXT_SYNOPSIS.Text, Me.TXT_AVIS_PERSONNEL.Text, Me.NUM_NOTE.Value)
        End If

        'MAJ de la liste dans la fenêtre parent
        ZBiblio.UpdateListe()
        'Ferme la fenêtre d'édition
        Me.Close()
    End Sub

    Private Sub IMG_AFFICHE_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles IMG_AFFICHE.Click
        'Ultérieur ; possibilité d'ajouter une fiche.
    End Sub

End Class

J'ai ajouté manuellement le constructeur de cette fenêtre. Lorsque vous créez le constructeur, automatiquement il ajoute :

' Cet appel est requis par le concepteur.
        InitializeComponent()

        ' Ajoutez une initialisation quelconque après l'appel InitializeComponent().

Il ne faut surtout pas l'effacer, c'est ce qui initialise les éléments graphiques. Ajoutez ce que vous voulez après. Personnellement j'ai demandé un argument au constructeur, cet argument étant le film à modifier. Si c'est nothingqui est passé, cela signifie que c'est une nouvelle fiche qu'il faut créer.

Pour le reste, même remarque : les commentaires doivent être assez clairs à mon avis.

Si un problème vient à vous bloquer, n'hésitez pas à laisser un commentaire sur ce chapitre, en détaillant votre problème.

Améliorations possibles

Concernant les amélioration possibles, je pense qu'il y a vraiment possibilité de faire évoluer ce petit logiciel jusqu'à le rendre agréable à l'utilisation.

  • Ajout d'une affiche de film. Cette affiche pourrait être sauvegardée dans un dossier les regroupant toutes.

  • Remplir mes DDL, ajouter autant d'éléments que de possibilités. Par exemple, pour les genres. Faites une recherche sur tous les genres de tous les films et créez une fonction permettant de les distinguer afin de garder des genres distincts, pas de double. Ce n'est qu'une idée. :)

  • Améliorer un peu l'interface, faire pourquoi pas un système d'onglets, une image de fond, etc.

Cette liste n'est évidemment pas exhaustive, elle ne dépend que de votre imagination. Je prévois cependant d'améliorer ce TP lors de la partie concernant les bases de données et une troisième version à la fin du tutoriel complet.

Exemple de certificat de réussite
Exemple de certificat de réussite