Frage zu zufällige Farbe und y Achse beschriften (Balkendiagramm)

Liebe Leute,

ich habe im Anhang vorher und nachher Bilder angehängt :slight_smile:

Ich habe ein Paar Fragen im Bezug meinem Code.
1.Warum bekomme ich immer die Farbe schwarz

  1. Wie kann ich Y Achse beschriften(Vielleicht einen Tipp)

Im Bezug andere Aufgabe, damit ich nicht so viele Beitrage mache :

  1. Wenn man ein Kreisdiagramm machen Möchte macht man doch fillOval
  2. Wenn man mit Prozente beschriften möchte verwendet man drawString und halt x und y Koordinate mit manuelle ausprobieren anpassen oder kann man die ausrechnen?
import java.awt.*;
import java.awt.event.*;

public class Balkendiagramm extends JFrame {
	MeineCanvas malflaeche;
	JButton but1, but2, but3, but4, but5, but6;
	int akt = 1;
	String[] monat = new String[] { "Jan", "Feb", "M‰rz", "April",
			"Mai", "Juni", "Juli", "Aug", "Sept", "Okt",
			"Nov", "Dez" };

	int[] h = new int[] { 150, 170, 140, 100, 15, 0, 30, 50, 100, 135, 160, 200 };

	Balkendiagramm() {
		setLayout(new FlowLayout());
		malflaeche = new MeineCanvas();
		JPanel p = new JPanel();
		p.setLayout(new GridLayout(6, 1, 40, 28));
		but1 = new JButton("Balken");

		add(malflaeche);
		p.add(but1);
		but1.addActionListener(new FZ());

	}

	class MeineCanvas extends Canvas {
		MeineCanvas() {
			setBackground(Color.WHITE);
		}

		public void paint(Graphics g) {
			if (akt == 0) {
				return;
			}
			if (akt == 1) {

				int x = 10;
				int b = 10;
				g.setColor(Color.red);
				g.drawLine(5, 20, 5, 250);
				g.drawLine(5, 250, 600, 250);

				for (int i = 0; i < 12; i++) {
					int rot = ((int) Math.random() * 256);
					int gruen = ((int) Math.random() * 256);
					int blau = ((int) Math.random() * 256);
					g.setColor(new Color(rot, gruen, blau));

					g.fillRect(x, 250 - h**, b, h**);

					g.drawString(monat**, x, 260);
					x = x + 50;
				}

			}

		}

		public Dimension getMinimumSize()
		{
			return new Dimension(800, 300);
		}

		public Dimension getPreferredSize() {
			return getMinimumSize();
		}

	}

	class FZ implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			String a = e.getActionCommand();
			if (a.equals("Balken")) {
				akt = 1;
			}
			
			malflaeche.repaint();
		}
	}

	public static void main(String args[]) {
		Balkendiagramm z = new Balkendiagramm();
		z.pack();
		z.setSize(800, 350);
		z.setVisible(true);
		z.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
	}
}```

[quote=anni80]int rot = ((int) Math.random() * 256); int gruen = ((int) Math.random() * 256); int blau = ((int) Math.random() * 256);[/quote]

Damit da schwarz rauskommt muss rot, gruen, blau 0 sein.
Wie kann das 0 sein?

Math.random() wird zu int gecastet und ist somit 0.
0 * 256 ist 0.

Die Lösung heißt richtig Klammern:

int gruen = ((int) (Math.random() * 256));
int blau = ((int) (Math.random() * 256));```

Meinst du mit Kreisdiagramm ein Tortendiagramm? Da würde fillOval ja nichts helfen, stattdessen würde man https://docs.oracle.com/javase/8/docs/api/java/awt/Graphics.html#fillArc-int-int-int-int-int-int- verwenden.

