Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Standard Widget Toolkit (SWT) » Table UI artifacts with ProgressBar
Table UI artifacts with ProgressBar [message #443364] Thu, 23 September 2004 17:37
Micah Silverman is currently offline Micah SilvermanFriend
Messages: 4
Registered: July 2009
Junior Member
This is a multi-part message in MIME format.
--------------070706080409050006020101
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

Hiya folks,

I have a strange UI problem happening. I have a situation where a client
will be retrieving information from a server. I wanted to show a
progress bar as a way of giving visual feedback to users even though it
is really indeterminate in terms knowing where the application server is
at in its processing.

Being dissatisfied with a ProgressBar with the SWT.INDETERMINATE
setting, I set up my own mechanism for this. Here is how it works:

1) If you scroll to the bottom of the table and then click the down
arrow, the next page is retreived. The retrieval is done in its own
thread. While the retrieval is happening, the ProgressBar is shown.
(NOTE: Data retrieval is done in its own thread, not any UI updates in
order not to violate the single thread model)

2) When the retrieval is done, the table is filled in with the retrieved
data. The ProgressBar is updated during the loop as TableItems are added.

3) When the table is done being filled out, the ProgressBAr (sitting on
its own Shell) is disposed.

The initial retrieval works just fine. You can click and hold the thumb
and scroll to the bottom.

Clicking the down arrow causes the ProgressBar to show up and the data
in the table is properly refreshed.

Now, however, if you click and hold the thumb on the vertical scrollbar,
you get a very strange UI issue: The last column in the table kind of
dissapears and is replaced with just a gray background. As soon as you
start scrolling around with the thumb, the column reappears, but there
are still some weird UI artifacts.

Here is the strange part: This behavior only happens if you click and
hold the thumb. If you click the up arrow once, then click and hold the
thumb, no problem. If you click in between the thumb and the up arrow
(causing it to scroll one page up) and then click and hold the thumb,
again no problem.

AND, it only seems to happen when this ScrollBar thing I made is used.

So, I am attaching my source code (3 files) as well as pasting each of
them inline.

I set it up so that if you run TimeProgressBarTest without any
parameters, the ProgressBar will be used when retrieving new data. If
you supply any parameters (doesn't matter how many or how they are
named) it will use the BusyIndicator.showWhile while data is being
retrieved. The artifact problem doesn't occur in this situation.

Incidentally, I tried this with SWT versions 2.1.1, 2.1.3, and 3.0

Here is the code (needs to be in package com.MPowerIT):

TimeProgressBarTest.java:

package com.MPowerIT;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;

/**
* @author msilverman2
*/
public class TimeProgressBarTest {
public static int NUMCOLS = 40;

private Table table;
protected Shell shell;

private int pageSize = 1000;
private int page = 1;

private boolean showProgress = true;

public static void main(String[] args) {
TimeProgressBarTest window = new TimeProgressBarTest();
if (args.length > 0) {
window.showProgress = false;
}

window.open();
}

public void open() {
final Display display = Display.getDefault();
createContents();
shell.layout();
shell.open();
getGridData();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
}

protected void createContents() {
shell = new Shell();
shell.setLayout(new GridLayout());
shell.setSize(800, 300);
shell.setText("SWT Application");

table = new Table(shell, SWT.BORDER);
final GridData gridData = new GridData();
gridData.heightHint = 200;
gridData.widthHint = 700;
table.setLayoutData(gridData);
table.setLinesVisible(true);
table.setHeaderVisible(true);

for (int i=0;i<NUMCOLS;i++) {
final TableColumn tableColumn = new TableColumn(table, SWT.NONE);
tableColumn.setWidth(100);
tableColumn.setText("Column "+(i+1));
}

for (int i=0;i<pageSize;i++) {
TableItem ti = new TableItem(table,SWT.NONE);
}

final ScrollBar sb = table.getVerticalBar();
sb.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
if (sb.getSelection() == sb.getMaximum() - sb.getThumb() && e.detail
== SWT.ARROW_DOWN) {
page++;
getGridData();
}
else if (sb.getSelection() == 0 && e.detail == SWT.ARROW_UP) {
page--;
if (page < 1) {
page = 1;
}
else {
getGridData();
}
}
}
});
}

private DataRunnable setupDataRunnable() {
DataRunnable dr = new DataRunnable();
dr.setPage(page);
dr.setPageSize(pageSize);
return dr;
}

private void getGridData() {
if (showProgress) {
getGridDataWithProgress();
}
else {
getGridDataWithoutProgress();
}
}

