IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Création de sous objet dans une classe


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Inscrit en
    Juillet 2013
    Messages
    777
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 777
    Par défaut Création de sous objet dans une classe
    Bonjour,

    Je suis en train de construire ma première classe (ouff!!)
    Ma problématique est assez générale mais je la présente à travers un exemple :
    Ma classe consiste à créer un modèle de chart personnalisé.
    Ce chart personnalisé contient 2 ChartAreas.
    Je suppose que cela commence donc ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Public Class CustomChart
    Inherits system.Windows.forms.DataVisualization.Charting.Chart
     
    Sub New()
    MyBase.New()
     
    Me.ChartAreas.Add("c1")
    Me.ChartAreas.Add("c2")
    ...
    Mais je remarque que si, dans un form, j'ai déjà créé un contrôle CustomChart, et si j'en crée un deuxième, ça plante parce que le nom des ChartAreas est forcé et identique dans les deux instances de CustomChart.

    D'où ma question, comment faire en sorte que le nom de l'instance des ChartAreas soit créé par défaut et incrémenté en temps que de besoin (par exemple "ChartAreas1, ChartAreas2...")

  2. #2
    Membre éclairé
    Inscrit en
    Juillet 2013
    Messages
    777
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 777
    Par défaut
    Bon alors je m'autocorrige :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Public Class CustomChart
    Inherits system.Windows.forms.DataVisualization.Charting.Chart
     
    Private _pie as New ChartArea
    Private _bar as New ChartArea
     
    Sub New()
    MyBase.New()
     
     
    Me.ChartAreas.Add(pie)
    Me.ChartAreas.Add(bar)
    ...
    N'empêche, quand je crée une instance depuis la boîte à outil, le contrôle se se dessine avec une apparence qui laisse penser que ma sub new a été correctement interprétée et est complète , mais l'exécution en mode débug provoque une erreur me disant que "ChartArea1 existe déjà dans ChartAreaCollection". cette erreur survient en fin de l'instruction Form.show() où Form est le form dans lequel j'ai glissé mon CustomChart

    Je progresse, mais c'est pas encore ça ...

  3. #3
    Membre éclairé
    Inscrit en
    Juillet 2013
    Messages
    777
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 777
    Par défaut
    En fait je m'aperçois que le pb vient de la sub dans laquelle j'implémente mon code.

    Donc résumons ; je veux créer un CustomChart avec juste 2 ChartAreas et 2 séries. Le code "utile" se résume à ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
            With Me
                .ChartAreas.Add(_pie)
                .ChartAreas.Add(_bar)
                .Legends.Add(_legend)
                .Series.Add(_series1)
                .Series.Add(_series2)
                End With
    Je m'aperçois que l'erreur provoquée citée plus haut vient du fait que je mets ce code dans la Sub New

    Je tatonne, je vois qu'il existe une sub InitialLayout mais si je mets le code dedans, le code est exécuté 2 fois :
    - une fois lors du rapatriement en mode design du contrôle : je me retrouve avec un chart contenant 3 chartAreas et 3 séries (j'en déduis au passage que, dans ce cas, le Chart créé contient déjà, par défaut, 1 chartarea et 1 série)
    - une autre fois lors de l'exécution : je me retrouve avec un chart contenant 5 chartareas et 5 séries.

    Donc le pb est que je n'ai pas compris, quand on personnalise un controle existant en créant une classe dérivée :
    - dans quel sub il faut implanter le code "utile" (par exemple, dans le tuto de P. Lasserre, on voit que ce code est implanté dans "OnPaint" pour un bouton)
    - dans quel cas il faut ajouter dans cette sub "Mybase.New" (dans la sub new) et "Mybase.mysub" (dans la protected sub mysub()). J'ai en effet tenté avec ou sans et je n'ai pas vu la différence.

    J'imagine que pour répondre à ces questions, il faut comprendre ce qui se passe dans la boîte du contrôle mère. Je n'ai pas trouvé dans les tutos réponse à ces questions.

    Qqun peut-il m'aider ou m'indiquer un tuto un peu plus complet que celui de P. Lasserre sur ces questions précises ?

  4. #4
    Membre Expert Avatar de _Ez3kiel
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2013
    Messages
    836
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Janvier 2013
    Messages : 836
    Par défaut
    Je n'y connais absolument rien en Chart, mais je veux bien essayer de t'aider.

    Déjà, j'ai du mal à saisir ton souci, concrètement.

    Dans ton control personnalisé, tu dois lui donner un constructeur Public Sub New()Ton control du fait qu'il hérite de system.Windows.forms.DataVisualization.Charting.Chart, il possède les propriétés de cette classe Windows, mais il faut les initialiser, et c'est ce que fait la Public Sub New() de la classe de Windows. Mais dans ta classe à toi ce n'est pas fait, bien que tu hérites de cette dernière.
    Du coup, il faut que tu appelles la Public Sub New() de la classe windows dans ta propre Public Sub New(), et ça se fait avec MyBase.New() (MyBase désignant la classe mère dont tu hérites)

    D'un point de vue code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            Public Sub New()
                MyBase.New() ' <--- Appelle le New de system.Windows.forms.DataVisualization.Charting.Chart
     
            End Sub
    Donc résumons ; je veux créer un CustomChart avec juste 2 ChartAreas et 2 séries.
    Et donc où est le souci ?

    Dans ton application, tu instancieras tonControlChart de type CustomChart et tu joueras avec ses properties .chartAreas() et .Series() que ta classe possédera vu qu'elle hérite de celle de Windows.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Public Class Form1
     
    Private sub bttn_click(sender,e) handles bttn.click
     
    Dim tonControlChar as New CustomChart
    Dim pie as new ChartArea
    Dim bar as new ChartArea
     
    tonControlChart.chartAreas.Add(pie)
    tonControlChart.chartAreas.Add(bar)
     
     
    end sub
    End class

  5. #5
    Membre éclairé
    Inscrit en
    Juillet 2013
    Messages
    777
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 777
    Par défaut
    Bonjour Ez3kiel et merci de ton aide.

    Alors quand je dis que je ma classe se résume à la création de 2 chartareas et 2 series, c'est pour simplifier à sa plus simple expression pour montrer aussi où se trouve l'exception générée.

    Donc voici le code simplifié mais complet de la classe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    Imports System.Windows.Forms.DataVisualization.Charting
     
    Public Class CustomChart
        Inherits System.Windows.Forms.DataVisualization.Charting.Chart
     
        Private components As System.ComponentModel.IContainer
        Private _pie As New ChartArea
        Private _bar As New ChartArea
        Private _series1 As New Series
        Private _series2 As New Series
        Private _legend As New Legend
     
     
        Public Sub New()
            MyBase.New()
     
            'affichage graphique
            With Me
                .ChartAreas.Add(_pie)
                .ChartAreas.Add(_bar)
                .Legends.Add(_legend)
                .Series.Add(_series1)
                .Series.Add(_series2)
     
            End With
            '...
        End Sub
    End Class
    Si je n'avais que cela à faire, je créerais ces éléments dans le form comme tu le préconises, mais c'est en fait le préambule à beaucoup d'autres propriétés des constituants du Chart que je fige au travers d'un code basique qui vient remplacer les points de suspension de la ligne 26. Je ne les détaille pas (sauf si tu le souhaites) car ce code n'apporte rien à la résolution du pb. Il y en a une page A4 (voire 2) de lignes de code car je fige pas mal de paramètres des chart areas + des séries + de la légende etc... D'où l'intérêt de le faire une fois et une seule dans un customchart que j'appelle ensuite plusieurs fois dans mon projet.

    Donc, si tu veux bien, on peut se concentrer sur le code ci-dessus même si sur le fond, je suis d'accord, il ne semble pas justifier la création d'une classe spécifique.

    J'ai donc bien mis la sub New (j'avais testé avec et sans) mais ça n'empêche pas l'erreur évoquée précédemment.

    Je crée un form1, j'y glisse le CustomChart depuis la boîte à outil. tout se passe bien.
    Dans mon form principal je crée un bouton pour ouvrir le form1

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Private Sub Formprincipal_bouton_click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MonBouton.Click
            Form1.Show()
        End Sub
    Un débug pas à pas montre que le code se déroule dans l'ordre suivant :
    - lecture de form1.show()
    - lecture de la sub New de la classe CustomChart jusqu'à End Sub
    -surlignage en jaune de Form1.Show avec l'exception générée "Une erreur s'est produite lors de la création du formulaire. Pour plus d'informations, consultez Exception.InnerException. L'erreur est : Un élément de graphique portant le nom « ChartArea1 » existe déjà dans « ChartAreaCollection »."

    A fait 2 jours que je suis sur ce pb. Je n'ai pas trouvé la solution mais j'ai émis des hypothèses :
    - la sub New est lue 2 fois : une fois lorsque je glisse le contrôle depuis la boîte à outil vers le form, une 2ème fois lorsque j'exécute l'appli (comme le montre le pas à pas sus-évoqué)
    - le code que j'ai dénommé "utile" ne doit pas se trouver dans la sub new mais ailleurs. Si c'est le cas, où ? Ce qui me fait penser à cela c'est qu'il y a pas mal d'exemples de boutons personnalisés (notamment dans le tuto de P. Lasserre) où les modifications sont mises dans le OnPaint et non dans la Sub New.

    J'espère que c'est plus clair...

  6. #6
    Membre Expert
    Homme Profil pro
    Développeur .Net / Delphi
    Inscrit en
    Juillet 2002
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Développeur .Net / Delphi
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2002
    Messages : 738
    Par défaut
    Bonjour,

    Je ne connais pas non plus vraiment Chart.
    A priori, l'ajout des ChartArea dans la collection a toute sa place au niveau du constructeur de la classe (Sub New()).
    Note : Les Exemples de code que tu as pu voir de boutons personnalisés sont situés dans l'évènement OnPaint car il s'agit de code de dessins. Cet évènement est généré par windows au moment du rendu lors de chaque rafraîchissement du control. Pour dessiner, c'est là que ça se passe. Mais ce n'est pas ton cas...

    Concernant l'erreur sur les ChartArea, ne faut-il pas leur donner un nom ? Il y a une surcharge du constructeur permettant de le faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Private _pie As New ChartArea("pie")
        Private _bar As New ChartArea("bar")
    Cela évitera d'avoir 2 ChartArea1...

    eb.

  7. #7
    Membre Expert Avatar de _Ez3kiel
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2013
    Messages
    836
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Janvier 2013
    Messages : 836
    Par défaut
    Citation Envoyé par noftal Voir le message
    - la sub New est lue 2 fois : une fois lorsque je glisse le contrôle depuis la boîte à outil vers le form, une 2ème fois lorsque j'exécute l'appli (comme le montre le pas à pas sus-évoqué)
    C'est une hypothèse exacte, lorsque tu déposes ton control dans le designer, il doit écrire le code de celui-ci dans son Designer.Vb afin de le déclarer et de définir les valeurs de ses propriétés, et pour ce faire, il lance le Sub New pour instancier ces valeurs.


    Ton souci ici c'est que quand tu déposes ton customControl, il fait MyBase.New() (Donc le New de la classe Windows) OR ce New instancie par défaut une ChartArea qu'il appelle ChartArea1, une Legend qu'il appelle Legend1 et une Serie qu'il appelle Series1.

    PUIS, toi tu lui dis d'instancier _pie, _bar, _serie12, etc, Or par défaut, tes ChartArea et autres n'ayant pas de nom, elle prennent un nom "par défaut" qui est malheureusement ChartArea1, ce qui fait planter car cette dernière a déjà été instancié par le MyBase.New()


    Soit tu donnes un nom à tes instances (autres que les noms qu'utilisent Windows comme ChartArea1 etc):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        Private _pie As New ChartArea("CA1")
        Private _bar As New ChartArea("CA2")
        Private _series1 As New Series("S1")
        Private _series2 As New Series("S2")
        Private _legend As New Legend("L1")
    Mais tu auras ton graphique ET le graphique d'initialisation de Windows.

    Soit tu te passes de ton MyBase.New(), ainsi, tes instances _pie etc prendra la valeur ChartArea1 par défaut, et vu que Windows n'aura pas instancié ses propres ChartArea, pas de conflit de nom !

    Ps: N'oublie pas de supprimer ton control de ton Form et de le remettre quand tu fais des tests, il régénère son Designer à chaque fois



    OU 3éme solution, tu fais les 2 du haut, pas de MyBase.New ET nommage des variables.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    Imports System.Windows.Forms.DataVisualization.Charting
     
    Public Class CustomChart
        Inherits System.Windows.Forms.DataVisualization.Charting.Chart
     
     
        Private _pie As New ChartArea("CA1")
        Private _bar As New ChartArea("CA2")
        Private _series1 As New Series("S1")
        Private _series2 As New Series("S2")
        Private _legend As New Legend("L1")
     
        Public Sub New()
            ' MyBase.New() 'On ne le met pas comme ça Windows n'instancie pas de ChartArea par défaut
     
     
     
            With Me
                .ChartAreas.Add(_pie)
                .ChartAreas.Add(_bar)
                .Legends.Add(_legend)
                .Series.Add(_series1)
                .Series.Add(_series2)
     
            End With
        End Sub
     
     
    End Class

Discussions similaires

  1. [POO] Un objet dans une classe
    Par Arnich dans le forum Langage
    Réponses: 6
    Dernier message: 25/11/2007, 22h46
  2. Réponses: 1
    Dernier message: 19/07/2007, 12h39
  3. list d'objet dans une classe
    Par wadcyr8_197 dans le forum C++
    Réponses: 10
    Dernier message: 04/07/2007, 15h34
  4. Réponses: 8
    Dernier message: 12/04/2007, 11h32
  5. [POO] import d'objet dans une classe
    Par wdionysos dans le forum Langage
    Réponses: 3
    Dernier message: 01/04/2006, 21h05

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo