"weiches" Bewegen von einem JComponent

Status
Nicht offen für weitere Antworten.
B

bananenkasper

Gast
Hallo Leute,

ich programmiere gerade ein kleines Spiel, bei dem sich Textfelder über einem Hintergrund bewegen sollen.

Momentan ist es so verwirklicht, dass ich JLabels mit "setBounds()" neu positioniere, und dann "repaint()" des "Hintergrund-Component" aufrufe.

Das geht soweit auch ganz gut, nur leider ist das ganze halt recht "ruckelig".

Aber wenn ich das JLabel pixelweise neu positioniere und entsprechend oft "repaint()" aufrufe, leidet die performance gewaltig.

Gibt es da eine elegantere Lösung?


MFG
 

André Uhres

Top Contributor
Du brauchst keinen "repaint", "setLocation" sollte genügen.
Versuch mal das Hintergrundbild im Bildpanel so zu malen:
Code:
   @Override
    public void paintComponent(final Graphics g) {
        super.paintComponent(g);
        Rectangle r = g.getClipBounds();
        g.drawImage(img, r.x, r.y, r.width + r.x, r.height + r.y,
                r.x, r.y, r.width + r.x, r.height + r.y, null);
    }
Die animierten JLabels werden zu diesem Bildpanel hinzugefügt.
"setLocation" bewirkt einen repaint, und zwar nur von dem Rechteck, das aktualisiert werden muss.
In "paintComponent" kann man dieses Rechteck mittels "getClipBounds" abfragen.
Der drawImage(..)-Aufruf, mit den angegebenen Parametern, zeichnet nur den
Teil des Bildes neu, der sich mit dem Cliprechteck überschneidet.
 
G

Guest

Gast
André Uhres hat gesagt.:
Du brauchst keinen "repaint", "setLocation" sollte genügen.
Versuch mal das Hintergrundbild im Bildpanel so zu malen:
Code:
   @Override
    public void paintComponent(final Graphics g) {
        super.paintComponent(g);
        Rectangle r = g.getClipBounds();
        g.drawImage(img, r.x, r.y, r.width + r.x, r.height + r.y,
                r.x, r.y, r.width + r.x, r.height + r.y, null);
    }
Die animierten JLabels werden zu diesem Bildpanel hinzugefügt.
"setLocation" bewirkt einen repaint, und zwar nur von dem Rechteck, das aktualisiert werden muss.
In "paintComponent" kann man dieses Rechteck mittels "getClipBounds" abfragen.
Der drawImage(..)-Aufruf, mit den angegebenen Parametern, zeichnet nur den
Teil des Bildes neu, der sich mit dem Cliprechteck überschneidet.


Clipping in Kombination mit Überschreiben von "paint()"....
Hatte ich auch schonmal in Betracht gezogen.
Erschien mir bis dato aber zu aufwending.
Aber wenn es so simple ist ;)

Vielen Dank für den Tipp!!
werde es gleich mal probieren!
 
B

bananenkasper

Gast
wie würde das gehen wenn ich kein bild zeichen möchte (drawImage()) sondern ein JLabel?
 

André Uhres

Top Contributor
bananenkasper hat gesagt.:
wie würde das gehen wenn ich kein bild zeichen möchte (drawImage()) sondern ein JLabel?
Einfach das Bild als Icon übergeben. Beispiel:
Code:
setIcon(new ImageIcon(img));
 

Marco13

Top Contributor
Irgendwie hätte ich das jetzt alles komplett anders verstanden - aber André Uhres scheint seine Kristallkugel frisch geputzt zu haben :wink:

Du willst also ein JPanel, bei dem in Hintergrund ein JLabel zu sehen ist, und auf diesem JPanel sollen sich JTextFields rumbewegen?!
 

André Uhres

Top Contributor
Marco13 hat gesagt.:
Du willst also ein JPanel, bei dem in Hintergrund ein JLabel zu sehen ist,
und auf diesem JPanel sollen sich JTextFields rumbewegen?!
Gemäss seinem ersten Beitrag sind die Textfelder JLabels und gemäss seinem letzten Beitrag
ist der "Hintergrund-Component" auch ein JLabel. Also JLabels bewegen sich auf einem JLabel
(es geht aber auch mit JTextFields, die sich auf einem JLabel bewegen).
Beispiel: TimerAnimation2.jar (Quellcode im jar)
 
