java – 具有缓慢重绘内容的滚动复合看起来很难看

前端之家收集整理的这篇文章主要介绍了java – 具有缓慢重绘内容的滚动复合看起来很难看前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在为SWT实现甘特图组件,这需要重新绘制一下(例如,图表的整个可见部分为200毫秒).

现在,当我滚动时,我只重新绘制剪切矩形所需的内容.当我快速滚动时,这使得应用程序看起来非常糟糕,因为滚动后仍然可见的部分似乎首先被OS移动,并且当我完成绘制剩余部分(滚动期间变得可见的部分)时,立即显示新的滚动步骤开始,将我的图表的一半移到右边,让我重新绘制另一半.这实际上看起来像我的图表在滚动期间在中间闪烁.

这看起来不太好.有办法解决这个问题吗?这个问题可以理解吗?

编辑:这是一个“小”测试程序,准确显示所描述的行为.您只需要在类路径中运行SWT即可运行它.

  1. package de.ikoffice.gui;
  2.  
  3. import org.eclipse.swt.SWT;
  4. import org.eclipse.swt.custom.ScrolledComposite;
  5. import org.eclipse.swt.events.PaintEvent;
  6. import org.eclipse.swt.events.PaintListener;
  7. import org.eclipse.swt.graphics.Color;
  8. import org.eclipse.swt.graphics.GC;
  9. import org.eclipse.swt.graphics.Rectangle;
  10. import org.eclipse.swt.layout.GridData;
  11. import org.eclipse.swt.layout.GridLayout;
  12. import org.eclipse.swt.widgets.Canvas;
  13. import org.eclipse.swt.widgets.Composite;
  14. import org.eclipse.swt.widgets.Display;
  15. import org.eclipse.swt.widgets.Shell;
  16.  
  17. public class SlowRepaintProblem {
  18.  
  19. public Color[] colors = new Color[501];
  20.  
  21. public SlowRepaintProblem() {
  22. Display display = Display.getDefault();
  23. for( int i=0; i<=500; i++ ) {
  24. int r = ( i * 10 ) % 256;
  25. int g = ( i * 20 ) % 256;
  26. int b = ( i * 30 ) % 256;
  27. colors[i] = new Color(display,r,g,b);
  28. }
  29.  
  30. Shell shell = new Shell(display);
  31. shell.setText("SlowRepaintTest");
  32. ScrolledComposite comp = new ScrolledComposite(shell,SWT.H_SCROLL | SWT.V_SCROLL | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND);
  33. SlowRepaintingCanvas canvas = new SlowRepaintingCanvas(comp,SWT.NONE| SWT.NO_BACKGROUND);
  34. comp.setContent(canvas);
  35. canvas.setSize(5000,5000);
  36.  
  37. // Layouting
  38. shell.setLayout(new GridLayout());
  39. comp.setLayoutData(new GridData(GridData.FILL_BOTH));
  40. shell.setBounds(50,50,800,600);
  41.  
  42. // Showing the control
  43. shell.open();
  44. while (!shell.isDisposed()) {
  45. try {
  46. if (!shell.getDisplay().readAndDispatch()) {
  47. shell.getDisplay().sleep();
  48. }
  49. } catch (Throwable e) {
  50. String message = e.getMessage();
  51. if( message == null || !e.getMessage().equals("Widget is diposed") ) {
  52. e.printStackTrace();
  53. }
  54. break;
  55. }
  56. }
  57. }
  58.  
  59. public static void main(String[] args) {
  60. new SlowRepaintProblem(); // Evil constructor call to start main program flow.
  61. }
  62.  
  63. class SlowRepaintingCanvas extends Canvas {
  64.  
  65. public SlowRepaintingCanvas(Composite parent,int style) {
  66. super(parent,style);
  67.  
  68. addPaintListener(new PaintListener() {
  69. @Override
  70. public void paintControl(PaintEvent e) {
  71. GC gc = e.gc;
  72. Rectangle r = gc.getClipping();
  73. gc.setAlpha(255);
  74. // gc.setBackground(ColorUtils.WHITE);
  75. // gc.fillRectangle(r);
  76.  
  77. int x = r.x - (r.x % 10);
  78. int width = (r.width + r.x - x) - (r.width + r.x - x) % 10 + 10;
  79. int y = r.y - (r.y % 10);
  80. int height = (r.height + r.y - y) - (r.height + r.y - y) % 10 + 10;
  81.  
  82. gc.setAlpha(128);
  83. for( int i = x; i < x+width; i+= 10 ) {
  84. gc.setBackground(colors[i/10]);
  85. gc.fillRectangle(i,r.y,10,r.height);
  86. }
  87. for( int j = y; j < y+height; j+= 10 ) {
  88. gc.setBackground(colors[j/10]);
  89. gc.fillRectangle(r.x,j,r.width,10);
  90. }
  91. }
  92. });
  93. }
  94.  
  95. }
  96.  
  97. }

解决方法

SWT绘画速度非常快,缺少UI通常可以追踪到缓慢的绘画方法.因此,尝试优化绘制图表的算法!一种方法可能是缓存 – 将图表内容绘制到图像中:
  1. Image cache = new Image(Display.getCurrent(),width,height);
  2. GC gc = new GC(cache);

并在滚动时仅重绘必要的图像部分:

  1. gc.drawImage(cache,srcX,srcY,srcWidth,srcHeight,destX,destY,destWidth,destHeight);

一旦图表发生变化 – 然后 – 使用复杂的绘制方法重新绘制缓存图像.

HTH

猜你在找的Java相关文章