tags:

views:

616

answers:

2

I have a java SWT application that works OK with Windows XP and Windows Vista. But when I run it on Windows 7, weird errors occure, and it crashes.

For example, in a method where I call Table.removeAll() I get a java.lang.ArrayIndexOutOfBoundsException: 0. The table has SWT.VIRTUAL in style.

Another problem is when I write something in a text box (there's a ModifyListener which filters something) - after 2 characters, the cursor moves at the beginning (before first character).

The SWT version is 3.5, but I tried with the latest from the eclipse website(3.6M3) and the result is the same.

Are there any known issues? Has anybody encountered this?


Here is a snippet that doesn't work in Windows 7:

import java.util.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

public class TableCheck {

  Shell shell;

  Button button1, button2, button3;

  UltraTable ut;

  public TableCheck() {
    Display display = new Display();
    shell = new Shell(display);
    shell.setLayout(new GridLayout(4, false));
    Text text = new Text(shell, SWT.SINGLE | SWT.LEAD | SWT.READ_ONLY | SWT.BORDER);
    text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
    text.setText("SWT " + SWT.getPlatform() + " " + SWT.getVersion() + "; "
            + System.getProperty("os.name") + " " + System.getProperty("os.version") + " "
            + System.getProperty("os.arch"));

    SelectionAdapter listener = new SelectionAdapter() {
        public void widgetSelected(SelectionEvent e) {
            if (e.widget == button1) {
                ut.setContent(Arrays.asList("01", "34", "test", "test2", "123", "1test", "test2"));
            } else if (e.widget == button2) {
                ut.setContent(Arrays.asList("Str1", "Str2", "Str3"));
            } else {
                ut.setContent(Collections.emptyList());
            }
        }
    };
    button1 = new Button(shell, SWT.PUSH);
    button1.setText("Data 1");
    button1.addSelectionListener(listener);
    button2 = new Button(shell, SWT.PUSH);
    button2.setText("Data 2");
    button2.addSelectionListener(listener);
    button3 = new Button(shell, SWT.PUSH);
    button3.setText("Data 3");
    button3.addSelectionListener(listener);

    GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1);
    gd.widthHint = gd.heightHint = 320;
    ut = new UltraTable(shell, SWT.MULTI | SWT.BORDER | SWT.VIRTUAL | SWT.FULL_SELECTION);
    ut.table.setLayoutData(gd);
    shell.pack();
    shell.open();
    while (!shell.isDisposed()) {
        if (!display.readAndDispatch()) {
            display.sleep();
        }
    }
    display.dispose();
  }

  class UltraTable {
    private Table table;

    private static final String DATA_COLLECTION = "<<CC>>", DATA_LISTENER = "<<VL>>";

    public UltraTable(Composite parent, int style) {
        table = new Table(parent, style);
        table.setLinesVisible(true);
        table.setHeaderVisible(true);
        TableColumn tableColumn = new TableColumn(table, SWT.NONE);
        tableColumn.setText("Column");
        tableColumn.setWidth(64);
    }

    void setContent(Collection<?> collection) {
        if ((table.getStyle() & SWT.VIRTUAL) != 0) {
            table.setData(DATA_COLLECTION, collection);
            table.clearAll();
            table.setItemCount(collection.size());
            if (table.getData(DATA_LISTENER) == null) {
                Listener listenerSD = new Listener() {
                    public void handleEvent(Event event) {
                        Collection<?> collectionW = (Collection<?>) event.widget.getData(DATA_COLLECTION);
                        Object object = collectionW.toArray(new Object[collectionW.size()])[event.index];
                        ((TableItem) event.item).setText(0, object.toString());
                    }
                };
                table.setData(DATA_LISTENER, listenerSD);
                table.addListener(SWT.SetData, listenerSD);
            }
        }
    }
  }
  public static void main(String[] args) {
    new TableCheck();
  }
}

The SWT versions I checked is (as shown in the text in the shell):

SWT win32 3550; Windows 7 6.1 x86
SWT win32 3617; Windows 7 6.1 x86

+1  A: 

I have resolved this problem after asking the same question.

You must either remove SWT.VIRTUAL or update to the SVN build of SWT. I've posted a bug report on the SWT bug page.

Edit: your code snippet has a bug in it that is causing the ArrayIndexOutOfBoundsException. You can resolve it by changing lines containing listenerSD:

public void handleEvent(Event event) {
    Collection<?> collectionW = (Collection<?>) event.widget
            .getData(DATA_COLLECTION);
    if (collectionW.size() > event.index) {
        Object object = collectionW
                .toArray(new Object[collectionW.size()])[event.index];
        ((TableItem) event.item).setText(0, object
                .toString());
    }
}
Paul Lammertsma
Thanks for the answer. I did search before on SO, but I haven't found your question, because in my case it wasn't `StackOverflowError` and you didn't add the `windows-7` tag
True Soft
I added the tag to my question so other users can find it more easily. The bug report on the Eclipse doesn't explicitly state the `StackOverflowError` (except where I posted my stack trace), only that there are occurrences where SWT locks up. What are your symptoms exactly? Perhaps posting a minimum working example to the bug site will help the SWT developers trace the source of the problem.
Paul Lammertsma
I will make a snippet with that case, because (I think) the patch doesn't resolve the problem. The thing is that I don't have windows 7 and it's difficult to find and test the exact methods that cause that problems.
True Soft
Perhaps you can post the offending code in your question?
Paul Lammertsma
Pressing `Data 1` inserts elements into the table. Subsequently pressing either `Data 2` or `Data 3` crashes it exactly as you said: `Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0`
Paul Lammertsma
The bug seems to be in your code, however. Simply wrap the operation on `collectionW` in the following if-statement: `if (collectionW.size() > event.index)`.
Paul Lammertsma
In XP and Vista it doesn't crash. I posted a bug report and somebody suggested to place `table.clearAll()` after `setItemCount`. He said "On Windows 7, the table updates the visible items immediately when clearAll()is called". @Paul, can you please test it without the if statement and with `clearAll` after , then tell me if it works?
True Soft
@True Soft: If you swap `setItemCount()` and `clearAll()` it works fine; the exception is no longer raised in either of the two cases.
Paul Lammertsma
A: 

On Windows 7, the table updates the visible items immediately when clearAll() is called. So
table.clearAll();
must be after the line
table.setItemCount(collection.size());

True Soft