placing a widget in the background in SWT - java

I'm trying to display a progress bar (using SWT's ProgressBar class). However, the bar isn't very visible due to my window's background. Therefore, I'm trying to put a white rectangle (using GC.fillRoundedRectangle()) behind the progress bar. I can't find a way to display the progress bar on top of the rectangle. How can I achieve "layering" in SWT?
Thanks!
EDIT: I tried #greg-449's suggestion, but all I got was a blank window-am I implementing this wrong?
public static void main(String [] args){
Display d = new Display();
Shell parent = new Shell(d);
parent.setSize(500, 500);
parent.open();
makeBar(parent);
while (!parent.isDisposed()) {
if (!d.readAndDispatch()) {
d.sleep();
}
}
}
private static void makeBar(Shell parent) {
Composite body = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.marginHeight = 20;
layout.marginWidth = 20;
body.setLayout(layout);
body.addListener(SWT.Paint, event ->
{
Rectangle rect = body.getClientArea();
event.gc.setBackground(body.getDisplay().getSystemColor(SWT.COLOR_WHITE));
event.gc.fillRoundRectangle(rect.x, rect.y, rect.width, rect.height, 20, 20);
});
ProgressBar bar = new ProgressBar(body, SWT.HORIZONTAL);
bar.setMaximum(100);
bar.setSelection(40);
}
This is what I see when I run this code:
Output of code

You could just use a Composite which you paint with the ProgressBar as a child.
Something like:
Composite body = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.marginHeight = 20;
layout.marginWidth = 20;
body.setLayout(layout);
body.addListener(SWT.Paint, event ->
{
Rectangle rect = body.getClientArea();
event.gc.setBackground(body.getDisplay().getSystemColor(SWT.COLOR_WHITE));
event.gc.fillRoundRectangle(rect.x, rect.y, rect.width, rect.height, 20, 20);
});
ProgressBar bar = new ProgressBar(body, SWT.HORIZONTAL);
bar.setMaximum(100);
bar.setSelection(40);

Related

How can I show Scroll on my UI, with JAVA, SWT?

I'm trying to put a ScrolledComposite on my UI with SWT.
but now it only shows blank area or something wrong.
The area to show ScrolledComposite is blank without the code,
"optionCompositeAtLeft.setSize(optionCompositeAtLeft.computeSize(SWT.DEFAULT, SWT.DEFAULT)); "
This is the pic of screenshot.
The optionTab should have the buttons with Scroll....
and with the code, it shows scroll, but too long height and narrow width.
Somehow, the upper is gone, but come back when I extend the size of window with scroll disappearing.
I set the color of background red to make it easier to see for you.
Can anyone help me make "optionCompositeAtLeft" filled in ScrolledComposite?
I want the left area of Option tab to be filled with a red background from "optionCompositeAtLef".
Below is my code.
private BomCloneDialog dialog = null;
private TabFolder tabFolder = null;
private TabItem tabOption = null;
public CreateOptionTab(TabFolder tabFolder, TabItem tabOption) {
this.tabFolder = tabFolder;
this.tabOption = tabOption;
}
public void createOptionTabUI() {
GridData gdWithFillBoth = new GridData(GridData.FILL_BOTH);
Composite optionComposite = new Composite(tabFolder, SWT.NONE);
optionComposite.setLayout(new GridLayout(2, true));
tabOption.setControl(optionComposite);
ScrolledComposite scrolledCompositeForOption = new ScrolledComposite(optionComposite,SWT.V_SCROLL | SWT.BORDER);
scrolledCompositeForOption.setLayoutData(gdWithFillBoth);
Composite optionCompositeAtLeft = new Composite(scrolledCompositeForOption, SWT.BORDER);
scrolledCompositeForOption.setContent(optionCompositeAtLeft);
optionCompositeAtLeft.setLayout(new GridLayout(1, true));
optionCompositeAtLeft.setLayoutData(gdWithFillBoth);
optionCompositeAtLeft.setBackground(new Color(Display.getCurrent(), 255,0,0));
Button b [] = new Button[30];
for(int a=0; a<30; a++){
b[a] = new Button(optionCompositeAtLeft, SWT.PUSH);
b[a].setText("button"+a);
}
**optionCompositeAtLeft.setSize(optionCompositeAtLeft.computeSize(SWT.DEFAULT, SWT.DEFAULT));**
Composite optionButtonComposite = new Composite(optionComposite, SWT.BORDER);
optionButtonComposite.setLayout(new GridLayout(1, true));
optionButtonComposite.setLayoutData(gdWithFillBoth);
Button optionSaveButton = new Button(optionButtonComposite, SWT.NONE);
optionSaveButton.setLayoutData(gdWithFillBoth);
optionSaveButton.setText("Save");
Button optionAddButton = new Button(optionButtonComposite, SWT.NONE);
optionAddButton.setLayoutData(gdWithFillBoth);
optionAddButton.setText("Add");
}
You need to configure ScrolledComposite to resize the content:
scrolledCompositeForOption.setExpandHorizontal(true);
scrolledCompositeForOption.setExpandVertical(true);

