Swing JApplet Designfrage

JochenS

Mitglied
Hi,
ich habe mehr oder minder eine Designfrage zu einem JApplet. Ich programmiere ein Applet für einen embedded Webserver. Das Applet soll eine Übersicht über die Daten der angeschlossenen Peripherie anzeigen meist in Form von Balken oder Grafdiagrammen – viele davon. Hierfür hab ich mir eine Klasse geschrieben welche die Daten bekommt und anschließend die Diagramme skaliert und zeichnet. Mein Problem ist nun, wie ich die Grafen selbst in das Applet bekomme. Die Daten stehen mir erst nach der Initialisierung des Applet zur Verfügung. Während der Initialisierung werden erst die GUI Elemente auf den Bildschirm geworfen, damit der Benutzer schon mal was zum anschauen hat, anschließend wird die Verbindung mit dem Webserver aufgebaut und die Daten abgeholt. Erst jetzt ist es mir möglich darauf zu zugreifen und die Diagramme mit den richtigen Werten auszustatten.
Mein Gedankengang war eigentlich, ich initialisiere ein Element meiner Grafenfunktion, werfe später die Daten rein und lass die Funktion dann mit repaint() einfach neu zeichnen. So funktioniert es aber leider nicht. 🙁
Bin für jegliche Art von Tipps dankbar, die mich hier weiter bringen. Die GUI baue ich mit NetBeans zusammen, die Grafenfunktion ist ein erweitertes JPanel. Es handelt sich um ein JApplet auch wenn ich oben immer nur Applet geschrieben hab 😉
Vielen Dank, Gruß Jochen
 
Wenn du genauer beschreibst, wie das Zeichnen abläuft, was "reinwerfen" heißt, und was beim Neuzeichnen nicht funktioniert, kann man da vielleicht was machen.
 
Klar, also meine Zeichenmethode sieht folgendermaßen aus:
Java:
public class BarChart extends JPanel {

	private double[] values;
	private String[] labels;

	public void putDataToTheDrawMethod(double[] givenValus, String[] givenLabels){
		this.values = new double[givenValus.length];
		System.arraycopy(givenValus, 0, this.values, 0, givenValus.length);
		this.labels = new String[givenLabels.length];
		System.arraycopy(givenLabels, 0, this.labels, 0, givenLabels.length);
	} // end putDataToTheDrawMethod()
	
