Swing Funktionsdarstellung

Newcomer2

Aktives Mitglied
Hallo Leute,
habe mal ein bisschen "gespielt" und wollte ne Grundlage für eine Funktionsdarstellung erzeugen. Möcht gern mal wissen, was ihr so davon haltet?

Hab mal gleich noch den Quelltext dabei, falls sich wer dafür interessiert :)

Unabhängig davon, wie groß das Fenster ist, erstellt es für eine der bis jetzt dargestellten Funktionen genau 1 Periode in das Zeichenfeld.
Allerdings sollte während der Erstellung einer Kurve das Fenster konstant bleiben ^^

Es ist natürlich noch ausbaufähig!

Java:
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;

public class Part1 
extends JFrame 
implements ActionListener
{
	private static final long serialVersionUID = 1L;
	static JPanel jpanel;
	static Part1 wnd;

	public static void main(String[] event) 
	{
		wnd = new Part1();
	}
	
	public Part1()
	{
		setResizable(true);
		setLocationRelativeTo(null);
		setVisible(true);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setLayout(new BorderLayout());
		
		Border bd1 = BorderFactory.createBevelBorder(BevelBorder.RAISED);
		Border bd2 = BorderFactory.createEtchedBorder();
		Border bd3 = BorderFactory.createCompoundBorder(bd1,bd2);
		
		JPanel jpnl = new JPanel();
		jpnl.setBorder(bd3);
		jpnl.setLayout(new GridLayout(4,1));
		
		for(int i=1;i<5;i++)
		{
			JButton jbutton = new JButton();
			switch(i)
			{
			case 1: { jbutton.setText("Sinus")  ; break; }
			case 2: { jbutton.setText("Cosinus"); break; }
			case 3: { jbutton.setText("Tangens"); break; }
			case 4: { jbutton.setText("Arcsin") ; break; }
			}
			jbutton.addActionListener(this);
			jpnl.add(jbutton);
		}
		add(jpnl, BorderLayout.WEST);
		jpanel = new JPanel();
		jpanel.setSize(400,200);
		jpanel.add(new Funktion());
		jpanel.validate();
		add(jpanel,BorderLayout.CENTER);
		pack();
	}

	public void actionPerformed(ActionEvent event) 
	{
		String cmd = event.getActionCommand();
		if(cmd.equals("Sinus"))
		{
			Funktion.function="Sinus";
		}
		if(cmd.equals("Cosinus"))
		{
			Funktion.function="Cosinus";
		}
		if(cmd.equals("Tangens"))
		{
			Funktion.function="Tangens";
		}
		if(cmd.equals("Arcsin"))
		{
			Funktion.function="Arcsin";
		}
		jpanel.removeAll();
		jpanel.add(new Funktion());
		jpanel.validate();
		Funktion.th.start();
	}
}

class Funktion 
extends Canvas
implements Runnable
{
	public static String function="";
	public Dimension getPreferredSize() { return new Dimension(Part1.jpanel.getWidth()-10,Part1.jpanel.getHeight()-10); }
	static Thread th;
	double x=0,y=0;
	private Image dbImage;
	private Graphics dbGraphics;
	List<Point> p = new ArrayList<Point>();

	public Funktion()
	{
		super();
		x=0;
		th = new Thread(this);
	}
	
	public void run() 
	{
		while(th.isAlive())
		{
			repaint();
			if(x>=40*Math.PI) th.stop();
			x+=Math.PI/100;
			auswahl(x);
			try {
				th.sleep(1);
			} catch (InterruptedException e) {e.printStackTrace();}
		}	
	}
	
	public void update(Graphics g)
	{
//		Double-Buffer initialisieren
		if (dbImage == null)
		{
			dbImage = createImage(this.getSize().width,this.getSize().height);
			dbGraphics = dbImage.getGraphics();
		}
		
//		Hintergrund löschen
		dbGraphics.setColor(getBackground());
		dbGraphics.fillRect(0,0,this.getSize().width,this.getSize().height);
		
//		Vordergrund zeichnen
		dbGraphics.setColor(getForeground());
		paint(dbGraphics);
		
//		Offscreen anzeigen
		g.drawImage(dbImage,0,0,this);
	}

	Point px;
	
	private void auswahl(double i)
	{
		double a=0;
		if(function.equals("Sinus"))   a=Math.sin(0.05*i);
		if(function.equals("Cosinus")) a=Math.cos(0.05*i);
		if(function.equals("Tangens")) a=Math.tan(0.05*i);
		if(function.equals("Arcsin"))  a=Math.asin(0.05*i);
		y=a*(getSize().height/2-2);
		px=new Point();
		px.setLocation((getSize().width/(40*Math.PI))*i,-y);
		p.add(px);	
	}
	
	public void paint(Graphics g)
	{
		g.setColor(Color.red);
		for(int i=0;i<p.size();i++)
		{
			if(i>0)
				g.drawLine(p.get(i-1).x, p.get(i-1).y+getSize().height/2,p.get(i).x, p.get(i).y+getSize().height/2);
		}
	}
}
 

Anhänge

  • Simulation.jar
    3,8 KB · Aufrufe: 11

javampir

Bekanntes Mitglied
Hi,
schaut echt gut aus! Das mit der Fenstergröße beim Zeichnen könntest du vlt. mit einem Window-Listener beheben, genauso wie ein repaint nach resize ganz gut wär.
javampir
 

Newcomer2