Besser ist aber in vieler Hinsicht (ohne da jetzt in die Details zu gehen), diese Funktionen nicht zu verwenden, sondern das ganze stattdessen über “Shape”-Objekte zu lösen. Die können dann in ein Graphics2D gezeichnet werden. Die Label-Position muss dann händisch ausgerechnet werden. Der First Shot wäre da, es “in die Mitte des Tortenstück-Randes” zu packen. Aber natürlich kann man da beliebig weit gehen. Wenn man die Vorteile will, ohne den Aufwand zu haben, kann man JFreeChart verwenden. Ansonsten hier ein kleines, billiges KSKB

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Arc2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


class SimplePieChart
{
    private final List<Double> values;
    private final List<String> labels;
    private final List<Color> colors;
    private double valueSum = 0;
    
    public SimplePieChart()
    {
        values = new ArrayList<Double>();
        labels = new ArrayList<String>();
        colors = new ArrayList<Color>();
    }
    
    void addSegment(double value, String label, Color color)
    {
        values.add(value);
        labels.add(label);
        colors.add(color);
        valueSum += value;
    }
    
    int getNumSegments()
    {
        return values.size();
    }
    
    Shape getSegmentShape(int index, double x, double y, double w, double h)
    {
        double accumulatedValue = 0;
        for (int i=0; i<index; i++)
        {
            accumulatedValue += values.get(i);
        }
        double angleRad = Math.PI * 2 * accumulatedValue / valueSum;
        double extentRad = Math.PI * 2 * values.get(index) / valueSum;
        
        Arc2D a = new Arc2D.Double(x, y, w, h, 
            Math.toDegrees(angleRad), 
            Math.toDegrees(extentRad), Arc2D.PIE);
        return a;
    }
    
    Color getSegmentColor(int index)
    {
        return colors.get(index);
    }
 
    Point2D getLabelPosition(int index, double x, double y, double w, double h)
    {
        double accumulatedValue = 0;
        for (int i=0; i<index; i++)
        {
            accumulatedValue += values.get(i);
        }
        double angleRad = Math.PI * 2 * accumulatedValue / valueSum;
        double extentRad = Math.PI * 2 * values.get(index) / valueSum;
        double labelAngleRad = angleRad + 0.5 * extentRad;
        
        double px = x + w * 0.5 + Math.cos(Math.PI * 2 - labelAngleRad) * w * 0.5;
        double py = y + h * 0.5 + Math.sin(Math.PI * 2 - labelAngleRad) * w * 0.5;
        return new Point2D.Double(px, py);
    }

    String getLabel(int index)
    {
        return labels.get(index);
    }
    
}

class SimplePieChartPanel extends JPanel
{
    private final SimplePieChart simplePieChart;
    
    public SimplePieChartPanel()
    {
        simplePieChart = new SimplePieChart();
        simplePieChart.addSegment(10, "Ten", Color.RED);
        simplePieChart.addSegment(20, "Twenty", Color.GREEN);
        simplePieChart.addSegment(30, "Thrity", Color.YELLOW);
        simplePieChart.addSegment(42, "Fourty-two", Color.PINK);
    }
    
    @Override
    protected void paintComponent(Graphics graphics)
    {
        super.paintComponent(graphics);
        Graphics2D g = (Graphics2D) graphics;
        
        double x = 100;
        double y = 100;
        double w = 400;
        double h = 400;
        for (int i=0; i<simplePieChart.getNumSegments(); i++)
        {
            g.setColor(simplePieChart.getSegmentColor(i));
            g.fill(simplePieChart.getSegmentShape(i, x, y, w, h));
            Point2D p = simplePieChart.getLabelPosition(i, x, y, w, h);
            g.setColor(Color.BLACK);
            g.drawString(simplePieChart.getLabel(i), (int)p.getX(), (int)p.getY());
        }
        
    }
}

