У меня есть приложение Swing, которое содержит холст SVG внутри JScrollPane. Приложение изменяет отображаемый документ SVG, что также приводит к изменению размера документа. Это изменение размера должно быть отражено в приложении. Размер холста SVG изменяется, а область просмотра JScrollPane прокручивается, чтобы отображалась правильная часть холста.
Однако это приводит к чему-то вроде «визуального прыжка», потому что пользователь сначала видит изменение размера холста, а уже после этого видит операцию прокрутки.
Есть ли способ сказать java, чтобы он прекратил обработку событий рендеринга для данного компонента (и его подкомпонентов) и возобновил работу только после того, как я закончил свои модификации, чтобы отображать только результат всех модификаций?
Вот моя идея в псевдокоде:
myScrollPane.suspendRendering();
svgDocument.changeSize();
svgCanvas.changeSize();
myScrollPane.getViewport().scrollToCorrectPosition;
myScrollPane.resumeRendering();
Я пробовал с myScrollPane.setIgnoreRepaint(true)
, но, похоже, здесь это не имеет никакого эффекта (даже если я никогда больше не устанавливал ignoreRepaint
в false
.
А вот SSCCE, который пытается имитировать эффект:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class Jumping extends JFrame {
private JButton innerPanel= new JButton("Some silly, useless text, just for fun. And it goes on even longer. But that's not a problem.");
private JScrollPane scrollPane= new JScrollPane(innerPanel);
private JButton btnJump= new JButton("Jump");
private int lastWidth= 1024;
public Jumping(){
this.setLayout(new BorderLayout());
this.add(btnJump, BorderLayout.NORTH);
this.add(scrollPane, BorderLayout.CENTER);
this.scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
this.scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
this.innerPanel.setPreferredSize(new Dimension(1024, 768));
this.innerPanel.setSize(1024, 768);
this.innerPanel.setMinimumSize(new Dimension(1024, 768));
this.innerPanel.setMaximumSize(new Dimension(1024, 768));
this.setSize(640, 480);
this.btnJump.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try{
System.err.println("> actionPerfomed");
//resize the canvas
new Thread(){
public void run() {
System.err.println("> SwingWorker.doInBackground "+SwingUtilities.isEventDispatchThread());
SwingUtilities.invokeLater(new Runnable(){
public void run(){
System.err.println("> resize canvas "+SwingUtilities.isEventDispatchThread());
final int newWidth= (int) (lastWidth * 1.5);
innerPanel.setSize(newWidth, 768);
innerPanel.setPreferredSize(new Dimension(newWidth, 768));
innerPanel.setMinimumSize(new Dimension(newWidth, 768));
innerPanel.setMaximumSize(new Dimension(newWidth, 768));
lastWidth= newWidth;
System.err.println("< resize canvas "+SwingUtilities.isEventDispatchThread());
}
});
//scroll to correct position
SwingUtilities.invokeLater(new Runnable(){
public void run(){
System.err.println("> scroll to pos "+SwingUtilities.isEventDispatchThread());
try {
System.err.println("< sleep "+SwingUtilities.isEventDispatchThread());
Thread.sleep(500);
System.err.println("> sleep "+SwingUtilities.isEventDispatchThread());
} catch (InterruptedException ex) {
ex.printStackTrace();
}
final Point viewPos= scrollPane.getViewport().getViewPosition();
scrollPane.getViewport().setViewPosition(new Point(viewPos.x + 50, viewPos.y));
System.err.println("< scroll to pos "+SwingUtilities.isEventDispatchThread());
}
});
System.err.println("< SwingWorker.doInBackground "+SwingUtilities.isEventDispatchThread());
}
}.start();
System.err.println("< actionPerfomed "+SwingUtilities.isEventDispatchThread());
}catch(Exception ex){
ex.printStackTrace();
}
}
});
}
public static void main(String[] args){
final Jumping frame= new Jumping();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}