private void getGridDataWithProgress() {
DataRunnable dr = setupDataRunnable();

Thread t = new Thread(dr);

t.start();
// Set up TimeProgressBar
TimeProgressBar tpb = new TimeProgressBar(shell,t);

// Bring up TimeProgressBar
tpb.startProgress();

// Show progress as long as XMLParser thread is alive
tpb.showProgress();

populateData(dr,tpb);
}

private void getGridDataWithoutProgress() {
DataRunnable dr = setupDataRunnable();

BusyIndicator.showWhile(shell.getDisplay(),dr);

populateData(dr,null);
}

private void populateData(DataRunnable dr,TimeProgressBar tpb) {
// Populate table
String[][] data = dr.getData();
table.setRedraw(false);
for (int i=0;i<data.length;i++) {
table.getItem(i).setText(data[i]);

// update TimeProgressBar
if (tpb != null) tpb.stepProgress();
}

// get rid of TimeProgressBar
if (tpb != null) tpb.endProgress();
table.setRedraw(true);
}
}

TimeProgressBar.java:

package com.MPowerIT;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

/**
* @author msilverman2
*/
public class TimeProgressBar {
public static final int SLEEPMILLIS = 250;
public static final int BARMAX = 60;

private Shell progressShell = null;
private ProgressBar progressBar = null;
private int progressInd = 0;
private long startTime = 0;

private Thread t = null;
private Shell parentShell = null;

public TimeProgressBar(Shell parentShell,Thread t) {
this.t = t;
this.parentShell = parentShell;
}

public void startProgress() {
progressShell = new Shell(parentShell,SWT.APPLICATION_MODAL);
progressShell.setLayout(new GridLayout());
Rectangle r = parentShell.getBounds();
Rectangle r1 = new
Rectangle(r.x+(r.width/2)-100,r.y+(r.height/2)-35,200,70);
progressShell.setBounds(r1);
Label l = new Label(progressShell,SWT.NONE);
GridData g = new GridData(GridData.CENTER);
l.setLayoutData(g);
l.setText("Retrieving Data...");
progressBar = new ProgressBar(progressShell,SWT.SMOOTH);
progressBar.setMinimum(0);
progressBar.setMaximum(BARMAX);
progressShell.open();
}

public void showProgress() {
while (t.isAlive()) {
stepProgress();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

public void stepProgress() {
long checkTime = System.currentTimeMillis();
if (checkTime - startTime > SLEEPMILLIS) {
progressBar.setSelection(progressInd++);
if (progressInd > BARMAX) {
progressInd = 0;
}
startTime = System.currentTimeMillis();
}
}

public void endProgress() {
progressShell.dispose();
progressShell = null;
}
}

DataRunnable.java:

package com.MPowerIT;

/**
* @author msilverman2
*/
public class DataRunnable implements Runnable {
private int pageSize = 1000;
private int page = 1;

String[][] data;

public void run() {
try {
Thread.sleep(10*1000);
} catch (InterruptedException e) {
;
}
data = new String[pageSize][TimeProgressBarTest.NUMCOLS];
for (int i=0;i<pageSize;i++) {
for (int j=0;j<TimeProgressBarTest.NUMCOLS;j++) {
data[i][j] = "Row: "+((page-1)*pageSize+1+i)+", Col: "+(j+1);
}
}
}

public void setPage(int page) {
this.page = page;
}

public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}

public String[][] getData() {
return data;
}
}

--------------070706080409050006020101
Content-Type: text/java;
name="TimeProgressBarTest.java"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="TimeProgressBarTest.java"

package com.MPowerIT;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;

/**
* @author msilverman2
*/
public class TimeProgressBarTest {
public static int NUMCOLS = 40;

private Table table;
protected Shell shell;

private int pageSize = 1000;
private int page = 1;

private boolean showProgress = true;

public static void main(String[] args) {
TimeProgressBarTest window = new TimeProgressBarTest();
if (args.length > 0) {
window.showProgress = false;
}

window.open();
}

public void open() {
final Display display = Display.getDefault();
createContents();
shell.layout();
shell.open();
getGridData();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
}

protected void createContents() {
shell = new Shell();
shell.setLayout(new GridLayout());
shell.setSize(800, 300);
shell.setText("SWT Application");

table = new Table(shell, SWT.BORDER);
final GridData gridData = new GridData();
gridData.heightHint = 200;
gridData.widthHint = 700;
table.setLayoutData(gridData);
table.setLinesVisible(true);
table.setHeaderVisible(true);

for (int i=0;i<NUMCOLS;i++) {
final TableColumn tableColumn = new TableColumn(table, SWT.NONE);
tableColumn.setWidth(100);
tableColumn.setText("Column "+(i+1));
}

for (int i=0;i<pageSize;i++) {
TableItem ti = new TableItem(table,SWT.NONE);
}

final ScrollBar sb = table.getVerticalBar();
sb.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
if (sb.getSelection() == sb.getMaximum() - sb.getThumb() && e.detail == SWT.ARROW_DOWN) {
page++;
getGridData();
}
else if (sb.getSelection() == 0 && e.detail == SWT.ARROW_UP) {
page--;
if (page < 1) {
page = 1;
}
else {
getGridData();
}
}
}
});
}

