Swing Lauftext Performance Probleme, in größerer Anwendung

sMau90

Aktives Mitglied
Hey,
Ich habe eine Klasse geschrieben welche einen Lauftext in Java realisiert, sie erweitert JComponent und das zeichnen wird in der paintComponent Methode realisiert. Ich benutze einen SwingTimer für das Aufrufen von repaint() in einem vorgegebenen Intervall um so die Geschwindigkeit des Textes zu beinflussen. Das Programm um das es geht ist schon recht groß und es kommt zu folgendem Problem:
Wenn ich z.B. nun dass "Einstellungs-Fenster" meines Programms öffne, stockt der Text für einen winzigen Moment, es ist nicht sonderlich viel, aber sichtbar. Das Ganze tritt mehr oder weniger stark bei noch anderen "größeren" Aktionen auf. Ich habe schon versucht durch Optimierungen, wie alle größeren Aufgaben in SwingWorker Klassen auszulagern, oder überall dort wo es möglich ist durch die Beachtung vom Clip des GraphicsContext, die Probleme in den Griff zu bekommen. Es ist dadurch auch bedeutend besser geworden, aber leider gibt es bei bestimmten Aktionen immer noch leichte, aber leider sichtbare Ruckler.
Da Swing mit dem EDT ja ein Single-Threaded-Model umsetzt, hab ich leider nun keine Idee mehr was ich da noch machen kann.
Ich hoffe jemand von euch hat hier ein paar Tips oder Tricks wie ich das ganze besser in den Griff bekomme.
Hier mal der Code der entsprechenden Komponente.


Java:
public class TickerComponent extends JComponent {
	
	private String tickerString;
	private int posOfString1;
	private int posOfString2;
	
	private int toDrawStringWidth;
	
	private int tickerSpeed;
	
	private String toDraw1;
	private String toDraw2;
	
	private Timer liveTickerTimer;

	public TickerComponent() {
		super();
		posOfString1 = getWidth();
		posOfString2 = getWidth();
		
		try {
			tickerSpeed = Integer.parseInt(PreferencesHandler.getInstance().getProperties().getProperty(Constants.PROP_TICKER_SPEED));
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
        startLiveTicker();

		
	}
	
	/**
	 * creates a new Swing Timer with the given update interval and starts the timer.
	 * The timer refreshes the ticker component every x milliseconds.
	 */
	public void startLiveTicker() {

		liveTickerTimer = new Timer(tickerSpeed, new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				repaint(0, 0, getWidth(), getHeight()); 
			}
		});
    	liveTickerTimer.start();
    	
	}
    
	/**
	 * stops the timer
	 */
    public void stopLiveTicker() {
    	liveTickerTimer.stop();
    }

    
	/**
	 * Set the ticker string to draw on the component.
	 * A GUI update is invoked automatically after setting the new string.
	 * @param tickerString
	 */
	public void setTickerString(String tickerString) {
		this.tickerString = tickerString;
		if(tickerString != null && !tickerString.equals("")) {
			generateDrawingStrings();
		} else if(tickerString != null) {
			toDraw1 = " ";
			toDraw2 = " ";
			stopLiveTicker();
		} else {
			stopLiveTicker();
		}
	}
	
	/**
	 * needs to be invoked after resizing the tickerComponent, e.g. after entering the fullscreen
	 */
	public void refreshStringGeneration() {
		generateDrawingStrings();
	}
	
	/**
	 * generates the two strings needed for a gapless ticker run.
	 */
	private void generateDrawingStrings() {

		int tickerStringWidth = getFontMetrics(getFont()).stringWidth(tickerString);
		
		toDraw1 = tickerString;
		toDrawStringWidth = tickerStringWidth;
		
		while(toDrawStringWidth < getWidth()) {
			toDrawStringWidth = toDrawStringWidth + tickerStringWidth;
			toDraw1 = toDraw1 + tickerString;
		}
		
		toDraw2 = toDraw1;
		posOfString2 = posOfString1 + toDrawStringWidth;
		
	}

	@Override
	protected void paintComponent(Graphics g) {

		if (toDraw1 != null && toDraw2 != null && !toDraw1.equals("") && !toDraw2.equals("")) {
			posOfString1--;
			posOfString2--;
			//if last char of the string is not visible anymore
			if(posOfString1 + toDrawStringWidth  < 0 ) {
				posOfString1 = posOfString2 + toDrawStringWidth;
			}
			//if last char of the string is not visible anymore
			if(posOfString2 + toDrawStringWidth < 0 ) {
				posOfString2 = posOfString1 + toDrawStringWidth;
			}
			Graphics2D tmpG2D = (Graphics2D) g.create();
	        tmpG2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
	        tmpG2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
			
	        tmpG2D.drawString(toDraw1, posOfString1, 55);
	        tmpG2D.drawString(toDraw2, posOfString2, 55);
	        tmpG2D.dispose();
		} else {
			stopLiveTicker();
		}
	}

}

