Java, comment dessiner en constante évolution graphique
Ne l'avez pas fait avant, donc évidemment, je l'ai sucer. Ici 64 pixels autour de la position actuelle de la souris est dessinée peu plus gros sur un formulaire. Problème, c'est que c'est le genre de " ralentir, et je n'ai aucune idée de par où commencer à corriger.
En plus de cela, j'ai fait un thread qui appelle constamment mise à jour des graphiques lorsque c'est fini, et un peu de fps, comme du texte, pour montrer vraiment à quelle vitesse les choses sont tirés.
De l'Image exemple: (l'Image est à partir de la lettre " a " dans Eclipse)
Exemple de Code :
@SuppressWarnings("serial")
public static class AwtZoom extends Frame {
private BufferedImage image;
private long timeRef = new Date().getTime();
Robot robot = null;
public AwtZoom() {
super("Image zoom");
setLocation(new Point(640, 0));
setSize(400, 400);
setVisible(true);
final Ticker t = new Ticker();
this.image = (BufferedImage) (this.createImage(320, 330));
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
t.done();
dispose();
}
});
try {
robot = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
t.start();
}
private class Ticker extends Thread {
public boolean update = true;
public void done() {
update = false;
}
public void run() {
try {
while (update == true) {
update(getGraphics());
//try {
//Thread.sleep(200);
//} catch (InterruptedException e) {
//e.printStackTrace();
//return;
//}
}
} catch (Exception e) {
update=false;
}
}
}
public void update(Graphics g) {
paint(g);
}
boolean isdone = true;
public void paint(Graphics g) {
if (isdone) {
isdone=false;
int step = 40;
Point p = MouseInfo.getPointerInfo().getLocation();
Graphics2D gc = this.image.createGraphics();
try {
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
gc.setColor(robot.getPixelColor(p.x - 4 + x, p.y
- 4 + y));
gc.fillOval(x * step, y * step, step - 3, step - 3);
gc.setColor(Color.GRAY);
gc.drawOval(x * step, y * step, step - 3, step - 3);
}
}
} catch (Exception e) {
e.printStackTrace();
}
gc.dispose();
isdone = true;
iter++;
}
g.drawImage(image, 40, 45, this);
g.setColor(Color.black);
StringBuilder sb = new StringBuilder();
sb.append(iter)
.append(" frames in ")
.append((double) (new Date().getTime() - this.timeRef) / 1000)
.append("s.");
g.drawString(sb.toString(), 50, 375);
}
int iter = 0;
}
Modifications apportées:
* ajout de "gc.dispose();"
* ajout de "isdone", afin de redessiner ne pouvait pas être appelé plus vite, alors il devrait.
* ajout de la ce lien à thrashgod source de réécriture
* ajout de la ce lien à thrashgod source de réécriture 2
Pourquoi êtes-vous en invoquant le garbage collector au cours de
paint
?Vraiment envie de peindre ce qui est près de la souris, et vous voulez qu'il travail où la souris est (aussi vite qu'il pouvait, même si sur la vidéo). Le problème, je suppose que vous avez trouvé c'est que la peinture événement pourrait également être appelée non pas par thread t. Je pense, c'est pas un problème, mais il fixe avec l'ajout de "isdone" de toute façon.
Quelques indicateurs généraux (1), vous ne devez peindre sur l'Event Dispatch Thread, mais vous avez l'air d'être de la peinture dans le Ticker Fil. (2) Vous ne devriez pas besoin d'un "fait" variable parce qu'un seul thread ne peut pas être en cours d'exécution de deux morceaux de code à la fois. (3) Essayez et séparer ce dans un Modèle (un 8*8 tableau de Couleurs) et la Vue (que vous demandez à repeindre lorsque le modèle est mis à jour). (4) Envisager l'utilisation de repeindre(x, y, w, h), ce qui indique une zone de fenêtrage et donc repeint plus rapide.
J'ai fait quelques profilage - robot.getPixelColor(..) est chien lent sur mon Mac. C'est un bon endroit pour commencer à chercher des améliorations
OriginalL'auteur Margus | 2010-09-18
Vous devez vous connecter pour publier un commentaire.
Voici mon réécriture majeure avec les modifications ci-après:
Le chrono fonctionne en permanence. Lorsqu'il détecte un changement de pixel de couleur (en raison de la souris en déplaçant vers une autre région ou les pixels sous la souris changer) il détecte exactement ce qui a changé, les mises à jour du modèle, puis demande l'avis de la repeindre. Cette approche est mise à jour instantanément à l'œil humain. 289 mises à jour d'écran a pris cumulativement 1 seconde.
C'était un défi plaisant calme pour un samedi soir.
+1 j'ai pris la liberté d'utiliser
createScreenCapture()
pour accélérer mon code alternatif.OriginalL'auteur Steve McLeod
Si vous n'avez pas l'esprit à l'aide de Swing, ce exemple montre comment effectuer rapidement un zoom avant sur une
BufferedImage
obtenues à partir d'unIcon
. Dans votre cas, vous voulez un 8x8BufferedImage
qui se remplit enmouseMoved()
avec les pixels vu par le robot.Addendum: Voici un aperçu du coin supérieur gauche de votre exemple.
Addendum:
La partie lente est l'obtention de pixels à partir du bureau; mise à l'échelle est mineur. Si vous voulez juste pour voir à une variété de techniques d'animation, jetez un oeil à cette exemple.
Addendum: Comme l'obtention de chacun des pixels est lent et le
createScreenCapture()
méthode proposée par @Steve McLeod est rapide, voici l'idée que j'étais en route. Vous pouvez voir aussi les mises à jour beaucoup plus en douceur. Notez que de relâcher le bouton de la souris permet de voir les couleurs capturées.Êtes-vous essayer de faire un zoom sur un composant ou sur le bureau?
Zoom communique lui-même n'est pas important, juste besoin d'une entrée rapide pour le changement de graphiques.
Ajout d'un lien vers votre réécriture du code, si vous pouviez voir ce que j'ai fait, et ce que je voulais dire par "avec pas de différence notable".
Je ne suis pas à la suite de ce que vous essayez de faire. J'ai ajouté un lien vers une animation exemple.
OriginalL'auteur trashgod
Ajouter cette méthode à la méthode de Peinture:
Bon alors d'utiliser une minuterie pour ralentir retard, pas de thread, c'est mauvais.
C'est juste pour ralentir le dessin donc il n'y a pas de scintillement.
Ensuite, envisager un Swing timer: docs.oracle.com/javase/7/docs/api/javax/swing/Timer.html ... jamais sommeil sur l'event dispatch thread 😉 (pour presque tous les sens de "jamais")
J'y ai ajouté une minuterie à la place d'un nouveau Thread. Maintenant, pourquoi est-ce mauvais? Il fonctionne lorsque je l'utilise.
Voir docs.oracle.com/javase/tutorial/uiswing/concurrency/... - tout retard sur l'event dispatch thread affecter la réactivité de l'application, ce qui peut causer des événements de l'arriéré.
OriginalL'auteur Blue Okiris
Simplement utiliser un temps de retard de la boucle.Vous pouvez ensuite affiner, le retard pris par le réglage de la limite de je.Il vous donne également la commande pour régler la transition de la vitesse de certains de frapper et d'essais.
for(long i=0;i<=100000000000;i++);
toile.repaint();
Il fonctionne très bien avec moi et aussi pas besoin d'utiliser un tampon d'images.
OriginalL'auteur Ritik