I wish to use org.eclipse.swt.widgets.List just to present some data. User should not be allowed to select any item.
I could just:
List list = new List(this, SWT.V_SCROLL);
list.setEnabled(false);
But then I will loose scrolling feature. How can I just make list items unselectable?
Another alternative is to use a Table instead of List and disable selection painting like this:
table.addListener(SWT.EraseItem, new Listener() {
#Override
public void handleEvent(Event event) {
event.detail &= ~SWT.SELECTED;
event.detail &= ~SWT.HOT;
}
});
You could try to clear selection each time user selects an item. The selection will be visible for a short time interval, though.
list.addListener(SWT.Selection, new Listener() {
#Override
public void handleEvent(Event event) {
list.setSelection(new String[0]);
}
});
If you don't like my other answer with clearing selection, you could try to keep the list disabled, but inside a ScrolledComposite. It will look disabled, but scrolling will work. Here is a snippet:
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
final ScrolledComposite scrolledComposite = new ScrolledComposite(shell, SWT.H_SCROLL | SWT.V_SCROLL);
scrolledComposite.setExpandHorizontal(true);
scrolledComposite.setExpandVertical(true);
scrolledComposite.setBackground(display.getSystemColor(SWT.COLOR_CYAN));
final List list = new List(scrolledComposite, SWT.NONE);
list.setEnabled(false);
scrolledComposite.setContent(list);
scrolledComposite.addListener(SWT.Resize, new Listener() {
#Override
public void handleEvent(Event event) {
final Point size = list.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
scrolledComposite.setMinSize(size);
}
});
for (int i = 0; i < 1000; i++) {
list.add(Integer.toString(i));
}
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
Arrow keys and page up/down down do not work, so you will have to register key listeners and implement scrolling with keyboard.
Related
I use a SWT Text field and I want to prevent it from being de-focused while it has no Text entered or just white spaces. Also I want to inform the User if thatĀ“s the case.
My current solution is that I check it inside a FocusListenerĀ“s focusLostMethod.
But the focusLost Event is sended twice so the User will get informed twice and thats not what I want. So my Questions are:
Is it normal that the focusLostEvent ist sended multiple times? Or is there something wrong in my application?
If it is normal: Is there a possibility to ensure the User gets informed just once?
This code here works just fine. SWT.FocusOut is only fired one:
public static void main(String[] args)
{
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("StackOverflow");
shell.setLayout(new FillLayout());
final Text text = new Text(shell, SWT.BORDER);
text.addListener(SWT.FocusOut, new Listener()
{
#Override
public void handleEvent(Event event)
{
if (text.getText().trim().length() < 1)
{
Display.getDefault().asyncExec(new Runnable()
{
#Override
public void run()
{
System.out.println("Please enter something!");
if (text != null && !text.isDisposed())
{
text.setFocus();
text.forceFocus();
}
}
});
}
else
{
System.out.println("Nothing to see here, move along.");
}
}
});
new Text(shell, SWT.BORDER);
shell.pack();
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
{
display.sleep();
}
}
display.dispose();
}
I Have a GridLayout filled with Composites in a random order. Now I'm sorting the Composites that are filling the GridLayout in a List/Collection and want to order them like the sort result from my List/Collection. I tried to do it by allocating them again to their parent so they are in the right order, but for some reason nothing happened. Then I tried to cache them in a Composite you don't see and then bring them back to the parent with the same method as in the first attempt. No change at all. Anyone has a pointer? I'm ordering by date, just in case /so want to know.
Thats how my grid looks like, now I want to order them like in my arrayList();
The methods you are looking for are Control#moveAbove(Control control) and Control#moveBelow(Control control) to reorder the items:
private static List<Label> labels = new ArrayList<Label>();
private static List<Color> colors = new ArrayList<Color>();
public static void main(String[] args)
{
Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("Stackoverflow");
shell.setLayout(new RowLayout(SWT.VERTICAL));
colors.add(display.getSystemColor(SWT.COLOR_BLUE));
colors.add(display.getSystemColor(SWT.COLOR_CYAN));
colors.add(display.getSystemColor(SWT.COLOR_GREEN));
colors.add(display.getSystemColor(SWT.COLOR_YELLOW));
colors.add(display.getSystemColor(SWT.COLOR_RED));
for (int i = 0; i < 5; i++)
{
Label label = new Label(shell, SWT.BORDER);
label.setText("Button " + i);
label.setBackground(colors.get(i));
labels.add(label);
}
Button sortButton = new Button(shell, SWT.TOGGLE);
sortButton.setText("Sort");
sortButton.addListener(SWT.Selection, new Listener()
{
#Override
public void handleEvent(Event e)
{
Button source = (Button) e.widget;
final boolean asc = source.getSelection();
Label oldFirst = labels.get(0);
Collections.sort(labels, new Comparator<Label>()
{
#Override
public int compare(Label o1, Label o2)
{
int result = o1.getText().compareTo(o2.getText());
if (asc)
result = -result;
return result;
}
});
Label label = labels.get(0);
label.moveAbove(oldFirst);
for (int i = 1; i < labels.size(); i++)
{
labels.get(i).moveBelow(labels.get(i - 1));
}
shell.layout();
}
});
shell.pack();
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
After starting:
After pressing the button:
I found the solution. You have to call child.moveAbove(otherChild) or .moveBelow() When you are done with the reordering just call on the parent Composite parent.layout()
I'm trying to do look alike chess-board in SWT, JAVA.
I tried to do array of buttons, but the color of a button can't be changed (after a long research I have done!).
So I did an array of labels that I can change their color, but now I cannot handle them in one listener, and I don't think that 64 copy-paste listeners are the right thing to do.
However, I found the setActionCommand is not for labels at all.
Do you have any suggestions what can I do to fix that out?
Thanks.
You can use the same Listener for multiple Labels:
public static void main(String[] args)
{
final Display display = new Display();
Shell shell = new Shell(display);
GridLayout layout = new GridLayout(8, true);
layout.horizontalSpacing = 0;
layout.verticalSpacing = 0;
shell.setLayout(layout);
shell.setText("Chess");
/* Define listener once */
Listener listener = new Listener()
{
#Override
public void handleEvent(Event event)
{
/* event.widget is the source of the event */
if(event.widget instanceof Label)
{
System.out.println(event.widget.getData());
}
}
};
for(int i = 0; i < 64; i++)
{
Label label = new Label(shell, SWT.CENTER);
label.setText(i + "");
label.setData(i);
/* Use listener here */
label.addListener(SWT.MouseUp, listener);
label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
Color background = ((i + (i/8))%2 == 0) ? display.getSystemColor(SWT.COLOR_BLACK) : display.getSystemColor(SWT.COLOR_WHITE);
Color foreground = ((i + (i/8))%2 == 0) ? display.getSystemColor(SWT.COLOR_WHITE) : display.getSystemColor(SWT.COLOR_BLACK);
label.setBackground(background);
label.setForeground(foreground);
}
shell.pack();
shell.setSize(200, 200);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
It will print out the Labels data on click.
Looks like this:
When creating a JFace TreeViewer, one can use the SWT constants to set single or multiple selections allowed for the user to the tree items (SWT.SINGLE or SWT.MULTI).
Can anyone help me please as I want a tree that its items can not be selected at all? I want it as for preview purpose and user should not be able to select an item there.
Many thanks in advance,
I don't really understand why do you want to suppress the selection, but this is how it may work:
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
#Override
public void selectionChanged(final SelectionChangedEvent event) {
if (!event.getSelection().isEmpty()) {
v.setSelection(StructuredSelection.EMPTY);
}
}
});
In addition to this I would make sure that the viewer:
is not registered as the selection provider in the part's site
accepts no other ISelectionChangedListeners
Another easy solution is to put the viewer into a separate composite and set the enabled state of it to false:
Composite c = new Composite(parent, SWT.NONE);
TreeViewer viewer = new TreeViewer(c, SWT.Border);
c.setEnabled(false);
Your viewer will now NOT appear grey (setting viewer.setEnabled will make it appear grey) but the user is unable to select anything in the viewer. Updating and refreshing the viewer works just fine. But keep in mind that no SelectionEvents will be thrown when clicking into the viewer now.
Could you try this?
Basically adding filter on selection events. In case of Viewer implementation,
org.eclipse.jface.util.OpenStrategy class is responsible for firing selection events what Viewer's understand. If filter is added on SWT selection event, Viewer will never know about underlying selection.
public class SWTSimpleTree {
Display display = new Display();
Shell shell = new Shell(display);
Tree tree;
private Listener filter = new Listener() {
#Override
public void handleEvent(Event event) {
event.type=SWT.None;
event.doit=false;
event.item = null;
tree.deselectAll();
}
};
public SWTSimpleTree() {
shell.setLayout(new GridLayout());
tree = new Tree(shell, SWT.BORDER);
tree.setLayoutData(new GridData(GridData.FILL_BOTH));
TreeItem item = new TreeItem(tree, SWT.NULL);
item.setText("ITEM");
TreeItem item2 = new TreeItem(item, SWT.NULL);
item2.setText("ITEM2");
TreeItem item3 = new TreeItem(item2, SWT.NULL);
item3.setText("ITEM3");
System.out.println("item: " + item.getParent() + ", " + item.getParentItem());
System.out.println("item2: " + item2.getParent() + ", " + item2.getParentItem());
System.out.println(tree.getItemCount());
System.out.println(tree.getItems().length);
tree.getDisplay().addFilter(SWT.Selection, filter);
tree.getDisplay().addFilter(SWT.DefaultSelection, filter);
shell.setSize(300, 200);
shell.open();
//textUser.forceFocus();
// Set up the event loop.
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
// If no more entries in event queue
display.sleep();
}
}
display.dispose();
}
private void init() {
}
public static void main(String[] args) {
new SWTSimpleTree();
}
}
Group group = new Group(parent, SWT.NONE);
StyledText comment = new StyledText(group, SWT.BORDER_DASH);
This creates a group with a text area inside.
How can I later delete the text (remove it from the screen so that I can replace it with something else)?
Use Widget.dispose.
public class DisposeDemo {
private static void addControls(final Shell shell) {
shell.setLayout(new GridLayout());
Button button = new Button(shell, SWT.PUSH);
button.setText("Click to remove all controls from shell");
button.addSelectionListener(new SelectionListener() {
#Override public void widgetDefaultSelected(SelectionEvent event) {}
#Override public void widgetSelected(SelectionEvent event) {
for (Control kid : shell.getChildren()) {
kid.dispose();
}
}
});
for (int i = 0; i < 5; i++) {
Label label = new Label(shell, SWT.NONE);
label.setText("Hello, World!");
}
shell.pack();
}
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
addControls(shell);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
}
Another option is to use a StackLayout to switch between underlying controls. This prevents you from running into a "widget is disposed" error.
You have to either call comment.changeParent(newParent) or comment.setVisible(false) to remove/hide it from the Group. I am unsure if comment.changeParent(null) would work but I would give that a try.
We do it this way because SWT uses the Composite Pattern.
group.getChildren()[0].dispose() will remove the first child. You need to find a way to identify the precise child you want to delete. It could be comparing the id. You can do that by using the setData / getData on that control:
For example:
StyledText comment = new StyledText(group, SWT.BORDER_DASH);
comment.setData("ID","commentEditBox");
and then:
for (Control ctrl : group.getChildren()) {
if (control.getData("ID").equals("commentEditBox")) {
ctrl.dispose();
break;
}
}