Vielen Dank schonmal.
Grüße,
sMau
 
Zuletzt bearbeitet:
H

hüteüberhüte

Gast
Alles, was mit GUI zu tun hat, sollte im EDT geschehen (invokeLater-Methode aufrufen): A Java SwingUtilities invokeLater example | SwingUtilities invokeLater and the EventDispatchThread (EDT) | devdaily.com (kurze Zusammenfassung)

Inwieweit dies bei dir der Fall ist, kann ich auf die Schnelle nicht nachvollziehen

Und, inwiefern SwingWorker evtl. schneller sein könnte, auch nicht. Aber in der API werden zwei Beispiele genannt, die vielleicht aufschlussreich sind: SwingWorker (Java Platform SE 6)
 
Zuletzt bearbeitet von einem Moderator:

Michael...

Top Contributor
Mal unabhängig von dem Problem würde ich den
Code:
tickerSpeed
fest einstellen, so dass mit 20 - 30 fps gezeichnet wird und stattdessen die Schrittweite anpassen, um die Laufgeschwindigkeit zu variieren.
Ausserdem gehört die Postionsberechnung aus der paintComponent raus, da diese 1. in regelmäßigen Intervallen (gleichmäßige Geschwindigkeit) neu berechnet werden soll und nicht bei jedem neuzeichnen der Komponente und 2. in der paintComponent grundsätzlich nur das nötigste berechnet werden soll, um den EDT möglichst wenig zu blockieren.
Evtl. für das sogar schon zu einer Verbesserung des Problems.
 

sMau90

Aktives Mitglied
Wow, cool vielen Dank @Michael. Genau das was du gesagt hast hat geholfen. Ich hab nun die Berechnung der String Positionen in einen java.util.Timer ausgelagert, welcher dann über invokeLater auf dem EDT nur das repaint() aufruft. In der paintComponent wird nun wirklich nur noch gezeichnet und siehe da die Ruckler sind weg.
Hier falls es jemand interessiert die fertige Lösung:

Java:
public class TickerComponent extends JComponent {

	private static final long serialVersionUID = 4472552567124740434L;
	
	private String tickerString;
	private int posOfString1;
	private int posOfString2;
	
	private int toDrawStringWidth;
	
	private int tickerSpeed;
	
	private String toDraw1;
	private String toDraw2;
	
	private Timer liveTickerTimer;

	
	class TickerTimerTask extends TimerTask {
		public void run() {
			runLiveTicker();
		}
	}
	
