Applet: Bilder Flackern

devilmc

Mitglied
Hallo,

ich bin gerade dabei ein Applet zu programmieren, welches aus einem Verzeichnis Bilder läd und diese in einem Strip anzeigt.
Die Bilder werden einzelnen Canvas gezeichnet und diese Canvas liegen in einem Panel mit GridBagLayout.
Dieses Panel ist dann in einem Scrollpane...

Das Anzeigen der Bilder und das Scrollen funktioniert, aber hier tritt mein Problem auf.
Wenn ich scrolle, flackern die Bilder bzw. der Hintergrund.
Am Rand des Applets flackert es Schwarz und zwischen den Bilder ist ein Zwischen Raum in dem es Weiß flackert. Muss also irgendwas mit den Paint Methoden zutun haben. Das Scrollpane liegt wieder in einem Panel, das ein Bild als Hintergrund hat.
Dieses wird auch angezeigt.

Kann mir jemand sagen, wie ich diese Flackern wegbekomme...
Die Bilder ansich Flackern nicht sondern nur beim scrollen an den Rändern der Bilder... entweder Links oder Recht, da ich nur Horizontal scrolle...

Freue mich schon auf Antwort.

Grüße
Devilmc
 
Hi devilmc,
Ich würde wenn möglich an Deiner Stelle Swing verwenden, da dort schon ein Doppelpuffer eingebaut ist, der AFAIK im AWT fehlt und selbst implementiert werden müsste.
Verwende also JPanel und JScrollPanel und alles wird gut :)
 
Ich hatte es am Anfang mit JPanels versucht, aber das Problem hier war, das die Bilder nie voll gezeichnet wurden, bzw das die Panels in der Größe gestaucht wurden und dafür habe ich den Fehler nicht gefunden, daher habe ich für die Canvas entschieden,
 
Kann es sein, dass Du bei dem Versuch von JPanel kein JScrollpane verwendet hattest? Man kann z.B. die größe des Panels auch setzen und sich dabei an der größe des Bildes orientieren.
BTW: möchtest Du eigetnlich Dein Bild auch skalieren können?
Falls dem so sei, da hätte ich eine nette Klasse für Dich die gleich mit einer Sliderbar aufwartet. Ebenso kann man mittels Mouserad verkleinern oder vergrößern. Allerdings setzt das voraus, dass Pannel eine bestimmte Mehtode implementiert.
 
ja ich hatte das schon in nem scrollpane, daran hatte sich ja nix geändert,
habe aber das prob jetzt soweit gelöst mit dem jpanel.
hatte was mit dem gridbaglayout zutun, warum der spass nicht richtig angezeigt wurde, anscheinend interessiert das Panel die methode setSize(w,h); nicht
sondern mann muss das panel über das gridbag skalieren...

die bilder sollten zwar nicht skalierbar sein, aber ich wäre dennoch für die class dankbar, da ich doch einiges vom aktuellen projekt auch mal wiederverwenden will für andere dinge...
 
Ein zoomfähiges Panel sei von folgender Klasse abgeleitet, wobei es mittels des zoomFactors in z.B. seiner paintComponent-Routine mittels Verhältnisrechnung seinen Inhalt zeichnet.
Java:
import javax.swing.JPanel;


abstract public class ScalablePanel extends JPanel
{
	abstract public void      setScaling(double zoomFactor);
}

Das ist die Komponente welche ein von ScalablePanel abgeleitetes Objekt aufnimmt und mittels slider-bar und auch MouseWheel die Darstellung skaliert
Java:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;

public class ScalingPanel extends JPanel implements MouseWheelListener
{
    private BorderLayout        m_borderLayout1  = new BorderLayout();
    private JSlider             m_zoomSlider     = new JSlider();
    private JScrollPane         m_scrollPanel    = new JScrollPane();
    private ScalablePanel       m_scalablePanel;

    public ScalingPanel()
    {
        try
        {
            jbInit();
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
        }
    }