Eclipse canvas paintListener never called

I'm creating an editor extension to eclipse, and a for a part of the editor I need to draw simple graphical parts. From what I understand I should be able to use the eclipse widget Canvas for this. But the paintControl method of the PaintListener added to the canvas is never called. I'm assuming I'm missing some crucial simple part but I can't find it. Here is the code that creates, adds and calls redraw on the canvas.
void createGraphicPage() {
Composite composite = new Composite(getContainer(), SWT.NONE);
drawWidget = new Canvas(composite, SWT.NONE);
FormLayout layout = new FormLayout();
drawWidget.setLayout(layout);
drawWidget.addPaintListener(new PaintListener() {
#Override
public void paintControl(PaintEvent e) {
System.out.println("inDrawWidget");
Rectangle r = drawWidget.getClientArea();
e.gc.drawOval(0, 0, r.width, r.height);
}
});
drawWidget.redraw();
int index = addPage(composite);
setPageText(index, "Graphics Editor");
}
You need to set a layout on each Composite which contains controls, and usually set layout data on the controls. So:
Composite composite = new Composite(getContainer(), SWT.NONE);
composite.setLayout(new GridLayout());
Canvas drawWidget = new Canvas(composite, SWT.NONE);
drawWidget.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
drawWidget.addPaintListener(new PaintListener() {
#Override
public void paintControl(final PaintEvent e) {
System.out.println("inDrawWidget");
final Rectangle r = drawWidget.getClientArea();
e.gc.drawOval(0, 0, r.width, r.height);
}
});
I have added a GridLayout to the Composite and GridData layout data to the Canvas. The GridData makes the Canvas use all available space.

print swt component even if hidden by scrollbar