B

bananenkasper

Gast
André Uhres hat gesagt.:
Marco13 hat gesagt.:
Du willst also ein JPanel, bei dem in Hintergrund ein JLabel zu sehen ist,
und auf diesem JPanel sollen sich JTextFields rumbewegen?!
Gemäss seinem ersten Beitrag sind die Textfelder JLabels und gemäss seinem letzten Beitrag
ist der "Hintergrund-Component" auch ein JLabel. Also JLabels bewegen sich auf einem JLabel
(es geht aber auch mit JTextFields, die sich auf einem JLabel bewegen).
Beispiel: TimerAnimation2.jar (Quellcode im jar)


Es gibt ein Hintergrundbild, dass ich in ein JLabel gepackt habe.
Dann gibt es Textfelder, die auch JLabels sind und sich auf diesem Hintergrund bewegen.

genaugenommen ist der Hintergrund ein "JLayerdPane",

es bewegt sich also ein JComponent "in" bzw. auf einem anderen JComponent.

Die Textfelder erstelle ich mit "setText()", "setFont()", "setBorder()", "setBackground()", etc.
Sie stellen reinen Text dar, der allerdings auf Blöcken "JLabel.setOpaque(true)" abgebildet ist.

Was ich noch nicht verstanden habe ist, wie ich diese "Textfeld-JLabels" zeichnen kann.
Ich meine es gibt ja eben keine Funktion "Graphics.drawComonent()"...
 
B

bananenkasper

Gast
Andre,

ich habe mal dein Beispielcode etwas modifiziert.
Da kommst du ja ausschliesslich mit "setLocation()" aus...

Will ich ein JLabel positionieren klappt das aber nicht.
Warum ist das so?

Code:
public class GuiTest extends JPanel {

	private class TimerAnimation extends JLabel implements ActionListener {
		// public class TimerAnimation extends JTextField implements
		// ActionListener {
		int deltaX = 2, deltaY = 3, directionX = 1, directionY = 1;

		public TimerAnimation(final int startX, final int startY,
				final int deltaX, final int deltaY, int directionX,
				int directionY, int delay) {
			this.deltaX = deltaX;
			this.deltaY = deltaY;
			this.directionX = directionX;
			this.directionY = directionY;
			// setText("O");
			try {
				setIcon(new ImageIcon(new URL(
						"http://www.java-forum.org/de/userfiles/"
								+ "user3690/redbull.gif")));
			} catch (MalformedURLException ex) {
				ex.printStackTrace();
			}
			setSize(getPreferredSize());
			setLocation(startX, startY);
			new javax.swing.Timer(delay, this).start();
		}

		public void actionPerformed(final ActionEvent e) {
			Container parent = getParent();
			// Determine next X position
			int nextX = getLocation().x + (deltaX * directionX);
			if (nextX < 0) {
				nextX = 0;
				directionX *= -1;
			}
			if (nextX + getSize().width > parent.getSize().width) {
				nextX = parent.getSize().width - getSize().width;
				directionX *= -1;
			}
			// Determine next Y position
			int nextY = getLocation().y + (deltaY * directionY);
			if (nextY < 0) {
				nextY = 0;
				directionY *= -1;
			}
			if (nextY + getSize().height > parent.getSize().height) {
				nextY = parent.getSize().height - getSize().height;
				directionY *= -1;
			}
			setLocation(nextX, nextY); // Move the label/textfield
		}

	}

	private class Picture extends JLabel {
		public Picture(final JFrame frame, final Image img) {
			setIcon(new ImageIcon(img));
			setOpaque(true);
			setBounds(75, 75, img.getWidth(frame), img.getHeight(frame));
			frame.setLayout(null);
			frame.add(this);// Picture component to the Frame:
		}
	}

	private class WordLabel extends JLabel {
		private final FontMetrics metrics;

		private final Font font = new Font("Sans", Font.BOLD, 24);

