none
MS Chart Farbpalette in der LegendCell verwenden RRS feed

  • Frage

  • Moin Forum,

    ich komme leider mit einem Problem nicht richtig weiter und hoffe auf eure Hilfe. Ich erzeuge dynamisch Serien in meinem Chart. Jetzt will ich eine Legende erstellen in der ich die einzelnen Serien über eine Checkbox ein- und ausblenden kann. Da gibt es ja auch ein schönes Beispiel in den Chart Samples.

    Legende soll so aussehen das erst das bmp mit der Checkbox dargestellt wird, dann eine Linie mit der Farbe  und der Name der Serie. Jetzt habe ich das Problem das in meiner Legende keine Farben der Serie angezeigt werden. Ich würde die gerne der Palette verwenden, da ja dynamisch x beliebige erzeugt werden können.

    Sobald ich isVisibleInLegend auf True setze, tauchen natürlich alle Einträge doppelt in der Legende auf, die einen mit der richtigen Farbzuordnung und die anderen (Cell) ohne Farbe. Setze ich die Farbe manuell über Color funktioniert es, ist aber nicht das was ich will.

       Dim LegendItem1 As LegendItem
        Dim LegendCell1 As LegendCell
        Dim LegendCell2 As LegendCell
        Dim LegendCell3 As LegendCell
    
        Dim Legend1 As Legend = New Legend
        ChartK1Logger.Palette = ChartColorPalette.Berry
    
        For Each n As clsK1Logger In myclassIC40.Instance.LogData.K1LoggerElements.Values
        
          
          ChartK1Logger.Series.Add(n.Name.ToString)
          
          ChartK1Logger.Series(n.Name.ToString).ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line
          ChartK1Logger.Series(n.Name.ToString).IsVisibleInLegend = False
          
          LegendItem1 = New LegendItem
          
          LegendCell1 = New LegendCell
          LegendCell1.CellType = System.Windows.Forms.DataVisualization.Charting.LegendCellType.Image
          LegendCell1.Image = "C:\subversion\Tools\BCSoft4\trunk\IC40\Resources\chk_checked.png"  
          
          LegendCell2 = New LegendCell
          LegendCell2.CellType = System.Windows.Forms.DataVisualization.Charting.LegendCellType.SeriesSymbol
          
          LegendCell3 = New LegendCell
          LegendCell3.Text = n.Name.ToString
          
          LegendItem1.Cells.Add(LegendCell1)
          LegendItem1.Cells.Add(LegendCell2)
          LegendItem1.Cells.Add(LegendCell3)
          LegendItem1.ImageStyle = System.Windows.Forms.DataVisualization.Charting.LegendImageStyle.Line
          LegendItem1.Name = n.Name
          
          Legend1.CustomItems.Add(LegendItem1)
    
          ChartK1Logger.Series(n.Name).ChartArea = "ChartArea1"
        Next
    
        Me.ChartK1Logger.Legends.Add(Legend1)

    Vielleicht kann mir ja jemand helfen und mir sagen was ich hier nicht beachte. Vielen Dank schonmal.

    Gruß

    Michael


    • Bearbeitet MiLampe Donnerstag, 6. Juli 2017 08:53
    Donnerstag, 6. Juli 2017 08:05

Antworten

  • und so sieht das im Beispiel aus.

    Zunächst im Kopf die Farbtabelle anlegen, damit kannst Du auch schön Deine eigene Farben vorgeben:

    Dim lstColors As List(Of Color) = New List(Of Color)
    lstColors.Add(Color.Red)
    lstColors.Add(Color.Blue)
    lstColors.Add(Color.Yellow)
    lstColors.Add(Color.Green)
    lstColors.Add(Color.Aqua)
    lstColors.Add(Color.Cyan)

    und dann bei der Farbzuweisung:

    ' die nächste Zeile durch die übernächste ersetzen
    'ser.Color = Color.FromArgb(255, r.Next(0, 256), r.Next(0, 256), r.Next(0, 256))
    ser.Color = lstColors(Offset - 1)

    Das Ergebnis sieht bei mir dann so aus:

    Grüße

    Roland


    • Bearbeitet Roland Franz Donnerstag, 13. Juli 2017 12:00
    • Als Antwort markiert MiLampe Donnerstag, 13. Juli 2017 12:10
    Donnerstag, 13. Juli 2017 11:49