I try to print a swt TreeViewer to png file. With:
Tree tree = treeViewer.getTree();
Image image = new Image(display, tree.getSize().x, tree.getParent().getSize().y);
GC gc = new GC(image);
System.out.println(new File(pathToSave).getAbsolutePath());
tree.print(gc);
ImageLoader loader = new ImageLoader();
loader.data = new ImageData[] { image.getImageData() };
loader.save(pathToSave, SWT.IMAGE_PNG);
gc.dispose();
image.dispose();
the png contains only the visible part of the tree. The tree has a scrollbar because it contains more elements than fit on the form.
I would like to print the tree with all elements visible and without scrollbar. Any ideas?
On swing components i could use .paintall().. swt components don't seem to know that.
First, the size of the image should have the size the tree would have without scrolls, and not the current size. For that you should use computeSize(SWT.DEFAULT, SWT.DEFAULT, true). Then you should resize the tree that size, print, and then resize it back. Since you don't want users to notice that, during this operation you should disabled draws with setRedraw(false).
Here is a full snippet that does all this:
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
Composite composite = new Composite(shell, SWT.NONE);
composite.setLayout(new FillLayout());
final Tree tree = new Tree(composite, SWT.NONE);
for (int i = 0; i < 100; i++) {
final TreeItem treeItem = new TreeItem(tree, SWT.NONE);
treeItem.setText(String.format("item %d long name", i));
}
tree.addListener(SWT.DefaultSelection, new Listener() {
#Override
public void handleEvent(Event event) {
tree.getParent().setRedraw(false);
final Point originalSize = tree.getSize();
final Point size = tree.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
final Image image = new Image(display, size.x, size.y);
final GC gc = new GC(image);
tree.setSize(size);
tree.print(gc);
tree.setSize(originalSize);
final ImageLoader loader = new ImageLoader();
loader.data = new ImageData[]{image.getImageData()};
final String pathToSave = "out.png";
System.out.println(new File(pathToSave).getAbsolutePath());
loader.save(pathToSave, SWT.IMAGE_PNG);
gc.dispose();
image.dispose();
tree.getParent().setRedraw(true);
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
Press enter to save the file.

Selective menu detection within a Composite

I want to add some objects into an Composite object. Objects can have different shapes (rectangle, circle, ellipse or even weird shape (represented by a polygon). So I defined classes like this:
public class Circle extends Canvas {
}
public class Rectangle extends Canvas {
}
...
I know how to draw in a Canvas to get the shape I want, but I also expected that the popup menu appears at each canvas only if the users click mouse inside the canvas area, so if I use these code in a composite class:
Menu aSampleMenu = new Menu(this);
Circle circle = new Circle(parent, style);
circle.setMenu(aSampleMenu);
the menu will appear if the user click right mouse button anywhere inside the canvas, even outside the shape area. How can I fix this problem?
Have a look at the code snippet below. The trick is defining the Menu first and then setting it only to those Controls that should allow menu detection:
public class StackOverflow
{
public static void main(String[] args)
{
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new GridLayout(2, true));
Composite c1 = new Composite(shell, SWT.BORDER);
c1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
Composite c2 = new Composite(shell, SWT.BORDER);
c2.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
Menu menu = new Menu(shell, SWT.POP_UP);
MenuItem item = new MenuItem(menu, SWT.PUSH);
item.setText("Popup");
new Label(shell, SWT.BORDER).setText("No menu here");
new Label(shell, SWT.BORDER).setText("No menu here");
// Add menu only to c1 and c2, not to the shell and not to the labels
c1.setMenu(menu);
c2.setMenu(menu);
shell.setSize(300, 300);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Here is a screenshot:
One solution is using Region, but I still dont figure out how it can be applied to circle case:
Region region = new Region();
region.add(new int[] {3, 3, 20, 20, 3, 20});
Canvas c = new Canvas(this, SWT.NONE);
c.setBounds(35, 35, 60, 60);
c.setRegion(region);
Menu menu = new Menu(this);
c.setMenu(menu);
MenuItem mntmProperties = new MenuItem(menu, SWT.NONE);
mntmProperties.setText("Properties");
MenuItem mntmDelete = new MenuItem(menu, SWT.NONE);
mntmDelete.setText("Delete");

Java swt canvas how does the paint listener work?

I've just started working with swt's canvas. I'm under the impression that draw commands from the graphics controller (gc) can be executed in any listener that is attached to the canvas. I guess though, my question is what triggers the paint listener method paintControl?
Does the canvas.redraw() cause this to run as well?
Thanks for anyone who can point me in the right direction. If there are tutorials or books I can read on the matter(2d drawing in swt in general as well), I would love to hear of them.
EDIT:
Here is the code, I'm running into an issue where the graphCanvas is not filling excess vertical space? It doesn't work when I have it fill excessHorizontal space either. But it seems to work when I apply those properties to the composites. Any idea?
Color black = Display.getCurrent().getSystemColor(SWT.COLOR_BLACK);
chartComposite = new Composite(parent, SWT.NONE);
GridLayout chartGridLayout = new GridLayout(1,false);
GridData chartGridData = new GridData();
chartGridData.grabExcessHorizontalSpace = true;
chartGridData.grabExcessVerticalSpace = true;
chartComposite.setLayout(chartGridLayout);
chartComposite.setLayoutData(chartGridData);
chartInnerComposite = new Composite(chartComposite, SWT.NONE);
GridLayout chartInnerGridLayout = new GridLayout(2,false);
GridData chartInnerGridData = new GridData();
chartInnerGridData.grabExcessHorizontalSpace = true;
chartInnerGridData.grabExcessVerticalSpace = true;
chartInnerComposite.setLayout(chartInnerGridLayout);
chartInnerComposite.setLayoutData(chartInnerGridData);
/**
* Create the four canvases
*/
Canvas yCanvas = new Canvas(chartInnerComposite, SWT.None);
graphCanvas = new Canvas(chartInnerComposite, SWT.None);
GridLayout graphGridLayout = new GridLayout(1, false);
graphGridLayout.makeColumnsEqualWidth = false;
GridData graphGridData = new GridData(SWT.FILL);
graphGridData.widthHint = 400;
graphGridData.grabExcessVerticalSpace = true;
graphCanvas.setLayout(graphGridLayout);
graphCanvas.setLayoutData(graphGridData);
graphCanvas.addPaintListener(new PaintListener() {
#Override
public void paintControl(PaintEvent e) {
e.gc.drawLine(20, 20, 500, 500);
e.gc.drawRectangle(0, 0, graphCanvas.getSize().x -1, graphCanvas.getSize().y -1);
e.gc.drawLine(0, 40, 500, 500);
e.gc.drawLine(0, 0, 0, 1200);
e.gc.drawLine(0, 0, 1200, 0);
}
});
/*graphCanvas.setSize(400, 400);
graphCanvas.redraw();
graphCanvas.update();*/
Canvas filler = new Canvas(chartInnerComposite, SWT.NONE);
Canvas xCanvas = new Canvas(chartInnerComposite, SWT.None);
Your code can definitely call canvas.redraw() manually, which will then trigger a paintControl event. SWT itself will also cause repaints to be triggered as needed, for things like window resizing and when the canvas gets obscured/un-obscured by other windows.

Categories