		WordLabel() {
			metrics = getFontMetrics(font);
			setFont(font);
			setForeground(Color.GREEN);
			setBackground(Color.BLUE);
			setBorder(BorderFactory.createLineBorder(Color.RED));
		}

		public int getWidth() {
			return metrics.stringWidth(getText()) + 4;
		}

		public int getHeight() {
			return metrics.getHeight() + 4;
		}
	}

	private final WordLabel word = new WordLabel();

	private final JFrame frame = new JFrame();

	private final Picture pic;

	private final Timer timer;

	private int y;

	GuiTest() {
		timer = new Timer(100, new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				y++;
				word.setLocation(0, y);

			}
		});
		timer.start();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(400, 400);
		frame.setLocationRelativeTo(null);
		URL url = null;
		Image img = null;// background image
		try {
			url = new URL("http://www.java-forum.org/de/userfiles/user3690/"
					+ "bottle-water-on-forehead.gif");
		} catch (MalformedURLException ex) {
			ex.printStackTrace();
		}
		try {
			img = ImageIO.read(url);
		} catch (IOException e) {
			e.printStackTrace();
		}
		pic = new Picture(frame, img);
		pic.add(word);
		pic.add(new TimerAnimation(10, 10, 2, 3, 1, 1, 10));
		pic.add(new TimerAnimation(300, 100, 3, 2, -1, 1, 20),
				BorderLayout.SOUTH);
		frame.setVisible(true);
		word.setText("hallo");
	}

	private static void createAndShowGui() {
		new GuiTest();
	}

	public static void main(final String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				createAndShowGui();
			}
		});
	}
}
 

André Uhres

Top Contributor
Versuch's mal so:
Code:
private class WordLabel extends JLabel {
    private final Font font = new Font("Sans", Font.BOLD, 24);
    WordLabel() {
        setFont(font);
        setForeground(Color.GREEN);
        setBackground(Color.BLUE);
        setBorder(BorderFactory.createLineBorder(Color.RED));
    }
    public void setText(String text) {
        super.setText(text);
        setSize(getPreferredSize());
    }
}
 
B

bananenkasper

Gast
André Uhres hat gesagt.:
Versuch's mal so:
Code:
private class WordLabel extends JLabel {
    private final Font font = new Font("Sans", Font.BOLD, 24);
    WordLabel() {
        setFont(font);
        setForeground(Color.GREEN);
        setBackground(Color.BLUE);
        setBorder(BorderFactory.createLineBorder(Color.RED));
    }
    public void setText(String text) {
        super.setText(text);
        setSize(getPreferredSize());
    }
}

wofür ist das gut?

EDIT:
ich habe zwar keinen Schimmer warum, aber so funktioniert es!!
Tausend Dank, Andre !!
 

André Uhres

Top Contributor
bananenkasper hat gesagt.:
wofür ist das gut?
Mit "setText(text)" wird die "PreferredSize" von "WordLabel" automatisch angepasst.
Da "Picture" keinen LayoutManager benutzt, müssen wir die "Size" von "WordLabel" manuell mit "setSize(..)" setzen.
Man könnte es natürlich auch so machen:
Code:
...
   private class WordLabel extends JLabel {
      private final Font font = new Font("Sans", Font.BOLD, 24);
      WordLabel() {
         setFont(font);
         setForeground(Color.GREEN);
         setBackground(Color.BLUE);
         setBorder(BorderFactory.createLineBorder(Color.RED));
      }
   }
...
   GuiTest() {
...
      word.setText("hallo");
      word.setSize(word.getPreferredSize());
   }
...
}

