2016-03-25 6 views
3

Mit dem Diagrammsteuerelement System.Windows.Forms.DataVisualization.Charting.Chart mache ich ein Streudiagramm.Bildformat in WindowsForms einschränken Datenvisualisierungstabelle

Wie kann ich es so beschränken, dass der Maßstab der X-Achse der Maßstab der Y-Achse entspricht?

Das Steuerelement selbst so zu setzen, dass es quadratisch ist, reicht nicht aus, da es interne Ränder zum Zeichnen und Beschriften der Achsen hat, die nicht gleich sind.

Ich könnte eine bestimmte Größe wählen und zwicken es zu quadratisch sein, aber es muss sowohl quadratisch und veränderbar sein.

Ich habe High und Low in der Dokumentation und im Eigenschaftenbrowser gesucht, aber ich kann nichts finden oder keine Möglichkeiten finden, es in der Größenanpassung zu tun.

Antwort

4

Dies ist eine gute Frage, aber leider gibt es keine einfache Lösung wie die beiden Axes Sperren oder einen Wert einstellen ..

ist, indem man die entsprechenden Spieler beginnen lassen:

  • Die Chart Kontrolle hat eine innere Size namens ClientSize, die Chart.Size minus die Grenzen ist. Beide Größen werden in Pixel gemessen.

  • Im Inneren kann es einen oder mehrere ChartAreas geben. Jeder hat eine Position, die vom Typ ElementPosition ist.

  • Innerhalb jedes ChartArea ist das ein Bereich, der für das tatsächliche Zeichnen der Punkte verwendet wird; es heißt InnerPlotPosition.

Die InnerPlotPosition Eigenschaft definiert, um das Rechteck innerhalb eines Diagramms Flächenelement, das zum Plotten von Daten verwendet wird; Ausgenommen sind Teilstriche, Achsenbeschriftungen und so weiter. Die für diese Eigenschaft verwendeten Koordinaten (0,0 bis 100,100) beziehen sich auf das ChartArea-Objekt und nicht auf das gesamte Diagramm.

Die InnerPlotPosition-Eigenschaft kann zum Ausrichten mehrerer Diagrammbereiche verwendet werden. Wenn jedoch ein Diagrammbereich über Teilstriche und Achsenbeschriftungen verfügt und nicht über einen anderen verfügt, können ihre Achsenlinien nicht ausgerichtet werden.

  • Sowohl ChartArea.Position und ChartArea.InnerPlotPosition enthalten nicht nur die Lage aber auch die Größe der Bereiche; Alle Werte sind in Prozent des äußeren Bereichs, dh ChartArea.InnerPlotPosition ist relativ zu ChartArea.Position und ChartArea.Position ist relativ zu Chart.ClientSize. Alle Prozentsätze gehen von 0-100.

So ist die ChartArea umfasst Labels und Legends sowie Axes und TickMarks ..

Was wir wollen, ist, einen Weg zu finden, den InnerPlotArea Platz zu machen, dh sie haben die gleiche Breite und Höhe in Pixel . Die Prozentsätze reichen nicht!

Beginnen wir mit ein paar einfachen Berechnungen; wenn diese die Daten sind wir haben ..:

// we'll work with one ChartArea only..: 
    ChartArea ca = chart1.ChartAreas[0]; 
    ElementPosition cap = ca.Position; 
    ElementPosition ipp = ca.InnerPlotPosition; 

.. dann sind dies die Pixelgrößen der beiden Bereiche:

// chartarea pixel size: 
    Size CaSize = new Size((int)(cap.Width * chart1.ClientSize.Width/100f), 
          (int)(cap.Height * chart1.ClientSize.Height/100f)); 

    // InnerPlotArea pixel size: 
    Size IppSize = new Size((int)(ipp.Width * CaSize.Width/100f), 
          (int)(ipp.Height * CaSize.Height/100f)); 

Idealerweise würden wir den InnerPlotArea gerne Platz sein; Da die kleine Seite nicht sehr gut wachsen kann (sonst würde die Grafik überziehen), müssen wir die größere verkleinern. Also ist die neue Pixelgröße des InnerPlotArea

