How to make SWT Table in CheckboxTableViewer scrollable? - java

I couldn't find any answers for this special case (using CheckboxTableViewer), so I hope it's not a duplicate.
I have the following createPartControl() in an Eclipse view (3.x).
I'm trying to display two buttons and a checkable table in a GridLayout, as below
-------------------
| Button | Button |
-------------------
| Table |
-------------------
Nothing spectacular. Everything is displayed fine so far. My table is embedded within a CheckboxTableViewer, has a single column and sometimes the content (String) is longer than the column width. So I'm trying to make the Table (got via viewer.getTable(), not explicitly constructed!) scrollable to make all content available. This doesn't work and I cannot understand why.
I have played around with SWT style bits (SWT.H_SCROLL, SWT.V_SCROLL), I've tried a ScrollableComponent, but to no avail. I couldn't get the ScrolledComponent to work because I'm not constructing my table explicitly, and thus couldn't setContents() properly.
Below is the gist of my createPartControl().
public void createPartControl(Composite parent) {
parent.setLayout(new GridLayout(2, false));
addSelectionButtons(parent); // Works
myTableViewer = CheckboxTableViewer.newCheckList(parent, SWT.BORDER);
myTableViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
Table myTable = (Table) myTableViewer.getControl();
TableLayout tableLayout = new TableLayout();
tableLayout.addColumnData(new ColumnWeightData(100, 50, true));
myTable.setLayout(tableLayout);
myTableViewer.setContentProvider(new MyContentProvider());
TableViewerColumn viewerCol = new TableViewerColumn(myTableViewer, SWT.LEFT);
TableColumn col = viewerCol.getColumn();
col.setText("My column");
viewerCol.setLabelProvider(new ColumnLabelProvider() {
#Override
public String getText(Object element) {
return text; // Dummy var
}
});
myTableViewer.setInput(getInput()); // Gets model
myTableViewer.getTable().setHeaderVisible(true);
myTableViewer.getTable().setLinesVisible(true);
}
I know this is borderline "give me teh codez", but I really cannot find the issue with this setup.

