In eigene JPanel Klasse zeichnen

Status
Nicht offen für weitere Antworten.

MisterDan

Mitglied
Hi Leute,

mein Programm hat bisher auf Mausklick an die geklickte Stelle einen Kreis mit ID (Waypoint) direkt in den JFrame gezeichnet.
Es soll mal ein "Waypoint-Creator" (zum erstellen von Wegpunkten, wo später eine Spielfigur lang läuft) werden.

So bisher hat auch alles funktioniert.

Nun musste ich mein Programm aus diversen Gründen umbauen und nun will ich in ein JPanel zeichnen.
Dafür hab ich mir eine Klasse "DrawPane" erstellt die von JPanel abgeleitet und außerdem noch einen Mouselistener implementiert.

Ich hab keine Paint-Methode oder sonstige Methoden der Klasse überschrieben.

Problem:

Vorher hab ich im Hauptprogramm (MainPogram) auf Mausklick eine Instanz der Klasse "Waypoint" (abgeleitet von Component) erstellt.
Waypoint zeichnet sich selbst. Dann einfach diese Instanz (welche ja ein Component ist) dem JFrame hinzugefügt.

Sprich:

getContentPane().add(waypoint);
getContentPane().paintAll(getContentPane().getGraphics());

Hat einwandfrei funktioniert!

Jetzt möchte ich genau das gleiche mit dem JPanel machen, also denke ich mir:

drawPanel.add(waypoint);
drawPanel.paintAll(drawPanel.getGraphics());

oder

drawPanel.add(waypoint);
drawPanel.paintAll(drawPanel.getGraphics());
drawPanel.invalidate();

oder

drawPanel.add(waypoint);
drawPanel.paintAll(drawPanel.getGraphics());
drawPanel.repaint();

ABER NICHTS TUT SICH! Wenn ich mir aber nach jedem Mausklick aber
System.out.println(drawPanel.getComponentCount());
aufrufe erhöht sich der Wert immer um 1.
Das heisst er fügt wohl nach jedem Mausklick eine Komponenten (Waypoint) hinzu!
NUR SEHE ICH DIESE NICHT!

Hat irgendjemand eine Idee. Es handelt sich um ein Studien-Projekt und in 2 Wochen ist Abgabe.

Ich danke jetzt schon 1000x im vorraus!

Mfg

MisterDan
 
> drawPanel.paintAll(drawPanel.getGraphics());

das ist ja schaurig, geht drawPanel.repaint(); nicht?

----------

ist das drawPanel überhaupt zu sehen? Layout in Swing kann manchmal tücksich sein,
je nach Layout der Oberkompontente werden Unterkomponenten gar nicht, minimiert auf 0,0, füllend oder in sonstigen Mittelgrößen anzeigt,

mit einem vollständigen Code-Beispiel wäre allen sehr geholfen,
evtl. gehts ja auch mit einfachen JLabel-Objekten statt Waypoints?
 
erstmal danke für die schnelle Antwort!

ich weiss, es ist schaurig, aber ich bin auch verzweifelt :?
drawPanel.repaint() geht leider nicht, was mich ja so verwundert!

das drawPanel ist zu sehen. Hatte anfangs auch große Probleme damit, ohh jaa Layout in Swing kann sehr tückisch sein *g*
Ich weiss das es mitterweile zu sehen ist, da ich die Backgroundcolor ändern kann und ergebnisse sehe, außerdem hab ich das JPanel auf Dimension(5000,5000) und man kann scrollen und scrollen, was bei ner größe von 0,0 ja auch nicht ginge. Wäre aber ein guter lösungsansatz gewesen.

Nein geht leider, leider nicht mit JLabeln, sorry! ->Da kommen später noch Verbindungslinien und so hinzu, spätestens dann gehts nicht mehr mit JLabeln.


Hilft das Weiter?

Hier mal ein bisschen Code:
Code:
public class MainProgram extends JFrame implements ItemListener{
....attribute.....
public MainProgram(){
.... fenstereinstellungen, buttons, panels, etc...
sowie,

//DrawPanel
		this.drawPanel = new DrawPane(/*cList, wpList*/);
		Dimension size = new Dimension(5000, 5000);
		this.drawPanel.setPreferredSize(size);
		this.drawPanel.setMinimumSize(size);
		this.drawPanel.setMaximumSize(size);
		this.drawPanel.setSize(size);
		this.drawPanel.setBackground(Color.black);
		
		//ScrollPane
		this.scrollPane = new JScrollPane();
		this.scrollPane.setPreferredSize(new Dimension(400,200));
		this.scrollPane.setBackground(Color.orange);
		this.scrollPane.setMinimumSize(new Dimension(400,200));
		this.scrollPane.setMaximumSize(new Dimension(400,200));
		this.scrollPane.setPreferredSize(new Dimension(400,200));
		this.scrollPane.invalidate();
		this.scrollPane.updateUI();
		this.scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		this.scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		this.scrollPane.setViewportView(drawPanel);	
this.getContentPane().add(BorderLayout.EAST,configPanel);
		this.getContentPane().add(scrollPane);
		
		this.setVisible(true);
		this.doLogic();
	}

public void doLogic()
    {
    	drawPanel.addMouseListener(new MouseAdapter() 
    	{
          public void mouseClicked(MouseEvent arg0) 
          {
        	 // klick auswerten     	 
        	 //System.out.print("Getted XPos: " + drawPanel.getXPos());
        	 //System.out.println(", Getted yPos: " + drawPanel.getYPos());

          	waypointIDCounter++;
 /*
*
*HIER SOLL JETZT DIE ERSTELLTE KOMPONENTE ("WAYPOINT") DEM PANEL HINZUGEFÜGT WERDEN!!
*WAS IST DARAN FALSCH?????
*
*/
          	waypoint = new Waypoint(waypointIDCounter, 100, 100); //hier würden dann die X und Y positionen hin kommen
          	drawPanel.add(waypoint);
          	//drawPanel.paintAll(drawPanel.getGraphics());
          	drawPanel.invalidate();
          	drawPanel.repaint();
          	
          	System.out.println(drawPanel.getComponentCount());
   }
    	});
    }


Wie man sieht wird in DrawPane nichts überschrieben:

Code:
public class DrawPane extends JPanel implements MouseListener {
private int x;
    private int y;

public DrawPane()
	{
		
		this.addMouseListener(this);
	}


public int getXPos(){
		return this.x;
	}
	