public class SimplePieChartExample
{
    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("Paint on button click");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        SimplePieChartPanel p = new SimplePieChartPanel();
        p.setPreferredSize(new Dimension(600, 600));
        frame.getContentPane().add(p);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

@Marko13
bis ich kreisdiagramm so programmieren kann, werde ich 3 Leben brauchen, deswegen dachte ich dass ich wie Rechtecke programmieren
also da g.fillArc(50,50,200,200,anfang,ende); Anfang ist doch abfangwert von Kreisbogen, aber bei 2.Wert ende von erste ist Anfang von 2.

was mache ich falsch?wie kann man anderes Kreisbogen berechnen?


int[] ein = new int[] { 40, 45, 15 };
      public void paint(Graphics g) {
                              int value = 0;
				int anfang = 0;
				int ende = 0;

				value = (360 * ein[0]) / 100;
				anfang = value;
				ende = value;
				for (int i = 1; i < 3; i++)

				{
					int rot = (int) (Math.random() * 255);
					int gruen = (int) (Math.random() * 255);
					int blau = (int) (Math.random() * 255);
					g.setColor(new Color(rot, gruen, blau));

					value = (360 * ein**) / 100;
					
					g.fillArc(50, 50, 200, 200, anfang, ende);
					anfang = ende;
					ende = ende +value;

				}

}

hier wieder Canvas?

die größte Weisheit hast du vielleicht noch nicht (in letzter Zeit wieder) erfahren:
System.out.println(),
logge jeden Schleifendurchlauf, gib aus welches i gerade drankommt, welchen Wert anfang, ende und value haben, z.B. kurz vorm Zeichnen,
überdenke auch wie du am Anfang die Variablen initialisiert

gegen verständliche Sätze wäre auch nichts einzuwenden

Sorry blöder Tippfehler. Ich kann mich mit dem Fehler nicht rechtfertigen dass deutsch meine Fremdsprache ist :slight_smile:

danke für den Tipp.mein code schaut jetzt so aus


public void paint(Graphics g) {
			
				int value = 0;
				int anfang = 0;
				int ende = 0;
				

				for (int i = 0; i < 3; i++)

				{
					int rot = (int) (Math.random() * 255);
					int gruen = (int) (Math.random() * 255);
					int blau = (int) (Math.random() * 255);
					g.setColor(new Color(rot, gruen, blau));
					
					ende = ende +(360 * ein**) / 100;
					
					System.out.println("Durchlauf" + i);
					System.out.println("anfang" + anfang);
					System.out.println("ende"+ ende);
					System.out.println("----");

					
					
					g.fillArc(50, 50, 200, 200, anfang, ende);
					anfang = ende;
				

				}

			}


Durchlauf0
anfang0
ende144

Durchlauf1
anfang144
ende306

Durchlauf2
anfang306
ende360


Ich bekomme einfarbigen Kreis.
fillarc hat folgende werte
1.Durchlauf :g.fillArc(50, 50, 200, 200, 0, 144);
2.Durchlauf : g.fillArc(50, 50, 200, 200, 144, 306);
3.Durchlauf : g.fillArc(50, 50, 200, 200, 306, 360);

da bei der Rechteck diese Schleife alle Rechtecke verschiedene Farben macht,warum ist bei der Kreisbogen nicht der fall?