I've managed to solve this issue by going back to square one and re-implementing in the most generic fashion I could find documented. I.e.:
I've added a proper LabelProvider (and got rid of the ColumnLabelProvider),
set a simple GridData layout data object to the table (and otherwise haven't messed with it),
and simplified the TableColumn section a lot (despite having only one column in the table, I still need to declare a TableColumn to be able to set a column heading). Note: The TableColumn must be pack()ed, otherwise the content doesn't show. From the TableColumn API: "Causes the receiver to be resized to its preferred size."
Simple and working.
public void createPartControl(Composite parent) {
parent.setLayout(new GridLayout(1, true));
addSelectionButtons(parent); // Adds select/deselect all buttons
myTableViewer = CheckboxTableViewer.newCheckList(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
myTableViewer.getTable().setLayoutData(new GridData(GridData.FILL_BOTH));
myTableViewer.setContentProvider(new MyContentProvider());
myTableViewer.setLabelProvider(new MyLabelProvider());
myTableViewer.setInput(getInput()); // Gets model
TableColumn column = new TableColumn(myTableViewer.getTable(), SWT.FILL);
column.setText("My column");
column.pack();
myTableViewer.getTable().setHeaderVisible(true);
myTableViewer.getTable().setLinesVisible(true);
}

Related

Keeping SWT Text box size after setting text

When I use setText() on one or both Text fields, it resizes the field to the length of the text. How do I prevent that from happening?
inner = new Composite(middle, SWT.NONE);
inner.setLayout(new GridLayout(5, false));
chkbxBtn = new Button(inner, SWT.CHECK);
chkbxBtn.setText("Check box button: ");
chkbxBtn.setSelection(false);
new Label(inner, SWT.NONE).setText("Text field 1: ");
startCol = new Text(inner, SWT.BORDER | SWT.NONE);
new Label(inner, SWT.NONE).setText("Text field 2: ");
endCol = new Text(inner, SWT.BORDER | SWT.NONE);
To clarify, SWT does not re-layout after changing the text (or any other property) of a Text control (or controls in general). It is your code or a resize event that causes the re-layout.
If you want a control to have a pre-set size, and its parent uses a GridLayout, you can set GridData with a widthHint like this:
GridData gridData = new GridData();
gridData.widthHint = ...
text.setLayoutData( gridData );
However, it is usually a bad idea trying to control the size of widgets. Thus make sure that your layout strategy aligns with best practices of UI design.
There are situations when changes to the text trigger a component re-layout. For example, show an error message as a text validation result (I found it in SWT forms).
Setting the width hint in the GridData for the text component fixes this. Width hint can be set to 0 or the minimum required size.
GridDataFactory.swtDefaults()//
.grab(true, false)//
.hint(0, SWT.DEFAULT)// width hint prevents text from expanding to full line
.align(SWT.FILL, SWT.CENTER)//
.applyTo(text);

how to split the screen to 3 parts in SWT?

I am new in SWT and java
I really need an help here.
I need to build Eclipse plug-in that should open a dialog when you press on button.
The dialog should look like
label 1 textBox1 label 2 textBox 2
label 3 textBox13 label 4 textBox 4
could be alot of them -> should be with scroller
---------------------------------------------------
output ( should be textbox)
-----------------------------------------------------
messages ( should be textbox)
It could be alot of labels and textbox, How I can add them to control that could hold alot of them ? ( it should be with scroller )
How I can split the screen to 3 parts in SWT or fjace ? and how I can control on the size for example that the first part ( label textbox) will be 60% and the output will be 30% and the messages 10% ?
Maybe you could help me with an example for this ?
This is asking for far too much code - you are supposed to show us what you have tried!
Some hints:
Use org.eclipse.jface.dialog.Dialog for the dialog, you could also use org.eclipse.jface.dialog.TitleAreaDialog which has an area for error messages.
To split an area by percentages use org.eclipse.swt.custom.SashForm.
To get multiple items on a line use org.eclipse.swt.layout.GridLayout specifying the number of columns.
To get a scrolled area use org.eclipse.swt.custom.ScrolledComposite
So something like:
#Override
protected Control createDialogArea(final Composite parent)
{
Composite body = (Composite)super.createDialogArea(parent);
// Vertical sash
SashForm sashForm = new SashForm(body, SWT.VERTICAL);
sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
// First part, scrollable
ScrolledComposite scrolledComp = new ScrolledComposite(sashForm, SWT.V_SCROLL);
Composite comp1 = new Composite(scrolledComp, SWT.NONE);
comp1.setLayout(new GridLayout());
// TODO: add controls to comp1
// Set scroll size - may need to adjust this
Point size = comp1.computeSize(SWT.DEFAULT, SWT.DEFAULT);
scrolledComp.setMinHeight(size.y);
scrolledComp.setMinWidth(size.x);
scrolledComp.setExpandVertical(true);
scrolledComp.setExpandHorizontal(true);
scrolledComp.setContent(comp1);
// Second part
Composite comp2 = new Composite(sashForm, SWT.NONE);
comp2.setLayout(new GridLayout());
// TODO: add controls to comp2
// Third part
Composite comp3 = new Composite(sashForm, SWT.NONE);
comp3.setLayout(new GridLayout());
// TODO: add controls to comp3
// Set the sash weighting (must be after controls are created)
sashForm.setWeights(new int [] {60, 30, 10});
return body;
}

How to disable horizontal scroll bars in the swt table?

To disable vertical scroll bar i used the following syntax
table.getHorizontalBar().setEnabled(false);
But it is not working. It is ruining my application ui. How can i disable it?
Use option SWT.NO_SCROLL and SWT.V_SCROLL while constructing the table as following:
new Table (shell, SWT.NO_SCROLL | SWT.V_SCROLL);
You can't prevent the Table from showing its scrollbars if it wants to. However, if you give the table the space it requires, it should not have to display any scrollbars.
Note:
You can simply use SWT.NO_SCROLL in the constructor but if you want to update it later it won't be possible.
ScrollBar / Table position synchronization in Java SWT turorial
Probably, if you you want to disable a scrollbar, it means you want to synchronize the content with something else. Here is example how to do it with two tables, where content of main table called tableExcel is mirrored in extra table called tableRow (please, be aware the code may not be perfect, because I am beginner):
*Note: the code is not complete & shows only key things (beginners, please use Window Builder and then edit/add code):
1) As ankur.trapasiya mentioned, do this:
tableRow = new Table(sashFormExcel, SWT.BORDER | SWT.VIRTUAL | SWT.NO_SCROLL);
2) And (SWT.VIRTUAL will be required to do the workaround, and to load tables fast, it will load what you see & where you scroll)
tableExcel = new Table(sashFormExcel, SWT.BORDER | SWT.VIRTUAL);
3) Because I used sash-form for better navigation, insert this above point 1:
SashForm sashFormExcel = new SashForm(sashForm_Main, SWT.NONE);
4) Then implement this (after point 3):
synchronizer synchronize = new synchronizer(tableRow, tableExcel); tableExcel.getVerticalBar().addSelectionListener(synchronize);
5) Add this class (will synchronize the tables content position):
class synchronizer implements SelectionListener
{
Table t1, t2;
public synchronizer(Table tableRow, Table tableMain)
{
t1 = tableRow;
t2 = tableMain;
}
#Override
public void widgetSelected(SelectionEvent e) {
t1.setTopIndex(t2.getTopIndex());
}
#Override
public void widgetDefaultSelected(SelectionEvent e) {
// TODO Auto-generated method stub
}
}
6) And after point 2, add this (it will make to load main table fast, and will also synchronize your table where scroll bar is disabled):
tableExcel.addListener( SWT.SetData, new Listener() {
public void handleEvent( Event event ) {
TableItem item = (TableItem) event.item;
int index = event.index;
int page = index / PAGE_SIZE;
int start = page * PAGE_SIZE;
int end = start + PAGE_SIZE;
end = Math.min (end, virtTableExcel.size());
for (int i = start; i < end; i++) {
item = tableExcel.getItem (i);
item.setText (virtTableExcel.get(i));
tableRow.getItem(i).setText(Integer.toString(i));
}
}
});
And on top of code, add this:
private static Table tableExcel;
ArrayList<String[]> virtTableExcel = new ArrayList<String[]>();
final int PAGE_SIZE = 64;
private Table tableRow;
As it is mentioned in point 7, you take data from array list virtTableExcel, but to trigger point 6, use this (somewhere in code, after you generated virtTableExcel with data), where rowMax is integer which is equal to virtTableExcel.size(); :tableExcel.setItemCount(rowMax);
tableRow.setItemCount(rowMax);
Please, don't blame me for code, I used it from my application. But, all these bits might be useful for other beginners.
What work for me:
When declaring the TableViewer I do this:
this.viewer.getTable().getHorizontalBar().setVisible(false);
this.viewer.getTable().pack();
this.viewer.getTable().getParent().layout();
this.viewer.getTable().getParent().getParent().layout();
and when i am changing the viewer input i also call the three last lines.
I got this solution from: https://bugs.eclipse.org/bugs/show_bug.cgi?id=304128
Try
table.getHorizontalBar().setVisible(false);
Is't simple:
leftTable.getVerticalBar().addListener(SWT.Selection, event -> {
rightTableViewer.getTable().setTopIndex(leftTableViewer.getTable().getTopIndex());
});
and vice versa.

