Bonjour à tous,

dans le cadre d'une application de jeu, j'utilise un double-buffer hardware via BufferStrategy dans mon application principale (qui s'étend de JFrame).

Mon problème est le concept d'affichage.
Si je fais abstraction de l'utilisation de composants Swing autres que la JFrame et un conteneur dans lequel j'affiche via Java2D toutes les informations de mon jeu (la map, le décor, les persos ...), y a aucun problème.
Du fait de cette abstraction, je n'ai pas à utiliser de méthode paint et d'ailleurs mon package utilise des fonctions draw que j'ai définies.

Le problème, c'est si je veux inclure des composants Swing dans mon application. Tout tourne au cauchemar.

Le début de double-buffering :
Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private Client(){
 
        // # scène de base
 
        setContentPane(stage = new Stage(this, 800, 600));
 
        // # éléments de la scène
        ...
 
        // stage.fullScreen(defaultDM);
 
        // # écouteurs
        ...
 
        // # fenêtrage (suite)
        pack();
        setResizable(false);
        setVisible(true);
        setSize(800, 600);
 
        // # système visuel
        // double buffering
        createBufferStrategy(2);
        strategy = getBufferStrategy();
        buffer = (Graphics2D)strategy.getDrawGraphics();
        stage.setBuffer(buffer);
        // démarrage de l'application
        stage.start();
    }

Suit la redéfinition des méthodes d'affichage de JFrame :
Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public void repaint(int x, int y, int width, int height) {
        display();
    }
 
    public void repaint(long time, int x, int y, int width, int height) {
        display();
    }
 
    public void repaint(long tm) {
        display();
    }
 
    /**
     * @inheritDoc
     */
    public void update(Graphics g){
        display();
    }
 
    /**
     * @inheritDoc
     */
    public void repaint(){
        display();
    }
 
    /**
     * @inheritDoc
     */
    public void paint(Graphics g){
        display();
    }

Et la dite-méthode display qui permet l'affichage :

Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 
    /**
     * Affiche la scène
     */
    public void display() {
        // assert wx.xyndhra.util.debug.trace("[rendering]");
        // Nettoyage
        if(buffer == null) return;
        // buffer.clearRect(0, 0, getWidth(), getHeight());
 
        // --- ui
        ...
        // Nouvelle image
        GraphicSession.width = getWidth();
        GraphicSession.height = getHeight();
 
        // méthode d'affichage
        // stage.draw(new GraphicSession(buffer));
 
        stage.drawable = true;
        // Affichage des composants
        paintComponents(buffer);
        // stage.drawable = false;
        // Affichage en double-buffering hardware
        strategy.show();
        // assert wx.xyndhra.util.debug.trace(" °--- [end rendering]");
    }

Ce code ne marche actuellement pas et la raison semble venir du caractère asynchrone de l'affichage de swing.
paintComponents n'affiche pas les composants...

mais pire, l'objet Graphics qui est passé à paintComponents n'est pas celui que je reçois dans les méthodes d'affichage paintComponent des dits-composants

Deux possibilités m'apparaissent (sans savoir comment s'en tirer réellement) :
1. utiliser la méthode d'affichage direct que j'utilisais, donc sans passer par paintComponents, mais en utilisant draw(new GraphicSession(buffer))
... le gros problème est que ça ne prend pas en compte les composants

2. faire persister l'objet buffer... appeler le strategy.show() plus tard ... non en fait j'ai des doutes sur ce que ça donnerait

Edit :
il semblerait que mon problème de visu venait de l'option d'utilisation d'opengl... ça faisait foirer le rendu

le fait est que maintenant, j'en suis au problème réel, j'ai beau avoir un rendu, il n'est pas bon...

Affichage saccadé incomplet, ne montre que la scène du jeu, et les composants en train d'être modifiés (comme un textfield qui a le focus) :
Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
// Affichage des composants
stage.paint(buffer);

Pour cette version, si j'arrive à trouver comment faire en sorte que mes composants soient complètement affichés, c'est gagné ! (faudrait pouvoir désactiver la vérification des éléments qui ont changé sur le textfield, car je dois le réafficher complètement).

---

Affichage complet, montrant tout, mais avec deux problèmes :
Code java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
// Affichage des composants
paintComponents(buffer);

Les problèmes sont :
1. l'objet Graphics2D qui est utilisé par les composants n'est pas l'original... mais surtout, il y a un décalage car mes calculs de position de la souris quant à la position sur les objets / personnages sont erronés, ils semblent être décalé de quelques dizaines de pixels

2. dès intéraction avec le textfield, ça bloque à presque tous les coups (10 secondes max d'utilisation)... l'application ne plante pas, mais l'affichage freeze complètement (vu que l'affichage est dans un thread séparé, je vois toujours le trace de l'application de base qui elle continue sans problème)

Soit j'arrive à régler ces problèmes, soit y a plus qu'à recréer des composants genre TextField, mais vu que c'est énorme à faire (rendre compte du comportement d'un composant comme TextField), je préfèrerais régler ces deux problèmes