	public TickerComponent() {
		super();
		posOfString1 = getWidth();
		posOfString2 = getWidth();
		
		try {
			tickerSpeed = Integer.parseInt(PreferencesHandler.getInstance().getProperties().getProperty(Constants.PROP_TICKER_SPEED));
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
        startLiveTicker();

		
	}
	
	private void runLiveTicker() {
		if (toDraw1 != null && toDraw2 != null && !toDraw1.equals("") && !toDraw2.equals("")) {
			posOfString1--;
			posOfString2--;
			
			//if last char of the string is not visible anymore
			if(posOfString1 + toDrawStringWidth  < 0 ) {
				posOfString1 = posOfString2 + toDrawStringWidth;
			}
			//if last char of the string is not visible anymore
			if(posOfString2 + toDrawStringWidth < 0 ) {
				posOfString2 = posOfString1 + toDrawStringWidth;
			}
			SwingUtilities.invokeLater(new Runnable() {
				
				@Override
				public void run() {
					repaint(0, 0, getWidth(), getHeight());
				}
			});
			
		} else {
			stopLiveTicker();
		}
		
	}
	
	/**
	 * creates a new Swing Timer with the given update interval and starts the timer.
	 * The timer refreshes the ticker component every x milliseconds.
	 */
	public void startLiveTicker() {
		liveTickerTimer = new Timer();
		liveTickerTimer.schedule(new TickerTimerTask(), 0, tickerSpeed);
    	
	}
    
	/**
	 * stops the timer
	 */
    public void stopLiveTicker() {
    	
    	liveTickerTimer.cancel();
    	liveTickerTimer.purge();
    }
    
	/**
	 * Set the ticker string to draw on the component.
	 * A GUI update is invoked automatically after setting the new string.
	 * @param tickerString
	 */
	public void setTickerString(String tickerString) {
		this.tickerString = tickerString;
		if(tickerString != null && !tickerString.equals("")) {
			generateDrawingStrings();
		} else if(tickerString != null) {
			toDraw1 = " ";
			toDraw2 = " ";
			stopLiveTicker();
		} else {
			stopLiveTicker();
		}
	}
	
	/**
	 * needs to be invoked after resizing the tickerComponent, e.g. after entering the fullscreen
	 */
	public void refreshStringGeneration() {
		generateDrawingStrings();
	}
	
	/**
	 * generates the two strings needed for a gapless ticker run.
	 */
	private void generateDrawingStrings() {

		int tickerStringWidth = getFontMetrics(getFont()).stringWidth(tickerString);
		
		toDraw1 = tickerString;
		toDrawStringWidth = tickerStringWidth;
		
		while(toDrawStringWidth < getWidth()) {
			toDrawStringWidth = toDrawStringWidth + tickerStringWidth;
			toDraw1 = toDraw1 + tickerString;
		}
		
		toDraw2 = toDraw1;
		posOfString2 = posOfString1 + toDrawStringWidth;
		
	}

	@Override
	protected void paintComponent(Graphics g) {
		Graphics2D tmpG2D = (Graphics2D) g.create();
        tmpG2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        tmpG2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		
        tmpG2D.drawString(toDraw1, posOfString1, 55);
        tmpG2D.drawString(toDraw2, posOfString2, 55);
        tmpG2D.dispose();
	}

}


Hab aber grade noch eine Frage zu dem was du gesagt hast, bzgl des fixieren des Updateintervalls. Ich hab da auch schon dran gedacht, so dass ich ne feste Framerate kriege, was mich an dieser Lösung stört ist die schlechte Skalierung der Geschwindigkeit, also ich kann ja immer nur entweder 1px pro Zyklus, oder 2px oder nur jeden 2. Zyklus 1px, wobei ich da die Geschwindigkeit ja jeweils halbiere/verdopple in diesem Beispiel. Gibts da ne bessere Variante, bei der ich feinere Einstellungsmöglichkeiten erreiche aber trotzdem eine feste Framerate vorgebe?

Grüße,
sMau
 
Zuletzt bearbeitet:

bERt0r

Top Contributor
Das geht so: Du verwendest die Formel v=s/t (Oder Geschwindigkeit = Weg/Zeit). -> s=v*t

Also statt posOfString dauernd um 1 zu erhöhen zählst du die Ticks und machst
Java:
posOfString = (v * ticks) % breite;
 

Ark

Top Contributor
Also statt posOfString dauernd um 1 zu erhöhen zählst du die Ticks und machst
Java:
posOfString = (v * ticks) % breite;
Vorsicht! Wenn immer nur [c]ticks++[/c] gerechnet wird, wird ticks irgendwann negativ (auch wenn dies bei int sehr lange dauern dürfte, und, wenn dies bei long passieren sollte, mindestens alle jetzt lebenden Menschen, wenn nicht sogar unser Sonnensystem, gestorben sein werden :D).

Also sollte möglichst früh ein geeignetes [c]ticks %= maxTicks[/c] oder Ähnliches stehen.

Ark
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
O Lauftext in Java Appliaktion AWT, Swing, JavaFX & SWT 6
H Viele ActionListener (MouseListener) - Performance AWT, Swing, JavaFX & SWT 24
missy72 JavaFX Performance / ImageView in TableView über TimeLine AWT, Swing, JavaFX & SWT 1
L JavaFX ListCell Performance AWT, Swing, JavaFX & SWT 10
E Swing Miserable Performance beim Ändern der Hintergrundfarbe von JLabels AWT, Swing, JavaFX & SWT 3
W Swing Performance bei Griderstellung verbessern AWT, Swing, JavaFX & SWT 15
C Pixel-Rendering/Animation Performance in BufferedImage AWT, Swing, JavaFX & SWT 1
I JavaFX Graphics Performance AWT, Swing, JavaFX & SWT 2
S Swing Performance bei Verschachtelung problematisch AWT, Swing, JavaFX & SWT 0
R Performance Drag and Drop & Timer AWT, Swing, JavaFX & SWT 3
O AWT Performance und Bug behebung[brauche Hilfe] AWT, Swing, JavaFX & SWT 2
T Swing Allgemeines Problem mit der Performance bei DragAndDrop AWT, Swing, JavaFX & SWT 2
T Prüfen ob 2 JLabel übereinander liegen. Performance Problem. AWT, Swing, JavaFX & SWT 5
B Performance-Probleme AWT, Swing, JavaFX & SWT 17
D DefaultTableCellRenderer - Performance AWT, Swing, JavaFX & SWT 3
hdi Swing [Umfrage] Swing Performance AWT, Swing, JavaFX & SWT 27
B 2D-Grafik BufferedImage Performance AWT, Swing, JavaFX & SWT 3
C Performance-Problem beim Überschreiben von paintComponent() AWT, Swing, JavaFX & SWT 2
Hausmeister JTable mit Bildern - Performance AWT, Swing, JavaFX & SWT 5
J JTree Performance AWT, Swing, JavaFX & SWT 2
Developer_X Swing Graphics2D translate zerstört performance AWT, Swing, JavaFX & SWT 2
hdi Swing JTable: Mein CellRenderer ist ein Performance-Killer? AWT, Swing, JavaFX & SWT 7
J Performance bei mouseMoved(...) AWT, Swing, JavaFX & SWT 4
L JFreeChart - Performance bei PNG-Erstellung AWT, Swing, JavaFX & SWT 5
P seltsame Performance Probleme bei 2 Guis abhängig vom Aufruf AWT, Swing, JavaFX & SWT 8
G Performance beim Zeichnen erhöhen? AWT, Swing, JavaFX & SWT 21
hdi bitte um performance ratschläge AWT, Swing, JavaFX & SWT 31
G performance fragen zu AWT, Swing AWT, Swing, JavaFX & SWT 14
T (Java 6) Thumbnails in JFileChooser - Performance steigern? AWT, Swing, JavaFX & SWT 3
hdi schlechte performance bei simplem swing AWT, Swing, JavaFX & SWT 9
G Probleme mit Performance bei einer Tabelle AWT, Swing, JavaFX & SWT 16
M Performance SWT ??? AWT, Swing, JavaFX & SWT 8
D performance problem: paintcomponent, alphacomp, bufferedImag AWT, Swing, JavaFX & SWT 10
P SWT: StyledText Performance steigern? AWT, Swing, JavaFX & SWT 2
T Performance Problem bei BufferedImage AWT, Swing, JavaFX & SWT 3
P SWT Performance : "Text" - Ausgabe beschleunigen ? AWT, Swing, JavaFX & SWT 21
O performance g2d.drawImage() AWT, Swing, JavaFX & SWT 17
D Performance Probleme Jtable AWT, Swing, JavaFX & SWT 4
N Performance (BufferStrategy?) AWT, Swing, JavaFX & SWT 2
F Problem mit Transparenz, MouseEvents und Performance AWT, Swing, JavaFX & SWT 3
O LookAndFeel und Performance AWT, Swing, JavaFX & SWT 7
W Performance verbessern AWT, Swing, JavaFX & SWT 2
S TableCellRenderer, Performance AWT, Swing, JavaFX & SWT 9
S Performance-Problem: JTextArea als Logging-Window AWT, Swing, JavaFX & SWT 8
Juelin Probleme bei Stage.close() AWT, Swing, JavaFX & SWT 23
XWing Swing Image anzeigen und probleme mit klassen AWT, Swing, JavaFX & SWT 3
E repaint Probleme AWT, Swing, JavaFX & SWT 13
mananana Mögliche probleme die in einer GUI passieren Können AWT, Swing, JavaFX & SWT 6
S GridBagLayout - Probleme mit Bilderanzeige AWT, Swing, JavaFX & SWT 3
I Probleme beim Drucken auf einen PDF-Drucker AWT, Swing, JavaFX & SWT 8
J Probleme mit idividueller Tablecell AWT, Swing, JavaFX & SWT 0
D JavaFX Probleme beim nachtäglichen hinzufügen der jfx dependency AWT, Swing, JavaFX & SWT 7
J Probleme mit InputDialog AWT, Swing, JavaFX & SWT 4
D JavaFX TextArea Probleme bei langen Zeilen AWT, Swing, JavaFX & SWT 1
G JavaFX SplitPane Anwendung - Controller Probleme AWT, Swing, JavaFX & SWT 5
K Probleme bei der Erstellung und Ausführung einer Jar Datei AWT, Swing, JavaFX & SWT 2
B Probleme Action Listener Taschenrechner AWT, Swing, JavaFX & SWT 27
pph080560 JavaFX Probleme mit FX AWT, Swing, JavaFX & SWT 3
M Probleme mit OpenJDK AWT, Swing, JavaFX & SWT 6
B 2D-Grafik paintcomponent Probleme beim zeichnen AWT, Swing, JavaFX & SWT 10
B Swing Probleme mit dem Layout AWT, Swing, JavaFX & SWT 1
L JavaFX Probleme beim Installieren JavaFX11 / JavaFX12 -- Eclipse 2019-03 AWT, Swing, JavaFX & SWT 3
Fiedlerdan Image-Pfad Probleme nach Export aus Eclipse AWT, Swing, JavaFX & SWT 31
H JFreeChart - DemoDataSetFactory Probleme AWT, Swing, JavaFX & SWT 1
H LayoutManager Probleme mit Positionierung/Abständen der Komponenten AWT, Swing, JavaFX & SWT 14
A Probleme mit gridheight (GridBagLayout) AWT, Swing, JavaFX & SWT 6
U Opaque Probleme AWT, Swing, JavaFX & SWT 3
H JavaFX Probleme Beim Wechseln der scene als .fxml AWT, Swing, JavaFX & SWT 7
F JavaFX Probleme beim automatischen Konvertieren AWT, Swing, JavaFX & SWT 4
S Probleme mit JComboboxen(?) AWT, Swing, JavaFX & SWT 18
S Swing Probleme mit MigLayout AWT, Swing, JavaFX & SWT 2
C Probleme mit createImage AWT, Swing, JavaFX & SWT 1
J Probleme mit contex Menu (javafx) AWT, Swing, JavaFX & SWT 1
J Probleme bei GameofLife AWT, Swing, JavaFX & SWT 24
S JavaFx - Button ActionEvent Probleme AWT, Swing, JavaFX & SWT 3
T Swing Probleme mit repaint() bzw. JScrollPane AWT, Swing, JavaFX & SWT 7
ImperatorMing JavaFX Probleme mit WindowEvent AWT, Swing, JavaFX & SWT 0
ImperatorMing JavaFX Probleme mit WindowEvent AWT, Swing, JavaFX & SWT 5
J LayoutManager GridBagLayout, probleme mit Anordnung von Objekten AWT, Swing, JavaFX & SWT 6
T Java FX Probleme beim befüllen eines Tableviews AWT, Swing, JavaFX & SWT 5
S AWT Probleme beim Zeichnen AWT, Swing, JavaFX & SWT 3
A Swing Probleme mit dem adden von JButtons zur JScrollPane AWT, Swing, JavaFX & SWT 2
D Swing Probleme mit dem Resizing AWT, Swing, JavaFX & SWT 7
G Probleme mit TextArea AWT, Swing, JavaFX & SWT 5
G JFrame Probleme AWT, Swing, JavaFX & SWT 2
K Probleme beim JPasswordField AWT, Swing, JavaFX & SWT 11
G Cardlayout Refresh Probleme AWT, Swing, JavaFX & SWT 2
J Swing Probleme mit ListSelectionListener(), Inhalte der JList werden gelöscht? AWT, Swing, JavaFX & SWT 6
D JavaFX Probleme bei Service-Klasse beim ändern der GUI AWT, Swing, JavaFX & SWT 8
K Probleme beim zeichnen mit paintComponent() AWT, Swing, JavaFX & SWT 1
M JButton Probleme AWT, Swing, JavaFX & SWT 14
L Probleme mit Programm AWT, Swing, JavaFX & SWT 13
blazingblade komischerweise probleme mit jtextfield.gettext() AWT, Swing, JavaFX & SWT 9
Xanny 2D-Grafik Beginner! Probleme mit Swing, Gprahics class und paint AWT, Swing, JavaFX & SWT 13
Sin137 LayoutManager GridBagLayout Probleme AWT, Swing, JavaFX & SWT 6
H Netbeans Designer: Probleme mit JPanel und JFrame AWT, Swing, JavaFX & SWT 2
M Swing Probleme mit Frame.pack() AWT, Swing, JavaFX & SWT 1
C Java FX Probleme beim Schließen einer Stage AWT, Swing, JavaFX & SWT 11
M Swing JProgressbar und Outoputstream probleme AWT, Swing, JavaFX & SWT 2
S Swing Probleme mit transparenz der Hintergrundfarbe und JRadioButtons AWT, Swing, JavaFX & SWT 2

Ähnliche Java Themen

Neue Themen


Oben