Unable to draw Composite in OwnerDrawLabelProvider

I have a TableViewer widget with a single column, where each row in the table's contents is a Composite with a number of child widgets. The column has a label provider that is a subclass of OwnerDrawLabelProvider. The label provider is supposed to render the Composite children in the table cell, but when paint() is called, nothing is rendered.
I have found a number of examples on how to draw plain or styled text items, or primitives using the GC in the Event object passed in, but nothing on drawing the contents of a Composite in the cell's area.
Is this possible, and if so, what am I doing wrong?
Here is the code to create the table:
viewer = new TableViewer(container, SWT.NONE);
final Table table = viewer.getTable();
TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.LEFT);
TableColumn tableColumn = viewerColumn.getColumn();
tableColumn.setText(Messages.getString("column.header.name"));
tableColumn.setResizable(true);
tableColumn.setMoveable(false);
tableColumn.setWidth(500);
viewerColumn.setLabelProvider(new CompositeLabelProvider());
Here are the measure and paint methods for the custom label provider, CompositeLabelProvider:
#Override
protected void measure(Event event, Object element) {
CompositeTableItem row = rowMap.get(element);
Composite contents = row.getContents(viewer.getTable().getParent());
Point size = contents.computeSize(SWT.DEFAULT, SWT.DEFAULT);
event.setBounds(new Rectangle(event.x, event.y, size.x, size.y));
}
#Override
protected void paint(Event event, Object element) {
CompositeTableItem row = rowMap.get(element);
Composite contents = row.getContents(viewer.getTable().getParent());
contents.redraw(event.getBounds().x, event.getBounds().y, event.getBounds().width, event.getBounds().height, true);
contents.update();
}
I think OwnerDrawLabelProvider is meant to be used if you want to draw your own component using the GC. If you only want render a normal SWT widget in a table you should probably use TableEditor and #setEditor(Control) to set the control you want to show in the table cell.

How to have text fields fill 100% horizontally

If I have a text field with SWT, how can I get the field to fill to 100% or some specified width.
For example, this text field will only reach for so much horizontally.
public class Tmp {
public static void main (String [] args) {
Display display = new Display ();
Shell shell = new Shell (display);
GridLayout gridLayout = new GridLayout ();
shell.setLayout (gridLayout);
Button button0 = new Button(shell, SWT.PUSH);
button0.setText ("button0");
Text text = new Text(shell, SWT.BORDER | SWT.FILL);
text.setText ("Text Field");
shell.setSize(500, 400);
//shell.pack();
shell.open();
while (!shell.isDisposed ()) {
if (!display.readAndDispatch ())
display.sleep ();
}
display.dispose ();
}
}
Make something like this:
Text text = new Text(shell, SWT.BORDER);
text.setText ("Text Field");
text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER));
/: Since this is the accepted answer I remove the errors. Thx for correcting me.
Positioning of elements in a Component depends on the Layout object that you are using. In the sample provided, you are using a GridLayout. That means, that you need to provide a specific LayoutData object to indicate how you want your component displayed. In the case of GridLayout, the object is GridData.
To achieve what you want, you must create a GridData object that grabs all horizontal space and fills it:
// Fills available horizontal and vertical space, grabs horizontal space,grab
// does not grab vertical space
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false);
text.setLayoutData(gd);
Alternative ways include using a different LayoutManager, such as FormLayout. This layout uses a FormData object that also allows you to specify how the component will be placed on the screen.
You can also read this article on Layouts to understand how Layouts work.
As a side note, the constructor new GridData(int style) is marked as "not recommended" in the documentation. The explicit constructor shown in this example is preferred instead.

Categories

Resources