I have a list of items which I display in a grid layout. Each row have couple of image buttons. When the row count reached over 1000 I am getting org.eclipse.swt.SWTError: No more handles
exception.
I used Sleak.java
and found that there have been a number of images in the memory. Is it possible to reuse these buttons somehow?
Below is the statistics from Sleak
.
Colors: 8 Cursors: 6 Fonts: 19 Images: 1317
Code:
private void looper(List<File> dicomFiles, int start, int stop, int toShow){
for(int i=start; i<stop; i++){
File dicomFile = dicomFiles.get(i);
Composite rowComposite = new Composite(dicomFilecomposite, SWT.None);
rowComposite.setLayout(configRowCompositeLayout());
rowComposite.setLayoutData(getRowCompositeGridData());
rowComposite.setBackground(Colors.CELL_BG_COLOR);
Label dicomFIleLabel = new Label(rowComposite, SWT.NULL);
dicomFIleLabel.setLayoutData(new GridData());
dicomFIleLabel.setText(dicomFile.getName());
dicomFIleLabel.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
dicomFIleLabel.setFont(FONT_10);
Label fileSizeLabel = new Label(rowComposite, SWT.None);
fileSizeLabel.setText((dicomFile.length() / 1000)+" "+Const.KB_LABEL);
fileSizeLabel.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
Composite progBarLabelComposite = new Composite(rowComposite, SWT.None);
progBarLabelComposite.setLayout(new RowLayout());
ProgressBar progressBar = new ProgressBar(progBarLabelComposite, SWT.HORIZONTAL | SWT.SMOOTH);
progressBar.setVisible(true);
Label progressPercentageLabel = new Label(progBarLabelComposite, SWT.None);
progressPercentageLabel.setText(Const.INITIAL_PROGBAR_PERCENTAGE);
progressPercentageLabel.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
Composite btnWrapperComposite = new Composite(rowComposite, SWT.None);
btnWrapperComposite.setLayout(configZeroMarginLayout(true));
GridData btnWrapperCompositeGridData = new GridData();
btnWrapperCompositeGridData.horizontalAlignment = GridData.END;
btnWrapperCompositeGridData.grabExcessHorizontalSpace = true;
btnWrapperComposite.setLayoutData(btnWrapperCompositeGridData);
Composite uploadCancelBtnComposite = new Composite(btnWrapperComposite, SWT.None);
uploadCancelBtnComposite.setLayout(new RowLayout());
Composite uploadBtnComposite = new Composite(uploadCancelBtnComposite, SWT.NULL);
uploadBtnComposite.setLayout(configZeroMarginLayout(false));
ImageButton uploadButton = new ImageButton(uploadBtnComposite, SWT.PUSH);
uploadButton.setImage(Const.UPLOAD_BTN_BG_IMAGE);
uploadButton.setListener(MainShell.this);
uploadButton.setCursor(HAND_CURSOR);
uploadButton.setToolTipText(Const.UPLOAD_LABEL);
ImageButton cancelButton = new ImageButton(uploadCancelBtnComposite, SWT.PUSH);
cancelButton.setImage(Const.DELETE_BTN_BG_IMAGE);
cancelButton.setListener(MainShell.this);
cancelButton.setCursor(HAND_CURSOR);
cancelButton.setToolTipText(Const.DELETE_LABEL);
FileUploadData fileUploadData = loadFileUploadData(progBarLabelComposite, dicomFilecomposite, dicomFile, progressBar, progressPercentageLabel);
uploadButton.setData(fileUploadData);
uploadButton.setData(IMG_BTN_DATA_KEY, Const.UPLOAD_LABEL);
uploadButtons.add(uploadButton);
fileUploadDatas.add(fileUploadData);
cancelButton.setData(fileUploadData);
cancelButton.setData(IMG_BTN_DATA_KEY, Const.DELETE_LABEL);
loadSeparatorField(rowComposite);
}
}
In these two lines are where the issue is occurring in my understanding.
ImageButton uploadButton = new ImageButton(uploadBtnComposite, SWT.PUSH);
ImageButton cancelButton = new ImageButton(uploadCancelBtnComposite, SWT.PUSH);
In SWT you can not reuse buttons however you can reuse images. Write a singleton class say ImageCache and cache all the images in it and fetch images from this class wherever required. I faced the same problem and solved it this way. Also create your custom dispose methods in your UI components and dispose UI components yourself because SWT does not disposes them properly and resources leak in most cases.
SWT best practice says that "all resources must be cached" so your fonts, colors, images must be cached and used properly in respective ItemRenderers.