	public Dimension getPreferredSize() {
		// This would be nice to draw graphs
		return new Dimension(835, 250);
	} // end getPreferredSize()

@Override
	public void paintComponent(Graphics g) {
		Graphics2D panel = (Graphics2D) g;

		// ***** Variables *****

		// Panel X Dimension
		// left |<- 25 ->|<-- x -->|<- 10 ->| right
		// Space Drawing Space
		int xPanelDimension;

		// Panel Y Dimension
		// top |<- 25 ->|<-- y -->|<- 25 ->| bottom
		// Space Drawing Space
		int yPanelDimension;

		int panelFrame = 25;

		double zeroLine = 25;
		int graphWidth = 5;

		double minTemperature = 0;
		double maxTemperature = 0;

		double pixelPerDegree;
		double spaceBetweenBars;

		boolean toggle = true;

		// ************************

		if ((values.length != 0) && (labels.length != 0)) {
			System.out.println("BarChart: Data is here, I should draw");

			// Analyse the given values: Find extreme of given temperatures
			for (int i = 0; i < values.length; i++) {
				if (minTemperature >= values[i])
					minTemperature = values[i];
				if (maxTemperature <= values[i])
					maxTemperature = values[i];
			}

			int tmp = (int) minTemperature;

			// Delete rounding error in cast
			if ((minTemperature % tmp) != 0)
				tmp--;

			// find the next point on a 5° based scale for the minimum
			while ((tmp % 5) != 0)
				tmp--;

			minTemperature = tmp;

			tmp = (int) maxTemperature;

			// Delete rounding error in cast
			if ((maxTemperature % tmp) != 0)
				tmp++;

			// find the next point on a 5° based scale for the maximum
			while ((tmp % 5) != 0)
				tmp++;

			maxTemperature = tmp;

			// Step 1: Calculate the draw panel
			xPanelDimension = super.getSize().width - panelFrame - 10;
			yPanelDimension = super.getSize().height - (2 * panelFrame);

			// Step 2: Calculate the measuring unit
			// temperature range = yPanelDimension
			// 1 degree = x pixel
			// x pixel = (yPanelDimension / temperature range)
			pixelPerDegree = yPanelDimension
					/ (Math.abs(minTemperature) + maxTemperature);

			// Step 3: Calculate the space between the bars
			// yAxis |<- 10px -> 1st bar <- space -> ... last bar <- 10px ->|
			// end of panel
			spaceBetweenBars = (xPanelDimension - (values.length * graphWidth) - 20)
					/ (values.length - 1);

			// Step 4: Paint the grid and label it

			// Step 4.1: Calculate the end point of the horizontal lines of the grid
			double temp = panelFrame + xPanelDimension;
			double yValue = 0;
			int i2 = 0;

			// Step 4.2: Draw the grid on a 5° based scale from max to min
			for (int i = (int) maxTemperature; i >= (int) minTemperature; i -= 5) {

				// calculate space between the lines
				yValue = panelFrame + i2 * 5 * pixelPerDegree;
				i2++;

				// paint the line x1 y1 x2 y2
				panel.draw(new Line2D.Double(panelFrame, yValue, temp, yValue));

				// label the lines
		  	           int yLabeling = (int) yValue + 3; 

				// print the label: string x y
				panel.drawString(String.valueOf(i), 3, yLabeling);

				// save the value of the zeroLine
				if (i == 0)
					zeroLine = yValue;
			}

			// Step 4.3: Draw the y-axis on the left side
			panel.draw(new Line2D.Double(panelFrame, panelFrame, panelFrame,
					yValue));

			// Step 4.4: Draw the y-axis on the right side
			panel.draw(new Line2D.Double(temp, panelFrame, temp, yValue));

			// Step 5: Paint the bars and label them
			System.out.println("Bars:");

			temp = 0.0;
			i2 = 0;
			yValue = 0.0;
			double heigth = 0.0;

			// Step 5.1: Draw a bar for each value
			for (int i = 0; i < values.length; i++) {

				// calculate the height of the current bar
				heigth = Math.abs(values[i]) * pixelPerDegree;
				yValue = zeroLine - heigth;

				// calculate the position on the x axis
				temp = panelFrame + 10 + i * (spaceBetweenBars + graphWidth);

				// draw the bar x y width height
				if (values[i] >= 0.0) {
					Rectangle2D.Double bar = new Rectangle2D.Double(temp,
							yValue, graphWidth, heigth);
					// calculate point for the gradient
					float gradientX = (float) (temp + 2.5);
					GradientPaint yellowToRed = new GradientPaint(gradientX,
							(float) yValue, Color.red, gradientX,
							(float) zeroLine, Color.yellow);
					panel.setPaint(yellowToRed);
					panel.fill(bar);
					panel.draw(bar);
				} else {
					Rectangle2D.Double bar = new Rectangle2D.Double(temp,
							zeroLine, graphWidth, heigth);
					// calculate point for the gradient
					float gradientX = (float) (temp + 2.5);
					float gradientY = (float) (zeroLine + heigth);
					GradientPaint whiteToblue = new GradientPaint(gradientX,
							(float) zeroLine, Color.cyan, gradientX, gradientY,
							Color.blue);
					panel.setPaint(whiteToblue);
					panel.fill(bar);
					panel.draw(bar);
				}

				// Step 5.2: Label the bar with the value
				// shift the label to the middle of the bar
				int xLabeling = (int) temp - 10; 
									
				panel.setPaint(Color.black);

				if (toggle)
					panel.drawString(String.valueOf(values[i]), xLabeling, 15);
				else
					panel.drawString(String.valueOf(values[i]), xLabeling, 20);

				// Step 5.3: Label the bar with the date
				// shift the label to the middle of the bar
				int yLabeling = 0;

				if (toggle) {
					yLabeling = (int) panelFrame + yPanelDimension + 15;
					toggle = false;
				} else {
					yLabeling = (int) panelFrame + yPanelDimension + 22;
					toggle = true;
				}

				// print the label: string x y
				panel.drawString(String.valueOf(labels[i]), xLabeling, yLabeling);
			}

			// Step 6: Draw again the zero line
			panel.setPaint(Color.black);
			temp = panelFrame + xPanelDimension;
			panel.draw(new Line2D.Double(panelFrame, zeroLine, temp, zeroLine));
		} else {
			System.out.println("BarChart: No Data arrived yet");
		}
	} // end paintComponent()

Die putDataToTheDrawMethod hab ich nur, weil NetBeans einen leeren Konstruktor verlangt um ein Element zur GUI-Palette hinzuzufügen.

Den Aufruf hab ich in einem demo per Knopfdruck, der den Erhalt der Daten simuliert:

Java:
public class demo extends javax.swing.JApplet {
    private BarChart bar;
   
    private void initComponents() {
        jPanel1 = new javax.swing.JPanel();
        jProgressBar1 = new javax.swing.JProgressBar();
        jButton1 = new javax.swing.JButton();
        bar = new BarChart();
        // NetBeans generated Code ...
    }

	private void dataAvailable(java.awt.event.ActionEvent evt) {
		jPanel1.removeAll();

		double[] testvalues = { -12.1, -11.4, -9.8, -7.6, -4.8, -4.4, -3.9,
				-4.8, -2.3, 0, 1.3, 2.4, 3.4, 4.1, 4.8, 5.3, 6.7, 7.5, 8.1,
				9.4, 10.9, 11.3, 12.7, 13.5, 13, 14.8, 15.7, 16.8, 17.9, 18.2,
				19.6, 20.1 };
		String[] testlabels = { "21.11.", "22.11.", " 23.11.", "24.11.",
				"25.11.", "26.11.", "27.11.", "28.11.", "29.11.", "30.11.",
				"01.12.", "02.12.", "03.12.", "04.12.", "05.12.", "06.12.",
				"07.12.", "08.12.", "09.12.", "10.12.", "11.12.", "12.12.",
				"13.12.", "14.12.", "15.12.", "16.12.", "17.12.", "18.12.",
				"19.12.", "20.12.", "21.12.", "22.12." };

		jPanel1.add(bar);
		bar.putDataToTheDrawMethod(testvalues, testlabels);
		bar.repaint();
		jPanel1.validate();
		jPanel1.repaint();
	}
}

Die Zeichenmethode selbst funktioniert einwandfrei, wenn die Daten bei der Initialisierung bekannt sind. Was beim Neuzeichnen falsch läuft ist einfach: Das Panel bleibt leer.
 
Zuletzt bearbeitet:
Anhand des geposteten schwer zu sagen, was da schiefläuft. Warum entfernst du erst alles von jPanel1, und fügst 'bar' dann wieder hinzu? Falls der NetBeans-generated-Code irgendwelche Layouts setzt, könnte es ihn dabei raushauen, ist aber erstmal auch nur geraten...
 

Zurück
Oben