I have a C++/Qt background and am now learning Java and SWT GUI programming. I need to draw some primitive shapes (circles, rectangles, etc.) on an image. The shapes need to move on the image (ie. change its position in relation to the background, imagine a real-time updating map). In Qt this could be easily done by using QGraphicsScene and QGraphicsItems but how to achieve this in SWT? I have tried to use Composite with Label which is close to what I need but I haven't found a way to add primitive shapes to the Composite.
The Canvas control is specifically for drawing on. Basic drawing operations are in the GC class.
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) {
Rectangle r = drawWidget.getClientArea();
e.gc.drawOval(0, 0, r.width - 1, r.height - 1);
}
});
Call the Canvas redraw method to request that the control be redrawn. This will call the paint listener again.
Other Eclipse packages such as Eclipse GEF provide much more sophisticated drawing APIs.
Related
I'm programming my first java App, I wanna create a GUI, which allow to draw different Plan. As close as possible to this representation :
My implementation is based on SWT.
For drawing Nodes and Edges, I used addPaintListener() method from the class Canvas.
But i have following problem, the method paintControl() is called infinitely times, redrawing every time.
I ask myself if there is a way to avoid it, or maybe a better way to draw a plan in Java.
Can someone of you suggest me a best way to draw diagram and edge in Java
Canvas canvas = new Canvas(composite, SWT.ALL);
canvas.addPaintListener(new PaintListener() {
#Override
public void paintControl(PaintEvent e) {
Rectangle rect=new Rectangle(0, 0, 60, 30);
e.gc.drawRectangle(rect);
}
});
i'm searching for a best implementation for my Gui-application.i have a problem in drawing edges
I can find neither a solution nor whether it is even possible to easily transform a Composite in SWT.
I'm trying to implement zooming in/out with CTRL+SCROLL over a Composite. What I found thus far is adding a PaintListener to a composite, like this:
this.viewingFrame = new Shell(new Display());
this.viewingFrame.setLayout(new GridLayout(2, false));
GridDataFactory.fillDefaults().grab(true, true).applyTo(viewingFrame);
c1 = new Composite(viewingFrame, SWT.NONE);
GridLayoutFactory.swtDefaults().applyTo(c1);
GridDataFactory.swtDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(c1);
c1.addPaintListener(new PaintListener() {
#Override
public void paintControl(PaintEvent e) {
Transform trans = new Transform(e.display);
e.gc.setAdvanced(true); // After this line a call to e.gc.getAdvance() returns true
trans.scale(1.5f, 1.5f);
e.gc.setTransform(trans);
trans.dispose();
}
});
// Of course there is more code. I have a KTable displaying a 2D map. I also tried adding the PaintListener to the shell, the composite c1 and the KTable. Same result.
However this doesn't work. While debugging I could see that the listener is called but there is no visible effect.
I'm a novice with regard to SWT but I learn fast so I'm willing to consider complex solutions.
The short answer is: scaling controls in SWT is not supported (directly). The Transform applies only to the drawing operations that are done on the GC for which it was created. It does not affect the controls that are contained in the Composite.
To emulate scaling to a cretain degree, you can change the font size of the container whose content should scale (i.e. the Shell or a Composite) and then re-layout. The font size is inherited by contained controls unless a font was explicitly set. In the latter case you would have to change the size of these fonts as well.
If you want the Shell to grow/shrink with its content you will have to pack() it. Otherwise you likely need to place a ScrolledComposite within the Shell that contains all the actual content.
BTW use the Canvas widget instead of a Composite if you actually want to draw something.
My setup:
I have a GWT Canvas that displays some grafics that rely on heavy algorithms. The objects are dragable, and therefore on drag I save everything beside the dragged object on a temporary canvas and reuse this as an image behind the dragging context.
My question:
My drag canvas is a reused Canvas object, that has first to be cleared before saving the static context to it before dragging starts.
I wonder if "reuse and clear" is better than "create a new canvas object".
What do you think?
Either clear canvas everytime:
private Canvas canvas;
void buffer() {
canvas.getContext2d().clearRect(0, 0, Window.getClientWidth(), Window.getClientHeight());
//...draw
}
...or create new object:
void buffer() {
Canvas canvas = Canvas.createIfSupported();
//draw
}
"Reuse and clear" is superior. It is more efficient since it only calls the native clearRect(x, y, w, h). There are many events that fire during the addition and removal widgets. I would use a new object only if it were a logical concept. You may also want to consider Lienzo.
I am trying to do render a swing UI into an OpenGl texture. All that works so far is this piece of code (btw it is Scala, but it should be obvious)
var image = new BufferedImage( width, height, BufferedImage.TYPE_4BYTE_ABGR)
mainFrame.paint(image.getGraphics)
var outputfile = new File("saved.png")
ImageIO.write(image, "png", outputfile)
But those things are still missisg:
I need to be notified when anything in the swing components changes, so that I can update the glTextures when needed.
The rendering to a swing window should be disabled
A virtual mouse would be nice, so that I can use my projected mouse position on the texture
Dynamic keyboard processing, so that I can activate keyboard processing as long as the UI is active. Else I would use LWJGL input processing.
I think the best way to approach the first two issues would be a Decorator to the Graphics object used to draw all the swing components, but I did not find any way to implant my variation of that class into Swing.
I hope that's it. But if you know a library that has already solved my problem you are welcome, but please do not recommend TWL.
I am working on some NetBeans platform app, and i am currently stuck on some detail in Visual Library. Ok, here is problem. I have Visual Editor for my app, with pallet, scene and everything works great, just there is a problem when i am dragging icons from pallet to scene. They are not displayed during drag event, i would like to create that effect, can someone help on this?
I do this in two phases:
1) Create a screenshot (an image) of a palette element. I create the screenshot lazily and then cache it within the view. To create the screenshot, you can use this snippet:
screenshot = new BufferedImage(getWidth(), getHeight(), java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE);// buffered image
// creating the graphics for buffered image
Graphics2D graphics = screenshot.createGraphics();
// We make the screenshot slightly transparent
graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f));
view.print(graphics); // takes the screenshot
graphics.dispose();
2) Paint the screenshot on the receiving view. When the drag gesture is recognized, find a way to make the screenshot available to the receiving view or one of its ancestor (you could make it available on the frame or its content pane, depending on where you want to make the screenshot drag available) and paint the image within the paint method. Something like this:
a. Make the screenshot available:
capturedDraggedNodeImage = view.getScreenshot(); // Transfer the screenshot
dragOrigin = SwingUtilities.convertPoint(e.getComponent(), e.getDragOrigin(), view); // locate the point where the click was made
b. As the mouse is dragged, update the location of the screenshot
// Assuming 'e' is a DropTargetDragEvent and 'this' is where you want to paint
// Convert the event point to this component coordinates
capturedNodeLocation = SwingUtilities.convertPoint(((DropTarget) e.getSource()).getComponent(), e.getLocation(), this);
// offset the location by the original point of drag on the palette element view
capturedNodeLocation.x -= dragOrigin.x;
capturedNodeLocation.y -= dragOrigin.y;
// Invoke repaint
repaint(capturedNodeLocation.x, capturedNodeLocation.y,
capturedDraggedNodeImage.getWidth(), capturedDraggedNodeImage.getHeight());
c. paint the screenshot in paint method:
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2.drawImage(capturedDraggedNodeImage, capturedNodeLocation.x,
capturedNodeLocation.y, capturedDraggedNodeImage.getWidth(),
capturedDraggedNodeImage.getHeight(), this);
}
Instead of calling repaint() and perform the painting in the paint() method, you could invoke paintImmediately() as the mouse moves but the rendering will be a lot poorer and you could observe some flickering, so I would not recommend that option. Using paint() and repaint() provides a better user experience and a smooth rendering.
If I hear you well, you are creating a graphical editor of some sort, with drag and drop of elements, and you want to create an effect during that drag and drop?
If so, you basically need to create a ghost of the object you're dragging and attach it to the move of the mouse. Easier said than done, of course, but you get the gist.
So what you need is to take the image of what you're dragging (it shouldn't be too much trouble) and move it according to the position of the mouse (think of substracting the relative position of the mouse cursor in the object you're dragging).
But I think that kind of code is available somewhere. I'd advise you to look that up :
http://free-the-pixel.blogspot.fr/2010/04/ghost-drag-and-drop-over-multiple.html
http://codeidol.com/java/swing/Drag-and-Drop/Translucent-Drag-and-Drop/
Hope that helps you!