java – Swing中的“原子渲染”
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java – Swing中的“原子渲染”,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5113字,纯文字阅读大概需要8分钟。
内容图文
我有一个swing应用程序,在JScrollPane中包含一个SVG画布.
应用程序修改显示的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);
}
}
解决方法:
通常一种可能是使用自定义RepaintManager.下面是一个简单且非常不优化的例子:
public class FreezableRepaintManager extends RepaintManager {
final Set<Component> frozen = new HashSet<Component>();
public void freeze(Container c) {
frozen.add(c);
for (Component child : c.getComponents()) {
if (child instanceof Container) {
freeze((Container) child);
} else {
frozen.add(child);
}
}
}
public void thaw(final Container c) {
frozen.remove(c);
for (Component child : c.getComponents()) {
if (child instanceof Container) {
thaw((Container) child);
} else {
frozen.remove(child);
}
}
c.repaint();
}
@Override
public void addDirtyRegion(JComponent c, int x, int y, int w, int h) {
if (!frozen.contains(c)) {
super.addDirtyRegion(c, x, y, w, h);
}
}
}
使用RepaintManager.setCurrentManager()在代码的早期某处设置重绘管理器,然后在开始一系列操作之前使用freeze(componentTree),并在完成后使用解冻(componentTree).
这适用于大多数组件,但不幸的是JScrollPane是不够的,因为它比大多数组件的绘图更复杂.因此,您可能需要一个JScrollPane,其createViewport()返回一个可以抑制blits的视图端口,例如:
class FreezableViewport extends JViewport {
private boolean frozen;
public void freeze() {
frozen = true;
}
public void thaw() {
frozen = false;
}
@Override
protected boolean computeBlit(int dx, int dy, Point blitFrom,
Point blitTo, Dimension blitSize, Rectangle blitPaint) {
if (frozen) {
return false;
}
return super.computeBlit(dx, dy, blitFrom, blitTo, blitSize, blitPaint);
}
}
这也需要在一系列修改之前冻结,并且在重新调整管理器的解冻方法被调用之前,使用上面的重绘管理器解冻.
内容总结
以上是互联网集市为您收集整理的java – Swing中的“原子渲染”全部内容,希望文章能够帮你解决java – Swing中的“原子渲染”所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。