Bonjour,

Je souhaite mettre en œuvre une fonction zoom dans un ScrollPane pour une
saisie de schéma d'électronique. Je vous explique d'abord l'approche que
j'ai retenue puis le problème qui apparait.

ZoomScrollPane est mis en œuvre via un JScrollPane.setViewportView(ZoomPane)

ZoomPane redéfinit paint(g) pour effectuer g.scale(zoom,zoom);
ZoomPane est un KeyListener : presse +/- pour augmenter/diminuer le zoom.
ZoomPane est également un MouseMotionListener simplement pour requestFocusInWindow();
Enfin ZoomPane contient un seul JComponent qui est nommé drawPane.

drawPane est un canvas sur lequel on vient déposer des Items: une résistance,
un générateur, ici un carré...

Ces Items sont des MouseListeners afin d'être sélectionné lorsqu'ils sont survolés
par la souris. Ils déclenchent repaint et leur bordure devient rouge.

Cette sélection fonctionne correctement tant que le facteur de zoom reste à 1. Si
vous zoomer une fois et survoler le carré (il y un décalage mais ça je sais
résoudre) on constate que seule une partie du bord est rafraichie. Ça fait deux
jours que je cherche à résoudre ce défaut !

Le problème provient du Graphics fourni à la méthode paint de zoomPane. Son
ClipBound (afficher par un rectangle bleu) est trop petit, il n'est pas mis à jour
par g.scale et jusqu'à maintenant je n'ai pas réussi à l'étendre.

Un tel ZoomScrollPane est-il faisable de cette manière ?
Existe-t-il une autre solution pour le réaliser ?

Merci de votre aide.

Code : 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
 
package ZoomScrollPaneFoireux;
 
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
 
public class Main {
 
    public static void main(String[] args) {
        new DrawingTopComponent();
    }
 
    private static class DrawingTopComponent extends JFrame {
        JScrollPane zoomScrollPane;
        static XDrawPane drawPane;
        static ZoomPane zoomPane;
 
        public DrawingTopComponent() {
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            initContentPane();
            pack();
            setLocationRelativeTo(null);
            setVisible(true);
            setBounds(0, 0, 400, 400);
        }
 
        void initContentPane() {
            setLayout(new BorderLayout());
            drawPane = new XDrawPane();
            zoomScrollPane = new JScrollPane();
            add(zoomScrollPane, BorderLayout.CENTER);
            zoomPane = new ZoomPane();
            zoomScrollPane.setViewportView(zoomPane);
            zoomPane.setLocation(0, 0);
            zoomPane.add(drawPane);
            drawPane.setBounds(0, 0, 300, 300);
            Item n = new Item();
            drawPane.add(n);
            n.addMouseListener(n);
            n.setLocation(100, 100);
            validate();
            validateTree();
        }
 
 
        public class ZoomPane extends JComponent implements MouseMotionListener, KeyListener {
 
            public ZoomPane() {
                super();
                addKeyListener(this);
                addMouseMotionListener(this);
            }
            double zoomFactor = 1.2;
            double zoom = 1.0;
 
            public void zoomMore() {
                zoom *= zoomFactor;
                setPreferredSize(new Dimension((int) (drawPane.getWidth() * zoom), (int) (drawPane.getHeight() * zoom)));
                setBounds(0, 0, (int) (drawPane.getWidth() * zoom), (int) (drawPane.getHeight() * zoom));
            }
 
            public void zoomLess() {
                zoom /= zoomFactor;
                setPreferredSize(new Dimension((int) (drawPane.getWidth() * zoom), (int) (drawPane.getHeight() * zoom)));
                setBounds(0, 0, (int) (drawPane.getWidth() * zoom), (int) (drawPane.getHeight() * zoom));
            }
 
            public void paint(Graphics g) {
                Graphics2D g2d = (Graphics2D) g;
                g2d.scale(zoom, zoom);
                Rectangle r = g2d.getClipBounds();
                g2d.setPaint(Color.blue);
                g2d.drawRect(r.x + 1, r.y + 1, r.width - 2, r.height - 2);
                g2d.setClip(r.x, r.y, r.width + 100, r.height + 100);  // useless to extend clip.
                super.paint(g2d);
            }
 
            public void mouseMoved(MouseEvent e) {
                requestFocusInWindow();
            }
 
            public void keyPressed(KeyEvent ke) {
                if (ke.getKeyChar() == '+') {
                    zoomPane.zoomMore();
                }
                if (ke.getKeyChar() == '-') {
                    zoomPane.zoomLess();
                }
            }
 
            public void mouseDragged(MouseEvent e) {
            }
            public void keyTyped(KeyEvent e) {
            }
            public void keyReleased(KeyEvent e) {
            }
        }
 
        public static class XDrawPane extends JComponent {
            public XDrawPane() {
                super();
            }
            public void paint(Graphics g) {
                g.setColor(Color.gray);
                g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
                super.paint(g);
            }
       }
 
        public class Item extends JComponent implements MouseListener {
 
            public Item() {
                super();
                addMouseListener(this);
                setSize(80, 80);
            }
            boolean highlight = false;
 
            public void paintComponent(java.awt.Graphics g) {
                g.setColor(Color.WHITE);
                g.fillRect(0, 0, getWidth() - 1, getHeight() - 1);
                if (highlight) {
                    g.setColor(Color.red);
                } else {
                    g.setColor(Color.BLACK);
                }
                g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
                super.paintComponent(g);
            }
 
            public void mouseEntered(MouseEvent e) {
                highlight = true;
                repaint();
            }
 
            public void mouseExited(MouseEvent e) {
                highlight = false;
                repaint();
            }
 
            public void mouseClicked(MouseEvent e) {
            }
 
            public void mousePressed(MouseEvent e) {
            }
 
            public void mouseReleased(MouseEvent e) {
            }
        }
    }
}