Comment savoir si un Graphique.drawImage() est réellement terminée
C'est ma première fois de poser une question sur ici, et je suis en espérant obtenir une réponse ou une idée qui va m'aider.
Je dessine une image de grande dimension et de mise à l'échelle vers le bas avec drawImage(). J'ai alors tout de suite une autre image avec drawImage() que je m'attends à être tiré sur le dessus de la précédente (à la seconde). Le problème est que drawImage retourne immédiatement, même si il faut ~50 ms à l'échelle et le rendu de la première image. La plupart du temps la deuxième image se termine sous le premier parce que c'est peint à la première tandis que la première est en cours de traitement. En gros est-il de toute façon à force de drawImage() bloque jusqu'à ce qu'il fait, ou de quelque sorte de vérifier quand il a terminé?
Je suis conscient de la ImageObserver paramètre, qui fonctionne très bien lors du téléchargement d'une image à partir d'Internet ou quelque chose, mais lors de l'utilisation d'un déjà-chargé BufferedImage, il n'est jamais déclenché ImageUpdate() juste après la mise à l'échelle et le dessin. Essentiellement depuis la première image est déjà "chargé", il ne touche jamais le ImageObserver, il faut juste faire comme ~50 ms dans son propre thread de processus, de ne jamais notifier lorsqu'elle est terminée.
Personne ne sait comment à force de bloquer ou d'attendre jusqu'à ce qu'il est entièrement fait de mise à l'échelle et de blitting une image? Et, évidemment, à l'aide de Fil.sommeil(xx) est un hack et pas viable en raison des différences entre la vitesse de l'ordinateur. Tout cela rendu est arrivé sur l'Événement de fil à l'intérieur de l'paint(Graphics g) de la méthode.
Merci!
EDIT: voici le code que j'ai actuellement ont pour vous donner une idée de la question:
public void paint(Graphics window)
{
window.setColor(Color.WHITE);
window.fillRect(0, 0, Settings.width * Settings.aaFactor, Settings.height * Settings.aaFactor);
Graphics2D window2D = (Graphics2D) window;
window2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
window2D.drawImage(this.image, 0, 0, Settings.width, Settings.height, null);
try
{
Thread.sleep(50);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
window2D.drawImage(this.image2, 0, 0, null);
repaint();
}
EDIT 2: Pour mieux expliquer le problème dont je parle, j'ai fait un exemple de code qui fait mieux ce que j'essaie d'expliquer. Exécutez-le et vous allez voir le scintillement où, parfois, la première image est sur le fond (comme il est censé l'être), mais la plupart du temps, il sera un top (seconde), ce qui est faux. Il suffit de changer les chemins d'accès à une petite image et une grande image.
public class Main extends Applet implements ImageObserver
{
private BufferedImage imageA;
private BufferedImage imageB;
@Override
public void init()
{
try
{
this.imageA = ImageIO.read(new File("C:\\LargeImage.jpg"));
this.imageB = ImageIO.read(new File("C:\\SmallImage.jpg"));
}
catch (IOException e)
{
e.printStackTrace();
}
}
@Override
public void update(Graphics g)
{
paint(g);
}
@Override
public void paint(Graphics g)
{
Graphics2D w = (Graphics2D) g;
w.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
w.drawImage(this.imageA, 0, 0, 50, 50, this);//This takes a while to do (scaling down and drawing)...
w.drawImage(this.imageB, 10, 10, null);//While this is drawn quickly, before A is done.
repaint();
}
@Override
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height)
{
System.out.println("ImageObserver fired, done drawing image. NEVER CALLED!");
return false;
}
}
- Je ne peux pas déterminer quand Java seront effectivement rendre la sortie de l'objet Graphique. La seule chose que vous pouvez vous assurer c'est que cela n'arrivera pas jusqu'à ce que APRÈS la méthode de peinture renvoie, de sorte que le Fil.le sommeil est de ne rien faire d'autre alors ralentir votre programme. Si vous êtes à la peinture par le biais d'un Composant quelconque, le passer à la drawInage que la méthode ImageObserver & laissez la mise à jour de lui-même quand il est prêt. L'autre choix est à l'échelle de l'image dans un thread d'arrière-plan
public class Main extends Applet..
Qui ne fonctionne pas ici, puisque cette applet utilisé des images qui ne sont pas sur les disques locaux. Les Applets sont également plus difficile pour les personnes à exécuter que les applications. Je vous suggère de poster une image basée sur SSCCE que ce soit à chaud des liens vers des images ou de les générer dans le code.
Vous devez vous connecter pour publier un commentaire.
Le dernier argument de
drawImage
(où l'on passe null) est unImageObserver
. Si vous fournissez votre propre implémentation de cette interface (voir la JavaDoc), vous serez informé lorsque l'image a été dessinée.Il est impossible de savoir quand le Swing va afficher le contenu d'un
Graphics
objet à l'écran. Qu'est-ce que sais c'est que ça n'arrivera pas jusqu'à ce que APRÈS lapaint
méthodes de retour (comme leGraphics
objet n'a pas été finalisé pour le rendu jusqu'à ce qu'il n').Ce que vous devez faire est de laisser le
Component
vous faites de la peinture à prendre la décision quand quelque chose a besoin de mise à jour, c'est la façon dont il a été conçu...(Component
implémenteImageObserver
)L'exemple ci-dessous constamment re-échelles de la maîtrise de l'image de fond alors que l'image est redimensionnée
Alors que je suis sûr que vous avez vos raisons, personnellement, je voudrais éviter de
Applet
en faveur deJApplet
et en fait, je serais personnellement d'éviter les applets ou ensemble. J'ai commencé ma carrière de codage des applets, ils sont tout simplement une douleur, surtout quand tout ce que vous essayez de faire est de tester une idée.