private DataRunnable setupDataRunnable() {
DataRunnable dr = new DataRunnable();
dr.setPage(page);
dr.setPageSize(pageSize);
return dr;
}

private void getGridData() {
if (showProgress) {
getGridDataWithProgress();
}
else {
getGridDataWithoutProgress();
}
}

private void getGridDataWithProgress() {
DataRunnable dr = setupDataRunnable();

Thread t = new Thread(dr);

t.start();
// Set up TimeProgressBar
TimeProgressBar tpb = new TimeProgressBar(shell,t);

// Bring up TimeProgressBar
tpb.startProgress();

// Show progress as long as XMLParser thread is alive
tpb.showProgress();

populateData(dr,tpb);
}

private void getGridDataWithoutProgress() {
DataRunnable dr = setupDataRunnable();

BusyIndicator.showWhile(shell.getDisplay(),dr);

populateData(dr,null);
}

private void populateData(DataRunnable dr,TimeProgressBar tpb) {
// Populate table
String[][] data = dr.getData();
table.setRedraw(false);
for (int i=0;i<data.length;i++) {
table.getItem(i).setText(data[i]);

// update TimeProgressBar
if (tpb != null) tpb.stepProgress();
}

// get rid of TimeProgressBar
if (tpb != null) tpb.endProgress();
table.setRedraw(true);
}
}

--------------070706080409050006020101
Content-Type: text/java;
name="DataRunnable.java"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="DataRunnable.java"

package com.MPowerIT;

/**
* @author msilverman2
*/
public class DataRunnable implements Runnable {
private int pageSize = 1000;
private int page = 1;

String[][] data;

public void run() {
try {
Thread.sleep(10*1000);
} catch (InterruptedException e) {
;
}
data = new String[pageSize][TimeProgressBarTest.NUMCOLS];
for (int i=0;i<pageSize;i++) {
for (int j=0;j<TimeProgressBarTest.NUMCOLS;j++) {
data[i][j] = "Row: "+((page-1)*pageSize+1+i)+", Col: "+(j+1);
}
}
}

public void setPage(int page) {
this.page = page;
}

public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}

public String[][] getData() {
return data;
}
}

--------------070706080409050006020101
Content-Type: text/java;
name="TimeProgressBar.java"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="TimeProgressBar.java"

package com.MPowerIT;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

/**
* @author msilverman2
*/
public class TimeProgressBar {
public static final int SLEEPMILLIS = 250;
public static final int BARMAX = 60;

private Shell progressShell = null;
private ProgressBar progressBar = null;
private int progressInd = 0;
private long startTime = 0;

private Thread t = null;
private Shell parentShell = null;

public TimeProgressBar(Shell parentShell,Thread t) {
this.t = t;
this.parentShell = parentShell;
}

public void startProgress() {
progressShell = new Shell(parentShell,SWT.APPLICATION_MODAL);
progressShell.setLayout(new GridLayout());
Rectangle r = parentShell.getBounds();
Rectangle r1 = new Rectangle(r.x+(r.width/2)-100,r.y+(r.height/2)-35,200,70);
progressShell.setBounds(r1);
Label l = new Label(progressShell,SWT.NONE);
GridData g = new GridData(GridData.CENTER);
l.setLayoutData(g);
l.setText("Retrieving Data...");
progressBar = new ProgressBar(progressShell,SWT.SMOOTH);
progressBar.setMinimum(0);
progressBar.setMaximum(BARMAX);
progressShell.open();
}

public void showProgress() {
while (t.isAlive()) {
stepProgress();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

public void stepProgress() {
long checkTime = System.currentTimeMillis();
if (checkTime - startTime > SLEEPMILLIS) {
progressBar.setSelection(progressInd++);
if (progressInd > BARMAX) {
progressInd = 0;
}
startTime = System.currentTimeMillis();
}
}

public void endProgress() {
progressShell.dispose();
progressShell = null;
}
}

--------------070706080409050006020101--
Previous Topic:how does a composite tell if it is visible?
Next Topic:OleEvent
Goto Forum:
  


Current Time: Thu Apr 25 17:08:55 GMT 2024

Powered by FUDForum. Page generated in 0.02842 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top