int ippNewSide = Math.Min(IppSize.Width, IppSize.Height); 

Was nun? Da die Chart.Size gerade eingestellt wurde, wollen wir uns nicht damit anlegen. Wir sollten auch nicht mit Zohan an der ChartArea: Es muss noch Raum der Legend etc halten ..

Also haben wir die Größe des InnerPlotArea ändern ..:

zuerst eine Klassenstufe Variable erstellen, um die ursprünglichen Werte zu speichern, die InnerPlotPosition:

ElementPosition ipp0 = null; 

Wir werden es brauchen, um die ursprünglichen Prozentsatz, dh die Margen zu halten, um sie zu verwenden, wenn die neue Berechnung. Wenn wir das Diagramm anpassen werden die dann aktuellen, bereits geändert/verzerrt worden ..

Dann erstellen wir eine Funktion, um die InnerPlotArea Platz zu machen, die es auf den Packungen:

void makeSquare(Chart chart) 
{ 
    ChartArea ca = chart.ChartAreas[0]; 

    // store the original value: 
    if (ipp0 == null) ipp0 = ca.InnerPlotPosition; 

    // get the current chart area : 
    ElementPosition cap = ca.Position; 

    // get both area sizes in pixels: 
    Size CaSize = new Size((int)(cap.Width * chart1.ClientSize.Width/100f), 
          (int)(cap.Height * chart1.ClientSize.Height/100f)); 

    Size IppSize = new Size((int)(ipp0.Width * CaSize.Width/100f), 
          (int)(ipp0.Height * CaSize.Height/100f)); 

    // we need to use the smaller side: 
    int ippNewSide = Math.Min(IppSize.Width, IppSize.Height); 

    // calculate the scaling factors 
    float px = ipp0.Width/IppSize.Width * ippNewSide; 
    float py = ipp0.Height/IppSize.Height * ippNewSide; 

    // use one or the other: 
    if (IppSize.Width < IppSize.Height) 
     ca.InnerPlotPosition = new ElementPosition(ipp0.X, ipp0.Y, ipp0.Width, py); 
    else 
     ca.InnerPlotPosition = new ElementPosition(ipp0.X, ipp0.Y, px, ipp0.Height); 

} 

Sie nennen würde die Funktion nach oder während der Größenänderung.

private void chart1_Resize(object sender, EventArgs e) 
{ 
    makeSquare(chart1); 
} 

Hier kann die Funktion bei der Arbeit ist:

Originalgröße: original

Zwängt ein wenig: scaled

und machte Platz wieder: square

Hinweis wie das grüne ChartArea reserviert genug Platz für die Labels und die Legend und wie die automatische Skalierung für die Achsen noch funktioniert .. Aber die X-Axis Etiketten passen jetzt nicht in eine Zeile. Beachten Sie auch, dass die ChartArea.BackColoreigentlich nur die Farbe der InnerPlotArea ist!

Beachten Sie, dass Sie haben können, die Variable ipp0 zu aktualisieren, um die geänderten Prozentsätze beziehen sich, nachdem sie auf die ChartArea Layout wie Vergrößern oder Verschieben oder Entfernen von Legends oder Ändern der Größe oder Winkel von Labels machen Modifikation etc ..

Of Natürlich können Sie die Funktion ändern, um in einem anderen Verhältnis zu übergeben, anstatt die Fläche ein Quadrat zu halten.

+0

Awesome, vielen Dank! Können Sie den Zweck von 'cip0' erklären? –

+0

Wir werden es brauchen, um die ursprünglichen Prozentsätze, d. H. Die Ränder, zu behalten, um sie bei der Berechnung der neuen zu verwenden. Wenn wir das Diagramm anpassen, werden die aktuellen bereits geändert/verzerrt. – TaW

+0

Ich denke, um meine Frage zu klären, wofür steht es/wie soll es initialisiert werden? Ich sehe, was "ipp0" darstellt und wo es initialisiert werden soll, aber nicht "cip0". –