			for(int i = 0;i<12;i++)
			{
				int rot = ((int)Math.random()*255);
				int gruen = ((int)Math.random()*255);
				int blau = ((int)Math.random()*255);
				g.setColor(new Color(rot,gruen,blau));
				
				g.fillRect(x,250-h**,b,h**);
				
				g.drawString(monat**,x,260);
				x=x+15;
			}```

warum so kompliziert mit Schleife?
teste ruhig auch einzeln Aufrufe

wäre Anfang und Ende wirklich Anfang und Ende (wie ich es gerade auch erst dachte),
dann wäre aber anfang144 + ende144 deutlich genug: so ginge es nicht, kein Grad Unterschied,

man kann auch kein Rechteck/ keine Linie von x = 144 bis x = 144 malen

tatsächlich ist aber das eine der Anfangswinkel und danach die Größe des gezeichneten Kreises,
-> mit 360 zum Schluss malst du einen vollen Kreis, egal wo begonnen, egal was davor gemalt

für ‘anfang306 ende360’ willst du sicherlich von den Werten 306 + 54 malen usw.

Nochmal auf den Punkt: Der letzte Parameter von Graphics (Java Platform SE 7 ) ist

arcAngle - the angular extent of the arc, relative to the start angle.

Also um ein Viertel des Kresies zu zeichen, müßte es z.B. 45 sein. (Absurderweise in GRAD, aber … das ist wohl den ints geschuldet…)

diese Rechteck Beispiel war andermal. und damals ging alle Rechtecke mit schleifendurchlauf in verschiedene Farben. ich habe zu kreisdiagramm ein Artikel gefunden, aber halt ohne schleife. Bei mir ist doch gleiche Logik und warum wird kreis in eine Farbe dargestellt?

mit 45 euro zeichne ich doch keinen viertel kreis, weil ich 45 von 100% berechne und nicht von 360°

                int anfang = 0;
				int ende = 0;
				
				
				for (int i = 0; i < 3; i++)

				{
					int rot = (int) (Math.random() * 255);
					int gruen = (int) (Math.random() * 255);
					int blau = (int) (Math.random() * 255);
					g.setColor(new Color(rot, gruen, blau));
					
					ende = ende +(360 * ein**) / 100;
					
					g.fillArc(50, 50, 200, 200, anfang, ende);
					anfang = ende;
				

				}
  1. durchlauf
    wird Farbe gesetzt g.setColor(new Color(rot, gruen, blau));
    dann wird Kreisbogen ausgefüllt g.fillArc(50, 50, 200, 200, 0, 144);

  2. durchlauf
    wird Farbe gesetzt g.setColor(new Color(rot, gruen, blau));
    dann wird Kreisbogen ausgefüllt g.fillArc(50, 50, 200, 200, 144, 306);

  3. durchlauf
    wird Farbe gesetzt g.setColor(new Color(rot, gruen, blau));
    dann wird Kreisbogen ausgefüllt g.fillArc(50, 50, 200, 200, 306, 360);

Leider bekomme ich aber einfärbigen Kreis, aber da unten ist doch gleiche Logik

du malst so als würde im Beispiel

fillArc(.., cdu, cdu+fdp)
fillArc(.., cdu+fdp, cdu+fdp+spd)```
stehen, das steht da aber nicht, nicht Anfang und Ende, sondern Anfang und Arc

ist bei Rechtecken doch genauso die Frage,
malt man von Punkt zu Punkt, von x=100 bis zu x=120 oder von einem Punkt x=100 aus mit bestimmter Breite, 20 ?

beide Varianten kann man sich vorstellen, eine davon ist von Java angeboten, 
wenn nicht schon längst klar geworden dann genau mit kleinen Werten ausprobieren, wie gemalt wird

[quote=SlaterB]ist bei Rechtecken doch genauso die Frage,
malt man von Punkt zu Punkt, von x=100 bis zu x=120 oder von einem Punkt x=100 aus mit bestimmter Breite, 20 ?[/quote]

Diese Zeilen haben mich gerettet. Danke Danke Danke

auf Variablenamen bin ich nicht stolz, aber das werde ich in ruhe ausdenken. wollte nur posten sobald ich fertig bin


				int anfang = 0;
				int ende = 0;
				int anfangspunkt =0;
				
				
				for (int i = 0; i < 3; i++)

				{
					int rot = (int) (Math.random() * 255);
					int gruen = (int) (Math.random() * 255);
					int blau = (int) (Math.random() * 255);
					g.setColor(new Color(rot, gruen, blau));
					
					anfangspunkt = anfangspunkt +(360 * ein**) / 100;
					ende = (360 * ein**) / 100;
					
					g.fillArc(50, 50, 200, 200, anfang, ende);
					anfang = anfangspunkt;
				

				}