	public int getYPos(){
		return this.y;
	}
	
	@Override
	public void mouseClicked(MouseEvent event) {
//		System.out.println("clicked1");
//		System.out.println(event.getX());
//		System.out.println(event.getY());
		this.x = event.getX();
		this.y = event.getY();
	}


Code:
public class Waypoint extends Component {
	
	
	private int ID;
	private int xPos;
	private int yPos;
	private String name;
	
	public Waypoint(int waypointIDCounter, int xPos, int yPos){
		this.ID = waypointIDCounter;
		this.xPos = xPos;
		this.yPos = yPos;
		this.name = "Waypoint"+waypointIDCounter;
	}
	
	public void paint(Graphics g) {
		System.out.println("PAINT!!!!!");
        g.setColor(Color.white);
        g.drawOval(xPos, yPos, 50, 50 );
        g.drawString(""+ID, ((xPos)+22), ((yPos)+30));
    }
 
so, hier eine gekürzte funktionierende, vollständig laufende Version:

Code:
public class MainProgram
    extends JFrame
{
    DrawPane drawPanel;
    JScrollPane scrollPane;
    static int waypointIDCounter;

    public MainProgram()
    {
        // DrawPanel
        drawPanel = new DrawPane(/* cList, wpList */);
        Dimension size = new Dimension(400, 400);
        drawPanel.setPreferredSize(size);
        drawPanel.setBackground(Color.black);

        // ScrollPane
        scrollPane = new JScrollPane(drawPanel);
        getContentPane().add(BorderLayout.CENTER, scrollPane);

        setSize(400, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
        doLogic();
    }

    public void doLogic()
    {
        drawPanel.addMouseListener(new MouseAdapter()
            {
                public void mouseClicked(MouseEvent arg0)
                {
                    waypointIDCounter++;
                    Waypoint waypoint = new Waypoint(waypointIDCounter, 100, 100); // hier
                    drawPanel.add(waypoint);
                    drawPanel.validate();
                    System.out.println(drawPanel.getComponentCount());
                }
            });
    }

    public static void main(String[] args)
    {
        new MainProgram();
    }

}

---------------

public class DrawPane
    extends JPanel
{
    private int x;
    private int y;

    public DrawPane()
    {

    }

}

--------

public class Waypoint
    extends Component
{
    private int ID;
    private int xPos;
    private int yPos;
    private String name;

    public Waypoint(int waypointIDCounter, int xPos, int yPos)
    {
        this.ID = waypointIDCounter;
        this.xPos = xPos;
        this.yPos = yPos;
        this.name = "Waypoint" + waypointIDCounter;
        this.setPreferredSize(new Dimension(100, 100));
        // this.setBorder(BorderFactory.createLineBorder(Color.red));
    }

    public void paint(Graphics g)
    {
        super.paint(g);
        System.out.println("PAINT!!!!!");
        g.setColor(Color.red);
        g.fillRect(0, 0, 100, 100);
        g.setColor(Color.white);
        g.drawOval(0, 0, 50, 50);
        g.drawString("" + ID, ((0) + 22), ((0) + 30));
    }

}


Hauptproblem 1:
ohne einen validate()-Aufruf wird das Layout nicht neu berechnet,
die neuen Komponenten nicht angezeigt

invalidate(); klingt ähnlich, aber knapp daneben ist auch vorbei 😉

Hauptproblem 2:
die neuen Waypoints haben standardmäßig eine Größe 0,0,
ohne ein setPreferredSize(new Dimension(100, 100)); läuft nicht viel,
(abhängig vom Layout von DrawPane, bei anderem Layout sind evtl. andere Schritte nötig)

Nebenproblem:
selbst wenn Waypoint eine gewisse Größe hätte, würde bei deiner komplizierten paint-Operation nichts zu sehen sein,
du malst erst bei Position 100,100, wenn also Waypoint weniger als 100,100 groß ist, wird gar nix gemalt

immer mit einfachen Zeichenoperationen wie 'alles rot malen' anfangen (von Punkt 0,0 aus),
der Richtpunkt 0,0 in Paint ist der Anfang der Komponente, nicht des DrawPanels,

ob Component so geeignet ist, weiß ich nicht,
nimm wenigestens JComponent, dann kannst du Border setzen,
die sehr gut geignet sind, selbst Komponenten mit Größe 0,0 zu erkennen
 
Wow, ich bin beeindruckt!

Vielen Dank dafür und auch für die sehr verständliche Erklärung!

Ich weiß nicht was ich noch sagen soll außer 1000send Dank^^

Mfg

MisterDan
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben