【问题标题】:SWT canvas not displaying an image when redrawn unless its 5x5 pixelsSWT 画布在重绘时不显示图像,除非其 5x5 像素
【发布时间】:2013-09-18 11:58:21
【问题描述】:

我的窗口 (SWT) 中有以下 UI 布局:

  • 壳牌
    • TabFolder(填充布局)
    • 复合(行布局(水平)
      • 组(行布局,垂直)
        • 标签
        • 标签
        • 文字(宽度:450)
        • 按钮
      • 组(行布局,垂直)
        • 标签
        • 标签
        • 画布(这就是问题所在)

所有的 RowLayouts 都有以下属性:

wrap = true, justify = true, pack = true, marginLeft = 0

我遇到的问题是,如果我尝试将任何 Image 设置为 canvas (在调用 paint 事件时使用 event.gc.drawImage(0,0) 绘制),它通常根本不会显示,即使调用绘画事件(我看到了System.out.println() 调用)。如果我设置一个 5pixel 的图像并最大化窗口,那么图像被绘制,但它也疯狂地调用绘画事件,并且图像不断闪烁。

我在设置图像后调整画布大小,使用:

canvas.setSize(img.getBounds().width, img.getBounds().width);

如果我删除它,那么闪烁和重复的paint 调用就会消失,但是我仍然无法显示大于 5x5 的图像,它们根本不显示。

这是怎么回事..?我应该切换到 GridLayout 吗?我基本上只想展示两组,每组都包含一个垂直的字段/画布列表。

用于处理图像显示的 ImgCanvas 类的代码:

public class ImgCanvas
{
    private Canvas canvas;
    private Image img; 
    private int lastImgHash = 0;

    public ImgCanvas(Composite parent)
    {
        canvas = new Canvas(parent, SWT.NONE);
        initCanvas();
    }

    public ImgCanvas(Composite parent, Image img)
    {
        canvas = new Canvas(parent, SWT.NONE);
        setImage(img);
        initCanvas();
    }

    public void setCanvas(Canvas canvas)
    {
        this.canvas = canvas;
        this.initCanvas();
    }

    public void setImage(Image img)
    {
        if (this.img != null)
            this.img.dispose();
        this.img = img;

        System.out.println("Set image: " + img.getBounds() + ", " + img.toString());
        redraw();
    }

    public void redraw()
    {
        canvas.redraw();
    }

    protected void initCanvas()
    {
        System.out.println("Canvas started");
        canvas.addPaintListener( getPaintListener() );
        canvas.addDisposeListener( getDisposeListener() );
    }

    protected PaintListener getPaintListener()
    {
        return new PaintListener()
        {
            public void paintControl(PaintEvent e)
            {
                System.out.println("Painting");
                if (img != null )
                {
                    System.out.println("Img:" + img.getBounds() );
                    e.gc.drawImage(img, 0, 0);
                    //canvas.setSize(img.getBounds().width, img.getBounds().width);
                    //canvas.pack();
                }
                else
                    System.out.println("Img is null: " + img);
            }
        };
    }

    protected DisposeListener getDisposeListener()
    {
        return new DisposeListener()
        {
            @Override
            public void widgetDisposed(DisposeEvent e)
            {
                System.out.println("Disposing");
                if (img != null)
                    img.dispose();
            }
        };
    }
}

这是通过以下方式设置的:

imgCanvas = new ImgCanvas(group2); //2nd group in the layout given above.

然后,在第 1 组按钮的点击处理程序(selectionHandler)中,完成以下操作:

    public void widgetSelected(SelectionEvent e)
    {
        //get a screenshot of a particular screen region using Java.Awt.Robot.captureScreenRegion,
        //convert the image into a SWT image, and try to show it:
        Image screenshot = ImgUtility.getScreenShot(0,0,10,10); 
        imgCanvas.setImage(screenshot);
        System.out.println("redrawn");
    }

【问题讨论】:

  • 您能添加有问题的代码吗?
  • 好的,请不要添加代码。我建议,在创建画布时使用以下参数objCanvas =new Canvas(parent, SWT.NO_REDRAW_RESIZE | SWT.DOUBLE_BUFFERED);
  • @ShishirPandey 我添加了一些代码...
  • @ShishirPandey 谢谢,现在闪烁消失了,但问题是图像根本没有显示,除非它的 5x5 像素并且我已经最大化了页面。
  • 好的,谢谢你的代码。我试图在我的最后重现问题。我会在某个时候恢复。

标签: java swt


【解决方案1】:

demo.java

import java.io.File;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import java.awt.Robot.*;

public class Demo {

    static Spinner s;

    public static void main(final String[] args) {
    final Display display = new Display();
    final Shell shell = new Shell(display);
    FillLayout layout= new FillLayout();
    shell.setLayout(layout);

    Composite comp=new Composite(shell, SWT.BORDER_DOT);
    RowLayout r1=new RowLayout(SWT.HORIZONTAL);
    r1.wrap=true;
    r1.justify=true;
    r1.pack=true;
    r1.marginLeft=0;

    RowLayout r2=new RowLayout(SWT.VERTICAL);
    r2.wrap=true;
    r2.justify=true;
    r2.pack=true;
    r2.marginLeft=0;

    comp.setLayout(r1);
    Group grp1;


    grp1= new Group(comp,SWT.BORDER_DASH);
    grp1.setLayout(r2);
    Label l11,l22;
    Text txt;
    Button btn;

    l11=new Label(grp1, SWT.NONE);
    l11.setText("Label1");
    l22=new Label(grp1, SWT.NONE);
    l22.setText("Label2");
    txt= new Text(grp1, SWT.BORDER);
    btn= new Button(grp1, SWT.PUSH);

    Group grp2;


    Label l1,l2;
    grp2= new Group(comp,SWT.BORDER);
    grp2.setLayout(r2);

    //grp2.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

    l1= new Label(grp2, SWT.NONE);
    l1.setText("lable1");

    l2= new Label(grp2, SWT.NONE);
    l2.setText("lable1");

    final ImgCanvas imgCanvas = new ImgCanvas(grp2);


    //shell.redraw();
//  shell.setSize(600, 600);
    shell.open();
    shell.layout();

    btn.addSelectionListener(new SelectionListener() {

        @Override
        public void widgetSelected(SelectionEvent e)
        {
            //get a screenshot of a particular screen region using Java.Awt.Robot.captureScreenRegion,
            //convert the image into a SWT image, and try to show it:
            Image screenshot = new Image(display, "c:\\temp\\imgmsg.png"); 
            imgCanvas.setImage(screenshot);
            System.out.println("redrawn");

        }

        @Override
        public void widgetDefaultSelected(SelectionEvent arg0) {
            // TODO Auto-generated method stub

        }
    });
    while (!shell.isDisposed()) {
      if (!display.readAndDispatch()) {
        display.sleep();
      }
    }  }}

以下是ImgCanvas.Java

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;

public class ImgCanvas
{
    private Canvas canvas;
    private Image img; 
    private int lastImgHash = 0;

    public ImgCanvas(Composite parent)
    {
        canvas = new Canvas(parent, SWT.BORDER);
        initCanvas();
    }

    public ImgCanvas(Composite parent, Image img)
    {
        canvas = new Canvas(parent, SWT.NONE);
       // canvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
     //   canvas.layout();
        setImage(img);
        initCanvas();
    }

    public void setCanvas(Canvas canvas)
    {
        this.canvas = canvas;
        this.initCanvas();
    }

    public void setImage(Image img)
    {
        if (this.img != null)
            this.img.dispose();
        this.img = img;

       // canvas.pack();
      // canvas.getParent().getParent().layout();
      //  canvas.getParent().getParent().getParent().layout();
        canvas.getParent().setSize(img.getBounds().width,canvas.getParent().getSize().y);
        canvas.setSize(img.getBounds().width, img.getBounds().height);



        System.out.println("Set image: " + img.getBounds() + ", " + img.toString());
        redraw();
    }

    public void redraw()
    {
        canvas.redraw();
    }

    protected void initCanvas()
    {
        System.out.println("Canvas started");
        canvas.addPaintListener( getPaintListener() );
        canvas.addDisposeListener( getDisposeListener() );
    }

    protected PaintListener getPaintListener()
    {
        return new PaintListener()
        {
            public void paintControl(PaintEvent e)
            {
                System.out.println("Painting");
                if (img != null )
                {
                    System.out.println("Img:" + img.getBounds() );
                    e.gc.drawImage(img, 0, 0);
                 //   canvas.setSize(img.getBounds().width, img.getBounds().width);
                 //   canvas.pack();
                }
                else
                    System.out.println("Img is null: " + img);
            }
        };
    }

    protected DisposeListener getDisposeListener()
    {
        return new DisposeListener()
        {
            @Override
            public void widgetDisposed(DisposeEvent e)
            {
                System.out.println("Disposing");
                if (img != null)
                    img.dispose();
            }
        };
    }
}

【讨论】:

  • 没有效果。我什至现在已经切换到 GridLayout,而且还是一样。在paintControl 方法中,我添加了这一行:System.out.println("Canvas: " + canvas.getBounds() );。现在输出为:Img:Rectangle {0, 0, 61, 30} Canvas: Rectangle {0, 0, 64, 64}。但尽管如此,图像并未显示。
  • 如果您自己对此进行测试,您是否能够在单击按钮时轻松设置图像并使其正确显示在表单上?如果是这样,我可以看看你的代码在哪里工作吗?
  • Shishir 你有Skype,所以我们可以在SWT相关的事情上互相了解吗?
  • 嗨,很遗憾我没有Skype。 :( 我的电子邮件 ID 在 stackoverflow 配置文件中更新。我们可以使用电子邮件联系。
  • 没有聊天或 IM 程序?
【解决方案2】:

Canvas 的布局数据设置为RowData 实例,其中widthheight 字段设置为图像大小。

【讨论】:

  • 我现在切换到 GridLayout,并尝试为 GridData 提供高度和宽度,但没有效果。 :(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-09
  • 1970-01-01
  • 1970-01-01
  • 2016-08-22
  • 1970-01-01
相关资源
最近更新 更多