加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

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

发布时间:2020-12-15 03:07:29 所属栏目:Java 来源:网络整理
导读:我正在为SWT实现甘特图组件,这需要重新绘制一下(例如,图表的整个可见部分为200毫秒). 现在,当我滚动时,我只重新绘制剪切矩形所需的内容.当我快速滚动时,这使得应用程序看起来非常糟糕,因为滚动后仍然可见的部分似乎首先被OS移动,并且当我完成绘制剩余部分(滚
我正在为SWT实现甘特图组件,这需要重新绘制一下(例如,图表的整个可见部分为200毫秒).

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

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

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

package de.ikoffice.gui;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class SlowRepaintProblem {

    public Color[] colors = new Color[501];

    public SlowRepaintProblem() {
        Display display = Display.getDefault();
        for( int i=0; i<=500; i++ ) {
            int r = ( i * 10 ) % 256;
            int g = ( i * 20 ) % 256;
            int b = ( i * 30 ) % 256;
            colors[i] = new Color(display,r,g,b);
        }

        Shell shell = new Shell(display);
        shell.setText("SlowRepaintTest");
        ScrolledComposite comp = new ScrolledComposite(shell,SWT.H_SCROLL | SWT.V_SCROLL | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND);
        SlowRepaintingCanvas canvas = new SlowRepaintingCanvas(comp,SWT.NONE| SWT.NO_BACKGROUND);
        comp.setContent(canvas);
        canvas.setSize(5000,5000);

        // Layouting
        shell.setLayout(new GridLayout());        
        comp.setLayoutData(new GridData(GridData.FILL_BOTH));
        shell.setBounds(50,50,800,600);

        // Showing the control
        shell.open();
        while (!shell.isDisposed()) {
            try {
                if (!shell.getDisplay().readAndDispatch()) {
                    shell.getDisplay().sleep();
                }
            } catch (Throwable e) {
                String message = e.getMessage();
                if( message == null || !e.getMessage().equals("Widget is diposed") ) {
                    e.printStackTrace();
                }
                break;
            }
        }
    }

    public static void main(String[] args) {
        new SlowRepaintProblem(); // Evil constructor call to start main program flow.
    }

    class SlowRepaintingCanvas extends Canvas {

        public SlowRepaintingCanvas(Composite parent,int style) {
            super(parent,style);

            addPaintListener(new PaintListener() {
                @Override
                public void paintControl(PaintEvent e) {
                    GC gc = e.gc;
                    Rectangle r = gc.getClipping();
                    gc.setAlpha(255);
//                    gc.setBackground(ColorUtils.WHITE);
//                    gc.fillRectangle(r);

                    int x = r.x - (r.x % 10);
                    int width = (r.width + r.x - x) - (r.width + r.x - x) % 10 + 10;
                    int y = r.y - (r.y % 10);
                    int height = (r.height + r.y - y) - (r.height + r.y - y) % 10 + 10;

                    gc.setAlpha(128);
                    for( int i = x; i < x+width; i+= 10 ) {
                        gc.setBackground(colors[i/10]);
                        gc.fillRectangle(i,r.y,10,r.height);  
                    }
                    for( int j = y; j < y+height; j+= 10 ) {
                        gc.setBackground(colors[j/10]);
                        gc.fillRectangle(r.x,j,r.width,10);  
                    }
                }
            });
        }

    }

}

解决方法

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

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

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

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

HTH

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读