Aktives Mitglied
Hallo javampir,

danke für den Hinweis. Hab den Code allerdings nochmal überarbeiten können, sodass er noch besser aussieht ^^.
Habs mal mitn Component-Listener in der Hauptklasse gemacht:
Java:
public void componentResized(ComponentEvent event) {
		String sub = (String)event.getSource().toString().subSequence(25, 35);
		int neue_breite=0, neue_höhe=0, n=0, i=0;
		String[] subsub = new String[2];
		subsub[0]=""; subsub[1]=subsub[0];
		while (sub.charAt(i)!=',') {
			if(sub.charAt(i)!='x') subsub[n]+=sub.charAt(i);
			else {sub=sub.substring(i); n++; i=0;} 
			i++; }
		for(i=0;i<subsub[0].length();i++)
			neue_breite+=(subsub[0].charAt(i)-48)*((Math.pow(10, subsub[0].length()))/Math.pow(10, i+1));
		for(i=0;i<subsub[1].length();i++)
			neue_höhe+=(subsub[1].charAt(i)-48)*((Math.pow(10, subsub[1].length()))/Math.pow(10, i+1));
		System.out.println("x: "+neue_breite+" y: "+neue_höhe);
		Funktion.breite=neue_breite;
		Funktion.höhe=neue_höhe; 
		jpanel.repaint(); }

Ist ziemlich wüst, ich weiß ^^ aber funzt ;)
Zumindest dahingehend, dass die Positionen für die neuen Punkte sofort auf die neue Größe angepasst werden, aber erst bei Veränderung beider Raumgrößen (bzw. Klick auf andere Achse), wird das Fenster wirklich neu skaliert. Und wirklich sofort gehts dann nur bei der Veränderung der Höhe. Bei der Breite gibts da immernoch probs.
Allerdings müsst ich dann noch die Position der bereits gesetzten Punkte neu berechnen lassen.
 

Newcomer2

Aktives Mitglied
So, hier jetzt die funktionierende Fassung, mit adaptiver Anpassung der Positionen für jeden Punkt, egal wie sehr das Fenster vergrößert oder verkleinert wird ;)

Viel Spaß beim testen ^^
 

Anhänge

  • Simulation.jar
    4,8 KB · Aufrufe: 7

javampir

Bekanntes Mitglied
hi,
irgendwas stimmt noch nicht ganz: wenn man unterm zeichnen das fenster maximiert, kommt nix gescheites raus. wie man das jetzt genau abfragt, weß ich nicht auswendig.
javampir
 

Newcomer2

Aktives Mitglied
Ja, das stimmt schon. Aber wenn man es während des Zeichnens einfach nur vergrößert, funktionierts ^^
Ich sollte an dieser Stelle vielleicht nochmal schauen, was mir die Resize-Methode für Werte weitergibt, oder sollte dann einen Window-Listener vielleicht nehmen. Es ließe sich vielleicht dann über den Fensterstatus bewerkstelligen.
Aber wie es immer so schön heißt: Das Kriterium der Wahrheit ist immer das Experiment :)
 

Newcomer2

Aktives Mitglied
Hab ne Variante gefunden, musste nen anderen LayoutManager für das JPanel verwenden, in dem die Kurve dargestellt wird ^^
Standardmäßig ist FlowLayout eingestellt, und damit passts dann nicht. Hab jetzt mit BorderLayout gemacht, damit gehts nun wunderbar. Jetzt is nur das Problem, dass er mir die Kurve vom Punkt 0,0 an die entsprechende Größe annehmend ausgibt und so kein freier Rand mehr oben und links vorhanden ist. Könnte ja da dann noch leere JPanels mit entsprechenden Breiten und Höhen einbauen ^^
 

Newcomer2

Aktives Mitglied
Hier mal nen kleines Update der Funktionsdarstellungen ^^
Demnächst kommt dann noch die Möglichkeit der Verschiebung in x- und y-Richtung :)
 

Anhänge

  • Simulation_Test.jar
    6,8 KB · Aufrufe: 6

Newcomer2

Aktives Mitglied
Wieder nen kleines Update ^^
Man kann die Funktion auf der X-Achse und Y-Achse verschieben. Wenn dabei der Y-Wert die Fenstergröße überschreitet, werden alle Punkte entsprechend angepasst. Das gefällt mir so aber noch nicht, vllt kann mir da wer von Euch helfen? :) Es fehlt da ja nur an der richtigen Berechnung ^^
 

Anhänge

  • Simulation_Test.jar
    8,3 KB · Aufrufe: 3
Zuletzt bearbeitet:

Newcomer2

Aktives Mitglied
Sorry für das zuspammen meines Threads hier ^^

Hab schon ne Lösung gefunden. Hier dann die Variante, mit automatischer Anpassung an die Fenstergröße, Anpassung der Amplitude bei überschreiten der Fenstergröße, Einstellbarer Verschiebung in X- und Y-Richtung sowie Einstellung von Start- und Enpunkt der Funktionsdarstellung.

Weitere Erweiterungen sind geplant: Ganz freie Eingabe von Start- und Endwerten, sowie Verschiebung in jede Richtung ^^ und irgendwann auch Eingabe einer anderen Funktion ;)

Hoffe gefällt Euch :)
Quelltext gibts auf Anfrage ^^
 

Anhänge

  • Simulation_Test.jar
    8,3 KB · Aufrufe: 6

Neue Themen


Oben