    private void jbInit() throws Exception
    {
        this.setLayout(m_borderLayout1);
        m_zoomSlider.setOrientation(JSlider.VERTICAL);
        m_zoomSlider.addChangeListener(new javax.swing.event.ChangeListener()
        {
            public void stateChanged(ChangeEvent e)
            {
                zoom();
            }
        });
        this.add(m_zoomSlider, BorderLayout.WEST);
        this.add(m_scrollPanel,  BorderLayout.CENTER);
        m_zoomSlider.setMaximum(500);
        m_zoomSlider.setMinimum(5);        
    }

    public  void zoom()
    {
    	if (m_scalablePanel!=null)
    	{
    		double zoomFaktor = (double)m_zoomSlider.getValue()/(double)100;
    		m_scalablePanel.setScaling(zoomFaktor);
    		Dimension d = m_scalablePanel.getPreferredSize();
    		m_scrollPanel.getVerticalScrollBar().setMaximum(d.width);
    		m_scrollPanel.getHorizontalScrollBar().setMaximum(d.height);
    	}
    }


    public ScalablePanel getScalablePanel()
    {
    	return m_scalablePanel;
    }

    public void setScalablePanel(ScalablePanel scalabePanel)
    {
    	if (m_scalablePanel!=null)
    	{
    		m_scalablePanel.removeMouseWheelListener(this);
    	}
    	m_scalablePanel = scalabePanel; 
    	m_scrollPanel.getViewport().add(m_scalablePanel, null);
    	
    	m_scalablePanel.addMouseWheelListener(this);
    	
    	zoom();
    }
    
    /** 
	 * @see java.awt.event.MouseWheelListener#mouseWheelMoved(java.awt.event.MouseWheelEvent)
	 */
	public void mouseWheelMoved(MouseWheelEvent e)
	{
		m_zoomSlider.setValue(m_zoomSlider.getValue()+e.getWheelRotation()*10);
		
	}
}

Nun fragst Du Dich möglicherweise wie man ein Panel dazu bekommt seinen darzustellenden Inhalt skalieren zu können. Es ist lediglich proportionales Rechnen (Dreisatz) dazu notwendig.

hier ein aus einem meiner Programme mal rausgegriffenes und runtergebrochenes aber ungetestetes Besiepiel:
Java:
public class SampleImagePanel extends ScalablePanel
{
    protected ImageIcon     m_planBild;
    protected URL           m_imageURL = null;
    protected double        m_skalaFaktor;

    public void setScaling(double faktor)
    {
        m_skalaFaktor = faktor;
        int width;
        int height;
        
        if (m_planBild!=null)
        {
        	width  = new Double((double)m_planBild.getIconWidth() * m_skalaFaktor).intValue();
        	height = new Double((double)m_planBild.getIconHeight() * m_skalaFaktor).intValue();
        }
            
        setPreferredSize(new Dimension(width, height));
    	setSize(new Dimension(width, height));
    }

    public void loadPlanBild(String imageFileName) throws MalformedURLException
    {    	
    	if (imageFileName!=null && imageFileName.length()>0)
    	{
    		m_imageURL = new File(imageFileName).toURI().toURL();
    		m_planBild = new ImageIcon(Toolkit.getDefaultToolkit()
                                              .createImage(m_imageURL));
    	}
    	else
    	{
    		m_planBild = null; 
    	}
    }
    
    public void loadPlanBild(URL imageURL)
    {
    	m_imageURL = imageURL;
    	m_planBild = new ImageIcon(Toolkit.getDefaultToolkit()
                                          .createImage(imageURL));
    }

// Nachtrag ;-)
    protected void paintComponent(Graphics g)
    {    	
        super.paintComponent(g);        
        Dimension d  = getPreferredSize(); 
        if (m_planBild!=null)
        {
        	g.drawImage(m_planBild.getImage(),0,0,d.width,d.height, (Color)null,m_planBild.getImageObserver());
        }
    }


}
Die für obige Klasse notwendigen Import Statements kannst Du Dir mit Eclipse mit quasi gleichzeitigen drücken von [shift] [Strg] [o] reinholen.

Falls noch etwas fehlen sollte oder unklar ist, sag mir einfach bescheid.

viel Spaß,
Takidoso
 
Zuletzt bearbeitet:
Zurück