I am developing vector graphics editor in Java Swing/AWT technology.
I am curious about solution for creating drawing area (workspace), which have size bigger than users screen resolution.
For example: Window of creating new file
public WorkspaceComponent() {
setPreferredSize(new Dimension(**WIDTH**,**HEIGHT**));}
User wants to create a document of size e.g 1920 x 1080[px], but his/her screen has only 1280 x 720 [px].
Does anybody have an idea or solution for scaling the drawing area to match screen and after export having original size?
Using an AffineTransform on the Graphics2D Context you can scale the drawing area. Using this, you could even implement something like a zoom in/out feature.
double scaledSize = ... // do calculations of the scale here
AffineTransform t = new AffineTransform();
t.scale(scaledSize, scaledSize);
g2d.setTransform(t);
// do your drawing after setting the transform
If your scale is 1, it wont change the scale. A value less than one will make it smaller and a value greater than 1 will make it bigger.
Related
I'm creating a game in libGDX. I want to create some UI elements (buttons and stuff), because of my app design, I would like to draw them in the world space, as other game objects.
I'm using Freetype generator that generates a bitmap font from true type font files(.ttf). The problem is that the dimension of the font is in pixels.
Orthographic camera that I use to to render the world, has viewport size of approximately 10x10, so when I generate a font at the size of 10, it covers almost whole screen(too big) and also looks very ugly because generated bitmap for the font is too small (too few pixels).
What I want is to create sprite, draw it at same size(world space) and draw text over it, and basicly create a button.
Is there some well established way how to deal with this?
Thanks to clarifying comments, I've came up with the solution.
I took a point at which I wanted to draw the text, projected it to the screen space by my world camera. Then I flipped y axis by:
point.y = viewportHeight - point.y;
Then I unprojected it with ScreenViewport (separate viewport for drawing the text, is uses camera of the size of the screen so 1unit == 1pixel).
Now I can draw text in projection where 1unit = 1pixel, on the point that is at the same place on the screen as previously chosen point in world space.
I also wanted to be able to draw text inside rectangular boundaries. For this I chose another point. At this point text should end. Did the same procedure as with start point, and then calculated width
targetWidth = endpoint.x - startpoint.x;
Then I used GlypthLayout class to get actual width of my text at some(generated) font size.
actualWidth = glyphLayout.width;
And when I scaled font like this
font.getData().setScale(targetWidth / actualWidth);
my font get scaled so drawed text is wide as target width.
But be aware of another problem! When I generate bimap font via FreetypeGenerator with size bigger when approximately 300, some letters don't draw, and are missing. (probably bug).
I'm using the approach I found in this answer to create zoom in/out functionality for an image labeling application. However, despite dealing with relatively high resolution images (order of 1500x1500 pixels), the scaling method for zoom leads to pixelation. I checked the image in Windows Photo Viewer and I could definitely zoom in without much pixelation until much more than the 200% zoom I have in my code.
If I resize only compared to the original image (i.e. not cascading each resize call), this works just fine (this is what's in the code snippet). But in order to do this, I lose any drawing functionality. Basically, I would like to be able to do the following:
Load an image
Draw lines/circles/shapes/etc on it
Zoom in (maintaining any drawing on the image)
Draw more
Zoom in/out at will for whatever reasons I need
In summary, the resizing-for-zoom works. It's preserving any additional drawing at each stage of the zoom that I can't seem to get.
Here's a code snippet of my resize function (heavily influenced by that answer cited before):
private void resizeImage()
{
int newImgW = (int)(this.zoom * this.imgW);
int newImgH = (int)(this.zoom * this.imgH);
BufferedImage resized = new BufferedImage(newImgW, newImgH, originalImage.getType());
graphics2D = resized.createGraphics();
graphics2D.drawImage(this.originalImage, 0, 0, newImgW, newImgH, null);
this.image = resized;
repaint();
}
I have a rather pressing question in regards to Swing, which I haven't touched for many years.
I have a code that allows the user to draw different rectangles on the pdf document (contained within JPanel). I draw them, move them, resize them, select them, and even write text on them. What I can't do is to keep them consistent when I zoom the document. As the document gets bigger, the rectangles I've drawn stay at the same position and the same size.
I was wondering if there's a relatively easy logic to track the zooming level and, most importantly, update the rectangles accordingly. I can retrieve zoom factor, it's a float, but, unfortunately, I'm using Rectangle object, which uses int for x, y, height, and width. It will be a hassle to convert it to Rectangle.Float, and I wanted to save it for a last resort.
I've tried to use AffineTransform, but I'm not quite familiar with it, for some reason I'm getting the wrong coordinates for y. Can anyone explain to me:
What's the best way to control the Rectangle object, as the pdf document gets zoomed in and out?
If AffineTransform is the best way, how should I handle it (maybe there's a link to a good explanation, if so - I couldn't find it)?
This is the only issue I've been struggling with and it's getting a bit frustrating now.
To scale using an AffineTransform:
Get the transform T of the Graphics object G
Create an AffineTransform object A
Set the scale of A
Set the transform of the G to A
Draw the shapes
Set the transform of G back to T
Translated into code - assuming scale is the value to scale by:
#Override
protected void paintComponent(Graphics gr){
super.paintComponent(gr);
Graphics2D g = (Graphics2D)gr;
AffineTransform prevTransform = g.getTransform();
AffineTransform at = new AffineTransform(prevTransform);
at.scale(scale, scale);
g.setTransform(at);
g.drawRect(...);
g.setTransform(prevTransform);
}
I am drawing a coordinate system with weight, height =10000*10000 on a frame. It too big, my graph can't fully display. I try to draw on scroll but it's lag. I want to display my graph on a frame 10000*10000, fit with my screen computer to print screen. What should I do?
You have to scale you graph. You know, Earth is very big but it fits map that can be shown on a screen of your smart phone :)
This means that if for example you want to show rectangle of 10000*10000 on screen that has (for example) 1000 pixels you have to scale your picture 10 times.
Option 1: Set the size of the JFrame on which you are displaying the graph to the desired size.
setSize(WIDTH, HEIGHT);
where WIDTH and HEIGHT are in pixels.
OR
Option 2: Scale the drawing. That is, simply divide each dimension in the drawing by 2 to make it half the size.
I am making a game in Java. I made a planet seen from outer space and I want to make it appear like the planet is slowly rotating. But I don't know how to rotate a image. I need a simple command that rotates my image 1 degree around its own center once. Any help?
This is what I want to do:
Image
Take a look at these tutorials:
Java2D: Have Fun With Affine Transform
Coordinate Translations and Rotations: Example Code
Transforming Shapes, Text, and Images
What you are describing is not rotating an image, but changing an image to represent a 3D rotation of the object in the image.
Ideally you wouldn't be working with this as an image but rather as a 3D object with a different camera angle. Then you would simply rotate the camera around the object and display the resulting image to the user.
However if you're set on doing this as an image, then you need to create a different images representing various states of rotation of your planet and have a separate thread that would replace the displayed image with the next one in sequence, at repeated intervals. Search the web for "java image animation" - there are plenty of tutorials on how to do this.
If you want to rotate an image in 2d space, you can use something like this:
Image image = ...
Graphics2D g2d = ...; //
g2d.translate(170, 0); // If needed
g2d.rotate(1); // Rotate the image by 1 radian
//or g2d.rotate(180.0/3.14); to rotate by 1 degree
g2d.drawImage(image, 0, 0, 200, 200, observer);