Zum Inhalt springen

Zeichnen eines Strichs


Empfohlene Beiträge

Geschrieben

Hallo Zusammen!

Ich habe eine Oberfläche und würde auf dieser gerne paar Striche ziehen. Das klappt mittlerweile EIGENTLICH auch. Das einzige ist wenn ich jetzt mein Frame hab dann sind die Striche genauso das wie ich sie haben will. Wenn ich jetzt jedoch ein anderes Fenster also ne internetseite meinen Explorer oder sonst was sind die Striche auf einmal weg alles andere ist genauso wie davor aber die Striche sind weg :confused:

Könnt ihr mir vllt weiter helfen? :(

Hier mein Code:


package UnserSudoku;


import java.awt.BasicStroke;

import java.awt.Font;

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.event.FocusEvent;

import java.awt.event.FocusListener;

import java.awt.geom.Line2D;


import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JPanel;

import javax.swing.JTextField;


public class Sudo_Frame extends JFrame{


	public int feldlänge 		= 9;

	public int[][] array 		= new int[feldlänge][feldlänge];

	public JTextField tf[][]	= new JTextField[feldlänge][feldlänge];

	public JButton bt_start 	= new JButton("Start");

	public Font font 			= new Font("SansSerif", Font.BOLD, 14);

	public JPanel panel			= new JPanel();


	public Sudo_Frame(){

		panel.setLayout(null);


		for(int zeilen = 0; zeilen < feldlänge; zeilen++){

			for(int spalten = 0; spalten < feldlänge; spalten++){

				tf[zeilen][spalten] = new JTextField();

				tf[zeilen][spalten].setDocument(new Sudo_TextFeld_Begrenzung(1));

				tf[zeilen][spalten].setHorizontalAlignment(JTextField.CENTER);

				panel.add(tf[zeilen][spalten]);

			}

		}


		add(panel);


		int pos_x = 10;

		int pos_y = 10; 

		int hoehe = 25;

		int breite = 25;

		int zähler = 0;



		for(int zeilen = 0; zeilen < feldlänge; zeilen++){

			for(int spalten = 0; spalten < feldlänge; spalten++){

				tf[zeilen][spalten].setBounds(pos_x, pos_y, hoehe, breite);

				pos_x = pos_x + 35;

				zähler++;


				if(zähler == 9){

					pos_x = 10;

					pos_y = pos_y + 35;

					zähler = 0;

				}

			}

		}


		setResizable(false);

		setTitle("Sudoku Löser");

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		setSize(330, 350);

	}    


	public int[][] getGet2DimArray(){		

		for(int zeilen = 0; zeilen < feldlänge; zeilen++){

			for(int spalten = 0; spalten < feldlänge; spalten++){

				array[zeilen][spalten] = Integer.parseInt(tf[zeilen][spalten].getText());

			}

		}


		return array;

	}


	public void anzeigen(boolean bool){

		setVisible(true);

	}


	public void paint( Graphics graphics ) {

		super.paint(graphics);


		graphics.drawLine( 10, 132, 320, 132);

		graphics.drawLine( 10, 237, 320, 237);

		graphics.drawLine(112,  30, 112, 340);

		graphics.drawLine(217,  30, 217, 340);

	}

}

MfG

Saban

Geschrieben

nachm runterscrollen hab ichs mir schon gedacht, dass Du die Striche in der paint() zeichnest.

Problem ist, wenn Windows Fenster überlagert/neu zeichnet, etc. muss man an den richtigen Stellen ein update() machen, damit auch die Java-paint() aufgerufen wird.

Geschrieben (bearbeitet)

Leider kann ich Dir das so pauschal nicht beantworten.

Richtig ist auf alle Fälle, dass der Code in das paint() muss.

Meiner Meinung nach sollte paint() jetzt bereits schon alles für Dich erledigen, aber wie mir scheint ist da noch irgendwo - vielleicht sogar im JDK selber - ein Bug.

Mach mal in das paint() eine System.out.println rein und versuche herauszufinden bei welchen übergeordneten Window-Events er KEIN paint() ausführt.

Beispiele:

- Du veränderst die Größe Deines Frames mit der Maus -> println kommt -> OK

- Du minimierst die Anwendung -> println kommt nicht -> OK

- Du normalisierst die Anwendung wieder -> println kommt ja/nein

- Du aktivierst ein anderes Fenster was NICHT überlagernd gezeichnet wird, so dass Du beide Fenster zu 100% sehen kannst, nur dass Dein Frame deaktiviert wird -> jetzt klickst wieder in den JFrame (am besten in die Titelzeile) -> jetzt kommt sicherlich kein paint

Irgendwo fehlt der Hinweis, dass der interne Puffer des JFrames eben gerade kein paint() nötig hat, sondern nur die Sub-Controls ein update bekommen.

Fakt ist so wie Du die Anzeige der Striche realisierst hast, musst Du sobald die Sub-Controls geupdated werden auch den JFrame updaten.

Ich empfehle dazu der Einfachheit nicht paint() vom Frame zu nutzen, sondern stattdessen ein eigenes oder vorhandenes Control zu benutzen, und das ganze Neuzeichnen/Updaten die normale Java-Umgebung machen zu lassen.

Leider weiss ich nicht auf die schnelle, welches Control Dir direkt weiterhelfen könnte. Wenn alle Stricke reissen nimm ein JLabel("|") :D

Das ist einer der schmutzigen Tricks, denen man sich bedienen muss, um per Workaround das Fenster-Triggering vom JDK zum Leben zu erwecken.

Das mit dem JLabel ist allerings wirklich nur die Notlösung, besser ist herauszufinden, bei welchen übergeordneten Ereignissen das JFrame kein paint() vom update() bekommt und dieses Event dann zu überschreiben und mit dem update() das paint() selbst anzustoßen.

Bearbeitet von VaNaTiC
Geschrieben

Hi

Also die Paint-Methode wir nur beim Starten des Programms und beim Maximieren aufgerufen. Aber so wirklich weiter weiß ich jetzt trotzdem nicht :confused:

Ich glaub ich mach des mit den Labels

MfG

Saban

Geschrieben

Hmm, also war meine Vermutung richtig, dass das JFrame keine Notwendigkeit sieht ein paint() zu machen. Du könntest das erzwingen indem Du Deine JTextFields in MyJTextField ableitest und dort die paint() und/oder updateUI() überschreibst:


public class MyJTextField extends JTextField

{

  public void paint(...)

  {

     super.paint(...);

     getParent().paint(...);

  }

  public void updateUI()

  {

     super.updateUI();

     getParent().updateUI();

  }

}

Damit sollte das Neuzeichnen beim Zeichnen eines Deiner Textfelder erzwungen werden.

Aber Vorsicht: Verbessere das bitte selbst, so dass das JFrame nicht bei jedem einzelnen JTextField neu gezeichnet wird.

Geschrieben

Ungetestet:


private void paintLine(Graphics graphics) {

    graphics.drawLine( 10, 132, 320, 132);

    graphics.drawLine( 10, 237, 320, 237);

    graphics.drawLine(112,  30, 112, 340);

    graphics.drawLine(217,  30, 217, 340);

}


public void paint( Graphics graphics ) {

    super.paint(graphics);

    paintLine(graphics);

}


public void update( Graphics graphics ) {

    super.update(graphics);

    paintLine(graphics);

}

Gruß

Geschrieben (bearbeitet)

Adde ein JPanel auf die Frame und male auf dem Panel!

Dann musst du auch nur die paint oder componentPaint Methode überschreiben.

Edit: Ich sehe gerade, dass du ja schon ein Panel beutzt...

Problem ist vielleicht nur, dass du auf der Frame malst, aber das Panel die Frame überdeckt. Zur Not kannst du dem Panel auch ein setOpaque(true) geben und es wird transparent.

Bearbeitet von zui2000
Geschrieben

Kannst Du bitte Deinen aktuellen Quellcode soweit reduzieren, dass alles in einem kleinen JFrame drin steht und hier posten?

Vielleicht lässt sich dann beim direkten Nachvollziehen was entdecken.

Geschrieben

Hi!

ich hoffe ich hab dich richtig verstanden also hier mein gekürzter Code:


import java.awt.Font;

import java.awt.Graphics;

import java.awt.event.FocusListener;


import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JPanel;

import javax.swing.JTextField;


public class Sudo_Frame_2 extends JFrame{


	public int feldlänge 		= 9;

	public JTextField tf[][]	= new JTextField[feldlänge][feldlänge];

	public JButton bt_start 	= new JButton("Start");

	public Font font 			= new Font("SansSerif", Font.BOLD, 14);

	public JPanel panel			= new JPanel();


	public Sudo_Frame_2(){

		panel.setLayout(null);


		for(int zeilen = 0; zeilen < feldlänge; zeilen++){

			for(int spalten = 0; spalten < feldlänge; spalten++){

				tf[zeilen][spalten] = new JTextField();

				tf[zeilen][spalten].setDocument(new Sudo_TextFeld_Begrenzung(1));

				tf[zeilen][spalten].setHorizontalAlignment(JTextField.CENTER);

				panel.add(tf[zeilen][spalten]);

			}

		}


		add(panel);


		int pos_x = 10;

		int pos_y = 10; 

		int hoehe = 25;

		int breite = 25;

		int zähler = 0;



		for(int zeilen = 0; zeilen < feldlänge; zeilen++){

			for(int spalten = 0; spalten < feldlänge; spalten++){

				tf[zeilen][spalten].setBounds(pos_x, pos_y, hoehe, breite);

				pos_x = pos_x + 35;

				zähler++;


				if(zähler == 9){

					pos_x = 10;

					pos_y = pos_y + 35;

					zähler = 0;

				}

			}

		}


		setResizable(false);

		setTitle("Sudoku Löser");

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		setSize(330, 350);

		setVisible(true);

	}    


	public void paint(Graphics graphics) {

		super.paint(graphics);


	    graphics.drawLine( 10, 132, 320, 132);

	    graphics.drawLine( 10, 237, 320, 237);

	    graphics.drawLine(112,  30, 112, 340);

	    graphics.drawLine(217,  30, 217, 340);

	}

}

Was ich noch dazu sagen wollte wenn ich die Paint Methode auf dem Panel ausführe dann werden die Striche garnicht angzeigt... Ich weiss wirklich nicht mehr weiter... :(

MfG

Saban

Geschrieben (bearbeitet)

Habe das mal lokal getestet und ich bekomme eine Exception.

Ändere mal "add(panel);" zu "getContentPane().add(panel);".

Bei mir funktionierts wunderbar.

Ansonsten wird vielleicht hier der Fehler liegen: tf[zeilen][spalten].setDocument(new Sudo_TextFeld_Begrenzung(1));

Denn das hatte ich auskommentiert.

Bearbeitet von zui2000
Geschrieben

Hmm, ja. Hatte einen Denkfehler!

Die paint()-Methode des JFrame kommt tatsächlich nur wenn nötig und eben nicht, wenn nur Child-Elemente nötig sind.

Und das ist genau die Krux. Dein Panel wird neu sehr wohl gezeichnet und genau deshalb sind die Striche plötzlich weg. Ist ja auch klar, die Striche sind ja nachträglich draufgekommen und nun ist halt JPanel wieder drüber.

Lösung:

Leite Dir ein eigenes Panel ab, kopiere die paint() in das Panel und ersetze die Referenz im Frame auf Dein neues Panel:

import java.awt.Font;

import java.awt.Graphics;

import java.awt.event.FocusListener;


import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JPanel;

import javax.swing.JTextField;


public class Sudo_Frame_2 extends JFrame{


	public int feldlänge 		= 9;

	public JTextField tf[][]	= new JTextField[feldlänge][feldlänge];

	public JButton bt_start 	= new JButton("Start");

	public Font font 			= new Font("SansSerif", Font.BOLD, 14);

	public JPanel panel			= new [COLOR="#ff0000"]SudoPanel[/COLOR]();


	public Sudo_Frame_2(){

		panel.setLayout(null);


		for(int zeilen = 0; zeilen < feldlänge; zeilen++){

			for(int spalten = 0; spalten < feldlänge; spalten++){

				tf[zeilen][spalten] = new JTextField();

				tf[zeilen][spalten].setDocument(new Sudo_TextFeld_Begrenzung(1));

				tf[zeilen][spalten].setHorizontalAlignment(JTextField.CENTER);

				panel.add(tf[zeilen][spalten]);

			}

		}


		add(panel);


		int pos_x = 10;

		int pos_y = 10; 

		int hoehe = 25;

		int breite = 25;

		int zähler = 0;



		for(int zeilen = 0; zeilen < feldlänge; zeilen++){

			for(int spalten = 0; spalten < feldlänge; spalten++){

				tf[zeilen][spalten].setBounds(pos_x, pos_y, hoehe, breite);

				pos_x = pos_x + 35;

				zähler++;


				if(zähler == 9){

					pos_x = 10;

					pos_y = pos_y + 35;

					zähler = 0;

				}

			}

		}


		setResizable(false);

		setTitle("Sudoku Löser");

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		setSize(330, 350);

		setVisible(true);

	}    


[COLOR="Red"]	/*public void paint(Graphics graphics) {

		super.paint(graphics);


	    graphics.drawLine( 10, 132, 320, 132);

	    graphics.drawLine( 10, 237, 320, 237);

	    graphics.drawLine(112,  30, 112, 340);

	    graphics.drawLine(217,  30, 217, 340);

	}*/

[/COLOR]}

[COLOR="#ff0000"]class SudoJPanel extends JPanel

{

    public void paint(Graphics graphics)

    {

        super.paint(graphics);


        graphics.drawLine( 10, 132, 320, 132);

        graphics.drawLine( 10, 237, 320, 237);

        graphics.drawLine(112,  30, 112, 340);

        graphics.drawLine(217,  30, 217, 340);

    }

}[/COLOR]

Hinweis: Die Koordinaten stimmen nicht mehr genau!

Geschrieben
Habe das mal lokal getestet und ich bekomme eine Exception.

Ändere mal "add(panel);" zu "getContentPane().add(panel);".

Bei mir funktionierts wunderbar.

Ansonsten wird vielleicht hier der Fehler liegen: tf[zeilen][spalten].setDocument(new Sudo_TextFeld_Begrenzung(1));

Denn das hatte ich auskommentiert.

Der erste Fehler liegt einfach nur darin, dass du noch eine ältere Java Version als er benutzt, in der man das getContentPane() auf dem JFrame noch ausführen muss. In der neuesten Version wird die add()-Methode des JFrames mittlerweile direkt auf die ContentPane umgeleitet.

Und der zweite Fehler liegt einfach nur daran, dass du die Klasse nicht hast, die dort erzeugt werden soll.

Also wohl alles keine Fehler die zu seinem Problem führen ;)

Geschrieben
Der erste Fehler liegt einfach nur darin, dass du noch eine ältere Java Version als er benutzt, in der man das getContentPane() auf dem JFrame noch ausführen muss. In der neuesten Version wird die add()-Methode des JFrames mittlerweile direkt auf die ContentPane umgeleitet.

Und der zweite Fehler liegt einfach nur daran, dass du die Klasse nicht hast, die dort erzeugt werden soll.

Also wohl alles keine Fehler die zu seinem Problem führen ;)

Jop stimmt schon, aber bei mir funktioniert es mit dem JDK1.4.

Dennoch habe ich mal in den tiefen meines Java Ordners gewühlt und eine Umsetzung gefunden die dem Problem entspricht.


@Override


	protected void paintComponent(Graphics g) {


		super.paintComponent(g);


		/*


		 * draw background (game field)


		 */


		ImageIcon icon = new ImageIcon("data/ressources/img/game_field.jpg");


		g.drawImage(icon.getImage(), 0, 0, this);


		/*


		 * draw player movement


		 */


		if(drawingPlayerRect)


			g.drawRect(rectBounds[0], rectBounds[1], rectBounds[2], rectBounds[3]);


	}


Dabei wird ein Hintergrundbild und ein Rechteck auf ein JPanel gemalt unter Java6.

War wohl einfach die falsche Methode.

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...