Die Klasse "TimerAnimation" geht übrigens ähnlich vor. Nach "setIcon" wird "setSize(getPreferredSize())" aufgerufen:
Code:
  private class TimerAnimation extends JLabel implements ActionListener {
...
      public TimerAnimation(...) {
...
         try {
            setIcon(...);
         } catch (MalformedURLException ex) {
            ex.printStackTrace();
         }
         setSize(getPreferredSize());//<-------------------
...
      }
 

Wolfgang Lenhard

Bekanntes Mitglied
Hi,
ich lese gerade, dass bei Swing paintComponent statt paint überschrieben werden sollte. Ich hatte bislang immer paint überschrieben und keine Probleme. Was ist der Grund für paintComponent()?

Viele Grüße,
Wolfgang
 

André Uhres

Top Contributor
Wolfgang Lenhard hat gesagt.:
ich lese gerade, dass bei Swing paintComponent statt paint überschrieben werden sollte. ... Was ist der Grund für paintComponent()?
"paint" ruft paintComponent, paintBorder und paintChildren auf, in dieser Reihenfolge.
Es gibt im Allgemeinen keinen Grund paintBorder() oder paintChildren() zu überschreiben.
Dies macht es den Programmen einfacher, nur den Teil des Zeichnens zu überschreiben,
den sie erweitern müssen: paintComponent.
Siehe auch: Malen in AWT und Swing: Die Malmethoden
 
B

bananenkasper

Gast
André Uhres hat gesagt.:
bananenkasper hat gesagt.:
wofür ist das gut?
Mit "setText(text)" wird die "PreferredSize" von "WordLabel" automatisch angepasst.
Da "Picture" keinen LayoutManager benutzt, müssen wir die "Size" von "WordLabel" manuell mit "setSize(..)" setzen.

Ok das ist soweit klar...
Aber warum wird das Label nach einem "setLocation()" nicht neu gezeichnet, wenn ich nicht voher setSize() aufrufe?
 

André Uhres

Top Contributor
bananenkasper hat gesagt.:
Aber warum wird das Label nach einem "setLocation()" nicht neu gezeichnet, wenn ich nicht voher setSize() aufrufe?
Es wird so gross gezeichnet wie sein Size ist. Wenn niemand den Size setzt,
dann ist er (0,0) und man sieht dann natürlich nix :wink:
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
G Weiches automatisches verschieben eines JSplitPane-Dividers? AWT, Swing, JavaFX & SWT 3
TheSepp Fenster um x Pixel bewegen, wenn man auf dem Knopf drückt AWT, Swing, JavaFX & SWT 10
N Objecte bewegen mit Tastatur AWT, Swing, JavaFX & SWT 5
B mit maus Objekt bewegen AWT, Swing, JavaFX & SWT 3
DonBronson Objekt bewegen (Mausposition) AWT, Swing, JavaFX & SWT 3
Z Button bewegen und Plätze tauschen AWT, Swing, JavaFX & SWT 4
Z Swing Button anklicken und bewegen AWT, Swing, JavaFX & SWT 2
F JLabel mit ImageIcon per Button bewegen AWT, Swing, JavaFX & SWT 4
D JavaFX Pane per Drag&Drop bewegen? AWT, Swing, JavaFX & SWT 2
A Swing JButton mit Pfeiltasten bewegen AWT, Swing, JavaFX & SWT 6
L Swing Panels bewegen wie Windows 10 Kacheln AWT, Swing, JavaFX & SWT 0
KilledByCheese 2D-Grafik Feld automatisch bewegen, in zeitabständen AWT, Swing, JavaFX & SWT 7
N Programm mit Swing und Thread, Figur bewegen sich nicht AWT, Swing, JavaFX & SWT 6
K Funktion für das Bewegen des Balles AWT, Swing, JavaFX & SWT 5
Z SnakeGame Schlange per KeyListener bewegen! AWT, Swing, JavaFX & SWT 10
F 2D-Grafik Objekt durch Einwirkung einer Kraft im Raum bewegen AWT, Swing, JavaFX & SWT 14
B Swing Form undecorated: Beim Bewegen geht die Maus immer automatisch zur linken Seite. AWT, Swing, JavaFX & SWT 7
A Panel lässt sich nicht bewegen AWT, Swing, JavaFX & SWT 2
D Bild bewegen mit Tastendruck AWT, Swing, JavaFX & SWT 7
E Swing Objekt zu Position (Point) bewegen AWT, Swing, JavaFX & SWT 2
M Swing + Java2D Sichtfeld bewegen verhält sich träge AWT, Swing, JavaFX & SWT 4
F Maus von alleine bewegen! AWT, Swing, JavaFX & SWT 8
O JLabel bewegen AWT, Swing, JavaFX & SWT 10
D Swing Objekte bewegen mit MouseMotionListener AWT, Swing, JavaFX & SWT 4
T 2D-Grafik Slideshow (DoubleBuffering und Image transformieren/bewegen) AWT, Swing, JavaFX & SWT 6
J Grafik (Kreis) schneller bewegen? AWT, Swing, JavaFX & SWT 6
H Rechteck via Mouse bewegen AWT, Swing, JavaFX & SWT 2
M Eine Kugel nach rechts bewegen AWT, Swing, JavaFX & SWT 5
M Objekte in JPanel bewegen AWT, Swing, JavaFX & SWT 4
U Swing JLabel bewegen mittels Thread AWT, Swing, JavaFX & SWT 3
K Jbutton bewegen AWT, Swing, JavaFX & SWT 4
T jPanels im jFrame bewegen - Auch ohne Textfield? AWT, Swing, JavaFX & SWT 4
G AWT Images aus Imagearray an die Maus pappen und bewegen AWT, Swing, JavaFX & SWT 4
M JPanel im JPanel bewegen AWT, Swing, JavaFX & SWT 7
T Processing: Bild auf X-Achse bewegen AWT, Swing, JavaFX & SWT 4
T Objekt in Kreisbahn bewegen AWT, Swing, JavaFX & SWT 5
E JWindow bewegen, minimieren, vergrößern und schließen AWT, Swing, JavaFX & SWT 5
M grafische objekte erstellen und bewegen AWT, Swing, JavaFX & SWT 4
L 2 Fenster gleichzeitig bewegen AWT, Swing, JavaFX & SWT 2
M Swing [JTextPane] Cursor lässt sich nicht mit Pfeiltasten bewegen AWT, Swing, JavaFX & SWT 3
W Objekte auf JPanel bewegen??? AWT, Swing, JavaFX & SWT 2
C Fenster gleich bewegen funktioniert nicht ganz! AWT, Swing, JavaFX & SWT 11
M DragAndDrop-Waypoints bewegen, ABER Bildschirm flackert AWT, Swing, JavaFX & SWT 3
M Fenster ohne Dekoration bewegen AWT, Swing, JavaFX & SWT 3
M Kreis mit gedrückter Maus bewegen AWT, Swing, JavaFX & SWT 20
S JButton bewegen AWT, Swing, JavaFX & SWT 7
S transparent + bewegen AWT, Swing, JavaFX & SWT 3
H Bild mit Mauszeiger bewegen AWT, Swing, JavaFX & SWT 2
K Punkte in eine bestimmte Richtung bewegen AWT, Swing, JavaFX & SWT 5
T Labels gleichzeitig bewegen und anklicken AWT, Swing, JavaFX & SWT 3
R Buttons bewegen AWT, Swing, JavaFX & SWT 4
W Components Focus mit TAB-Taste VERTIKAL bewegen AWT, Swing, JavaFX & SWT 4
P JSlider automatisch bewegen AWT, Swing, JavaFX & SWT 3
Juelin Zugriff auf Bildschirmobjekte aus einem anderen Programm AWT, Swing, JavaFX & SWT 6
M Seltsame Exception bei setVisible(true) Methode in einem JFrame AWT, Swing, JavaFX & SWT 2
MartinNeuerlich Kann mir jemand, der einen Mac mit einem m1 oder m2-Chip hat, eine POM geben mit der Javafx-Fullscreen beim Mac mit m-Chip funktioniert? AWT, Swing, JavaFX & SWT 1
W 2 JTables in einem Swing-Fenster? AWT, Swing, JavaFX & SWT 5
J JavaFx PDF in einem Element in einem Fenster anzeigen. AWT, Swing, JavaFX & SWT 11
Mojo7310 Ändern von Text in JLabel mit einem Button AWT, Swing, JavaFX & SWT 11
I JTable mit einem Button zu einer Detail Seite springen AWT, Swing, JavaFX & SWT 4
S Swing zu einem Datum Tage addieren/subtrahieren AWT, Swing, JavaFX & SWT 6
E Swing Mausposition auf einem JFrame erkennen AWT, Swing, JavaFX & SWT 5
Jose05 NullPointerException bei Beschreiben eines Labels aus einem Array AWT, Swing, JavaFX & SWT 12
ExceptionOfExpectation Textdarstellung auf einem Canvas mit Hilfe von repaint(); AWT, Swing, JavaFX & SWT 6
2 JavaFX die ChoiceBox leitet den String nicht weiter oder es komm zu einem NullPointer AWT, Swing, JavaFX & SWT 8
L JavaFX javafx.fxml.LoadException bei einem Taschenrechner AWT, Swing, JavaFX & SWT 5
Z GUI Forms - Mehrere Fenster in einem Projekt AWT, Swing, JavaFX & SWT 18
N Nur bei einem Textfiled Nullpointerexception bei getText() AWT, Swing, JavaFX & SWT 1
H JComobox in einem JPopupNeu AWT, Swing, JavaFX & SWT 7
P Button simpler random auf einem JPanel verteilen? AWT, Swing, JavaFX & SWT 3
W Inject bei einem Swing Frontend AWT, Swing, JavaFX & SWT 8
H Daten aus einer XML(x83-Datei) in einem JFrame anzeigen lassen AWT, Swing, JavaFX & SWT 9
Z Swing Drag and Drop mit einem JButton AWT, Swing, JavaFX & SWT 1
Z Mit einem Button einen anderen Button Triggern AWT, Swing, JavaFX & SWT 3
D AWT Wie kann ich ein Frame von einem anderen aus beeinflussen? AWT, Swing, JavaFX & SWT 7
T Setzen von der Schriftgröße bei einem Shell AWT, Swing, JavaFX & SWT 15
A checkbox in einer TableView abhängig von einem anderen Celleninhalt disablen AWT, Swing, JavaFX & SWT 1
J Fenster mit Inhalten aus einem Array Füllen AWT, Swing, JavaFX & SWT 4
D JavaFX Ein Parameter von einem Stage(GUI) zu einem anderen übergeben AWT, Swing, JavaFX & SWT 6
T Bilder bei einem JFrame einfügen AWT, Swing, JavaFX & SWT 4
S JavaFX Variablen in einem FXML File verwenden AWT, Swing, JavaFX & SWT 8
A Objekt von einem Window erstellen? AWT, Swing, JavaFX & SWT 8
Drachenbauer Swing Wie ändere ich die helle geklickt-Farbe von einem JButton? AWT, Swing, JavaFX & SWT 4
ralfb1105 JavaFX Alert Confirmation Dialog aus einem Service Thread AWT, Swing, JavaFX & SWT 8
F JavaFX Aktuelle Zeit in einem TextField anzeigen AWT, Swing, JavaFX & SWT 7
M JavaFX Bild zur ImageView in einem Kreis anzeigen. AWT, Swing, JavaFX & SWT 4
F JavaFX PNG aus einem resource Ordner laden AWT, Swing, JavaFX & SWT 8
F JavaFX Checken ob der Input einem festgelegten Format gleicht AWT, Swing, JavaFX & SWT 7
B JavaFX Bilder in einem Gewissen bereich halten AWT, Swing, JavaFX & SWT 1
cool_brivk24 BufferedImage einem ClickEvent hinzufügen AWT, Swing, JavaFX & SWT 13
Q-bert Doppelclick auf einem List item AWT, Swing, JavaFX & SWT 9
J JavaFX von einem Array aus Buttons herausfinden auf welcher geklickt wurde aus dem Array. AWT, Swing, JavaFX & SWT 1
C SWT autosize bei gc.drawString() auf einem Label AWT, Swing, JavaFX & SWT 7
R Farbe zu einem Eckpunkt generieren AWT, Swing, JavaFX & SWT 2
T Reihenfolge der Komponenten im einem JFrame AWT, Swing, JavaFX & SWT 8
F abgeleitete Panels von einem ContentPanel AWT, Swing, JavaFX & SWT 4
heinz ketchup While-Schleife in einem Service für GUI AWT, Swing, JavaFX & SWT 22
D zwei JLabel stapeln in einem JPanel AWT, Swing, JavaFX & SWT 5
H Hintergrundbild in einem Programm AWT, Swing, JavaFX & SWT 4
F RGB-Werte aus einem String einlesen AWT, Swing, JavaFX & SWT 26

Ähnliche Java Themen


Oben