Alle Antworten

  • Hallo Michael,

    versuche doch einmal vor der Schleife die bereits im Control enthaltenen Legenden zu löschen.

    .
    .
    .
    ChartK1Logger.Palette = ChartColorPalette.Berry
    ChartK1Logger.Legends.Clear()   'Das sind die zwei neuen Zeilen
    ChartK1Logger.Series.Clear()    ' """ 
    For Each n As clsK1Logger In lstseries
    .
    .
    .

    Falls das nicht Dein Problem ist, könntest Du mal bitte einen Screenshot von Deiner legende machen?

    Grüße

    Roland

    Donnerstag, 6. Juli 2017 13:25
  • Hallo Roland,

    das hat leider nicht funktioniert.

    Habe gerade festgestellt, dass ich noch keine Bilder hochladen darf. Ich versuch das dann mal zu beschreiben. Wie lange dauert das denn, bis ich überprüft wurde?

    Wenn ich den Code wie oben verwende, habe ich eine Legende mit allen Einträgen (Series). Ein Legendeneintrag besteht aus einem Legenditem mit jeweils 3 Zellen. 1. Bitmap der Checkbox, 2. Farbe der Serie und 3. der Name. Wenn ich forecolor der 2. Zelle auf Rot setze, wird die Linie auch in Rot dargestellt.

     ChartK1Logger.Series(n.Name.ToString).ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line
          ChartK1Logger.Series(n.Name.ToString).IsVisibleInLegend = False


    Wenn ich IsVisibleInLegend auf True setze, habe ich quasi 2. Legenden. Es wird aber nur eine Legende mit new von mir erzeugt. Alle Einträge sind jetzt doppelt da. Also eine Legende mit allen Serien, so wie ich es haben will, daneben noch eine komplette Legende so wie sie vom Chart erzeugt wird (Darstellung Linie mit der Farbe der Serie und der entsprechende Text.  Ich schaffe es nicht das er sich die Farben aus der Palette nimmt.

    Vielleicht gibt es ja noch eine einfachere/bessere Möglichkeit, wie man Serien über eine "Checkbox" ein- und abschalten kann.

    Bin leider erst am Montag wieder da und kann mich dann erst wieder um meine Legende kümmern.

    Schönes Wochenende

    Gruß

    Michael


    • Bearbeitet MiLampe Donnerstag, 6. Juli 2017 14:04
    Donnerstag, 6. Juli 2017 14:03
  • Hallo Michael,

    es ist in der tat schwierig Custom Items mit normalen Items in der Legende zu mischen. Dabei müsste man ganz geziehlt einzelen Elemente aus der Legende nachträglich etfernen.

    Als Alternative könnte ich Dir eine Selektion über separate Checkboxen z.B. in einer GroupBox zeigen.

    Das hat zwar den Nachteil, dass die Legende und die Auswahlcheckbox nicht an einer Stelle liegen, dafür ist der Programmcode relativ einfach.

    Zunächst würde ich Dir gerne zeigen wie die Oberfläche damit aussieht.

    Zunächst mit allen Reihen ausgewählt:

    Und hier nur die erste und fünfte Reihe ausgewählt:

    Der komplette Programmcode für das Beispiel sieht so aus:

        Dim lstseries As List(Of clsK1Logger) = New List(Of clsK1Logger) '***Nur zum Testen eingebaut
        Dim cht As Chart
        Dim ser As Series
    
        lstseries.Add(New clsK1Logger("Reihe1"))    '*** Nur zum Testen eingebaut
        lstseries.Add(New clsK1Logger("Reihe2"))
        lstseries.Add(New clsK1Logger("Reihe3"))
        lstseries.Add(New clsK1Logger("Reihe4"))
        lstseries.Add(New clsK1Logger("Reihe5"))
    
        cht = ChartK1Logger
        cht.Palette = ChartColorPalette.Berry
        cht.Series.Clear()
        Dim Offset As Integer = 1
        For Each n As clsK1Logger In lstseries
            ser = cht.Series.Add(n.Name)                         '*** an meine testumgebung angepasst
            ser.ChartType = SeriesChartType.Line
            ser.IsVisibleInLegend = True
            ser.ChartArea = "ChartArea1"
            For index = 1 To 10                                  '***Nur zum Testen eingebaut
                ser.Points.AddXY(index, index * index * Offset)  '***Eigene Testdaten
            Next
            Offset += 1
            cb = New CheckBox()                     '*** ab hier werden dynamisch die
            cb.Left = 10                            '*** Checkboxen aufgebaut
            cb.Top = (Offset - 1) * 20
            cb.Name = n.Name
            cb.Text = n.Name
            cb.Checked = True
            AddHandler cb.CheckedChanged, AddressOf cb_CheckedChanged
            gbReihen.Controls.Add(cb)
        Next
    End Sub
    Private Sub cb_CheckedChanged(sender As Object, e As EventArgs) Handles cb.CheckedChanged
        Dim cb As CheckBox
        cb = sender
        ChartK1Logger.Series.Item(cb.Name).Enabled = cb.Checked
    End Sub

    Die Checkboxen werde in dem Beispiel ebenfalls dynamisch mit jeder reieh angelegt.

    Gegenüber Deinem Beispiel enhält der Code ein paar Zeilen mit dem ich mir Testdaten erzeuge, das musst Du natürlich wieder an Deine Daten anpassen.

    Grüße

    Roland



    Freitag, 7. Juli 2017 11:37
  • Hallo Roland,

    Danke für deine Antwort. Diese Version habe ich in der Vergangenheit auch gehabt. Finde es aber so unglücklich, weil unnötig viel Platz verschwendet wird.

    So wie in dem Bild (kommt von den Microsoft Chart samples) würde ich es auch gerne machen, nur in dem Beispiel sind die Farben der einzelnen Serien fest definiert. Ich möchte die gerne aus einer Palette verwenden.

    Im 2. Bild ist mein derzeitiger Zustand. Die rechte Hälfte der Legende kann ich über VisibleInLegend = False ausblenden. Links ist so wie ich es gerne hätte, nur leider fehlen die Farben der Serie. Ich denke das muß doch irgendwie gehen. Wenn nicht, muß ich wohl den alten Weg über die Checkboxen machen.


    • Bearbeitet MiLampe Mittwoch, 12. Juli 2017 07:55
    Mittwoch, 12. Juli 2017 07:43
  • Hallo Michael,

    wie sieht es damit aus?

    Grüße

    Roland

    Mittwoch, 12. Juli 2017 09:58
  • Hier noch mal eine Ausschnittsvergrößerung:

    Mittwoch, 12. Juli 2017 10:00
  • Hallo Roland,

    das geht ja schon in die richtige Richtung. Wie hast du denn die Farbzuweisung der einzelnen Serien umgesetzt? Das ist ja genau das, was bei mir irgendwie nicht funktioniert.

    Gruß

    Michael

    Mittwoch, 12. Juli 2017 11:36
  • Hallo Michael,

    wenn es das ist was Du suchst, könnte ich Dir ein Beispiel erstellen.

    Grüße

    Roland

    Mittwoch, 12. Juli 2017 11:42
  • Hallo Roland,

    das hilft mir schon. Hätte es eigentlich lieber mit der costumized Legend gelöst, wie in dem Microsoft Beispiel, aber wenn das nicht anders zu lösen ist, bau ich mir die Legende selber. Danke dir für deinen Einsatz.

    Gruß

    Michael

    Mittwoch, 12. Juli 2017 12:01
  • wenn es das ist was Du suchst, könnte ich Dir ein Beispiel erstellen.

    Hallo,

    bist du schon vorangekommen mit dem Beispiel?

    Danke Michael

    Donnerstag, 13. Juli 2017 08:36
  • Hallo Michael,

    das war ein Missverständnis, ich dachte mit Deiner Aussage "ich baue mir die Legende selber" wäre das erledigt. Aber kein Problem das Beispiel ist schnell erstellt.

    In ein paar Minuten werde ich das hier einstellen.

    Grüße

    Roland

    Donnerstag, 13. Juli 2017 09:04
  • Hier das Beispiel:

        Private Sub btnEigeneLegende_Click(sender As Object, e As EventArgs) Handles btnEigene.Click
            Dim lstseries As List(Of clsK1Logger) = New List(Of clsK1Logger) '***Nur zum Testen eingebaut
            Dim cht As Chart
            Dim ser As Series
            gbLegende.Visible = True
            lstseries.Add(New clsK1Logger("Reihe1"))    '*** Nur zum Testen eingebaut
            lstseries.Add(New clsK1Logger("Reihe2"))
            lstseries.Add(New clsK1Logger("Reihe3"))
            lstseries.Add(New clsK1Logger("Reihe4"))
            lstseries.Add(New clsK1Logger("Reihe5"))
            lstseries.Add(New clsK1Logger("Reihe6"))
            lstseries.Add(New clsK1Logger("Reihe7"))
            lstseries.Add(New clsK1Logger("Reihe8"))
    
            cht = ChartK1Logger
            cht.Palette = ChartColorPalette.Berry
            cht.Series.Clear()
            Dim Offset As Integer = 1
            Dim r As New Random
            Dim intSeriesCount As Integer = lstseries.Count
    
            gbLegende.Height = intSeriesCount * 20 + 25
            For Each n As clsK1Logger In lstseries
    
                ser = cht.Series.Add(n.Name)                         '*** an meine testumgebung angepasst
                'ser.ChartType = SeriesChartType.Line
                ser.ChartType = SeriesChartType.Spline
                ser.Color = Color.DarkRed
                ser.Color = Color.FromArgb(255, r.Next(0, 256), r.Next(0, 256), r.Next(0, 256))
                ser.IsVisibleInLegend = False
                ser.ChartArea = "ChartArea1"
                For index = 1 To 10                                  '***Nur zum Testen eingebaut
                    ser.Points.AddXY(index, index * index * Offset)  '***Eigene Testdaten
                Next
    
                Offset += 1
                cb = New CheckBox()                     '*** ab hier werden dynamisch die
                cb.Left = 10                            '*** Checkboxen aufgebaut
                cb.Top = (Offset - 1) * 20
                cb.Name = n.Name
                cb.Text = "---  " + n.Name
                cb.ForeColor = ser.Color
                cb.Checked = True
                AddHandler cb.CheckedChanged, AddressOf cb_CheckedChanged
                gbLegende.Controls.Add(cb)
            Next
    
        End Sub
        Private Sub cb_CheckedChanged(sender As Object, e As EventArgs) Handles cb.CheckedChanged
            Dim cb As CheckBox
            cb = sender
            ChartK1Logger.Series.Item(cb.Name).Enabled = cb.Checked
        End Sub
    

    Die GroupBox habe ich in die obere rechte Ecke des Fensters geklebt, die lässt sich aber auch in das Diagramm setzten.

    Die Anfangsposition musst Du noch an Deine Form anpassen:

        Me.gbLegende.Anchor = CType((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.gbLegende.BackColor = System.Drawing.Color.White
        Me.gbLegende.FlatStyle = System.Windows.Forms.FlatStyle.Flat
        Me.gbLegende.Location = New System.Drawing.Point(1073, 0)
        Me.gbLegende.Name = "gbLegende"
        Me.gbLegende.Size = New System.Drawing.Size(134, 495)
        Me.gbLegende.TabIndex = 3
        Me.gbLegende.TabStop = False
        Me.gbLegende.Text = "Legende"
     

    Donnerstag, 13. Juli 2017 09:10
  • Danke dir,

    Die Farben der Serien werden ja bei dir über einen Random Wert festgelegt. Das bedeutet, es können auch identische bzw, sehr ähnliche Farben in einer Chart vorhanden sein.

    Gruß

    Michael

    Donnerstag, 13. Juli 2017 11:24
  • Klar ist ja nur ein Beispiel.

    Für den praktischen Nutzen würde ich eine Farbtabelle anlegen aus der ich mich dann bediene.

    Grüße

    Roland

    Donnerstag, 13. Juli 2017 11:38
  • und so sieht das im Beispiel aus.

    Zunächst im Kopf die Farbtabelle anlegen, damit kannst Du auch schön Deine eigene Farben vorgeben:

    Dim lstColors As List(Of Color) = New List(Of Color)
    lstColors.Add(Color.Red)
    lstColors.Add(Color.Blue)
    lstColors.Add(Color.Yellow)
    lstColors.Add(Color.Green)
    lstColors.Add(Color.Aqua)
    lstColors.Add(Color.Cyan)

    und dann bei der Farbzuweisung:

    ' die nächste Zeile durch die übernächste ersetzen
    'ser.Color = Color.FromArgb(255, r.Next(0, 256), r.Next(0, 256), r.Next(0, 256))
    ser.Color = lstColors(Offset - 1)

    Das Ergebnis sieht bei mir dann so aus:

    Grüße

    Roland


    • Bearbeitet Roland Franz Donnerstag, 13. Juli 2017 12:00
    • Als Antwort markiert MiLampe Donnerstag, 13. Juli 2017 12:10
    Donnerstag, 13. Juli 2017 11:49
  • Fein, so gehts.

    Da hast du dir quasi eine Palette selber erstellt. Das sollte ja auch mit meinen customItems in der Legende funktionieren. Einfach die Farbe der Serie und die Legende auf die eigene Farbpalette abstimmen. Probiere ich gleich mal aus.

    Ganz lieben Dank für die Lösung und deinen Einsatz.

    Gruß

    Michael

    Donnerstag, 13. Juli 2017 12:10