Jpanel Zooming like in a paint program - java

I've got a problem over a zoom feature on a program. Here's the deal, I got a canvas which extends a jpanel and has a grid drawn on it. My problem is how to implement a zoom function. By zooming on the jpanel each small squares on the grid will divided into 3x3.
I've tried doing a 3 panel zoom, 3 panels with 3 different sizes with different division on the grid but it takes up a lot of memory and run time. I'm implementing only 1 jpanel with fix size and will zoom on it by using Graphics2d.scale(...) but seems to have an offset on the mouse coordinates and the jpanel's. I know it could be fix but my other concern is the jpanel is implemented with jscrollpane. Will fixing the coordinate offset will solve this issue, i haven't tried because i don't know how.
paint in the jpanel drawing the grid
public void paint(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
int x=0;int y=0;
g2.setColor(Color.GRAY);
for(int i=1; i<this.divisions; i++){
x = i *divSize;
g2.drawLine(x, 0, x, this.size);
}
for(int i=1; i<this.divisions; i++){
y = i *divSize;
g2.drawLine(0, y, this.size, y);
}
/*code for filling the small squares with colors*/
}

You can draw all your content on a BufferedImage. Graphics of the image can be scaled to achieve desired zoom effect.
But anyway if you use JScrollPane with panel inside the panel's size (preferred size) must be adapted to show scrollbars when it's needed.

Related

Changing origin for circle in JPanel

I'm using the JPanel and JFrame to animate an example of something called Circle Packing, which essentially is just filling an object with continuously growing circles to fill the object with circles of different sizes.
I've been able to animate an arraylist of circle objects, but they grow in a way that is not desirable for my project. A circle growing, according to me, is a fixed point P from which a circle with radius R around it is created, and it expands solely by the R increasing. JPanel does not act this way. It changes the x and y positions as well, which I do not understand.
This is my repaint:
public void repaint(Graphics g) {
g.setColor(new Color(125, 0, 100));
g.fillRect(0, 0, WIDTH, HEIGHT);
g.setColor(new Color(255, 165, 0));
Circle myCircle = new Circle(rand.nextInt(500), rand.nextInt(500), 1);
circles.add(myCircle);
for (Circle c : circles) {
int newx = (int) c.getX();
int newy = (int) c.getY();
int newsize = (int) c.getSize();
c.grow();
c.growth(); // These are the growing functions
c.Edges();
g.drawOval(newx, newy, newsize, newsize);
}
}
and my grow, growth and Edges are to check for cases where the circles touches the sides of the screen.
Please edit my question to a more appropriate title if necessary, I'm still new to S.O.
A circle growing, according to me, is a fixed point P from which a circle with radius R around it is created, and it expands solely by the R increasing
Maybe, but you didn't write the Graphics API. So your code needs to work based on the methods of the API.
It changes the x and y positions as well, which I do not understand.
Read the API for the drawOval(...) method to understand how it works. Don't assume how it works.
The method works by specifying the top/left x/y point, not the center point.
So if the radius increases, the x/y values must decrease if you want the center point to remain constant. So you need to fix your grow logic.
I'm using the JPanel and JFrame to animate an example of something called Circle Packing,
Also, don't generate random values in a painting method. You can't control when the component will be repainted so the values can change unexpectedly. That is don't change the state of an object in a painting method.
So you need a method to "grow" each circle (which is separate from your painting code). This method will adjust the radius and x/y location of each object in the Array. Then you invoke repaint() on the panel. The painting code will then just iterate through the Array and paint the current state of each object in the array.

Java paintComponent(Graphics g) drawn graphics disappear

I am new to the graphics and paint on java swing component. I have a few code issue related to these areas.
I have a customJPanel that extends JPanel. Inside the panel, there is a "+" and "-" button to increase the number of image by 1 at a time (minimum 1 image, maximum 50 image). The images are already stored in a list. The buttons are listener that takes care of the add/remove image on the customJPanel:
//ADD BUTTON LISTENER
imagePanel.add(imageList.get(i);
add(imagePanel, BorderLayout.CENTER); //customPanel contains a imagePanel(center), and another panel(south)
repaint();
revalidate();
Once the images are added, I have a function that draws lines to link the images to a fixed point(x1, y1) on the JPanel.
public void drawLinkedLine(){
Graphics2D g2d = (Graphics2D) imagePanel.getGraphics();
g2d.setColor(Color.BLACK);
for(int i = 0; i < imagesList.size(); i++){
//some codes to get the image location on the imagePanel
g2d.drawLine(x1, y1, x2, y2);
}
}
This method is called by the override paintComponent(Graphics g):
public void paintComponent(Graphics g){
super.paintComponent(g);
drawLinkedLine();
}
The issues I am facing now is when I click on the button, it adds/removes 1 image. It suppose to draw line from that image to (x1,y1). However, I can see the lines appear in a flash and disappear. Why would this happening and is there a way to solve this?

Build a grid and let the squares blink

I'm not well familiar with Java and try to build a grid in a window but I'm not sure which Class I should extend (like JFrame) and which method is the best way to get that grid.
My goal is to create a grid and let the squares blink randomly.
I tried it JPanel but not sure if it is the right way
JPanel content = new JPanel(new GridLayout(4,4));
I would use a JPanel on a JFrame. You override the paintComponent Method of the JPanel to fit your needs:
#Override
public void paintComponent(Graphics g){
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLACK);
//draw rects
for(int i=0; i<n; i++){
//draw rects
g2d.drawRect(x, y, width, height);
}
//fill rects
for(int i=0; i<n i++){
//set random color for blinking effect
g2d.setColor(/*random color*/);
g2d.fillRect(x, y, width, height);
}
}
You have to compute the grid yourself though, using the size of your JPanel and the size of the squares you want to draw.
Then, set a Timer and redraw every time you want that blinking effect.
If you are not familiar with java Swing and simple draw operations, you should watch same tutorials etc. because im not going to explain it all here ;).

How to display the whole contents of a large JPanel in a small JFrame?

I have a JPanel with a size of 816 x 1056 pixels (size of a standard typewriting paper). Is there any way of displaying the whole JPanel and its content without altering its actual size, in a small JFrame? Is there a way of like zooming it out?
I can't think of an easy method to zoom a JPanel out, but you can do it via double-buffering:
private void paintPanel (Graphics2D g)
{
// here goes the code of your paint() or paintComponent() method
}
/** Draw content into an Image, shrink it, and display it. */
protected void paintComponent (Graphics g)
{
// paint image
BufferedImage img = new BufferedImage(MAX_WIDTH, MAX_HEIGHT, BufferedImage.TYPE_INT_ARGB);
paintPanel(img.createGraphics());
// shrink image and paint it
g.drawImage(img, 0,0, WIDTH,HEIGHT, 0,0, MAX_WIDTH,MAX_HEIGHT, null);
}
This will paint everything on a BufferedImage with the size MAX_WIDTH x MAX_HEIGHT. Then, the Image will be shrinked into the size WIDTH x HEIGHT and then displayed.

Drawing a dot grid

I'm new to graphics programming. I'm trying to create a program that allows you to draw directed graphs. For a start I have managed to draw a set of rectangles (representing the nodes) and have made pan and zoom capabilities by overriding the paint method in Java.
This all seems to work reasonably well while there aren't too many nodes. My problem is when it comes to trying to draw a dot grid. I used a simple bit of test code at first that overlayed a dot grid using two nested for loops:
int iPanX = (int) panX;
int iPanY = (int) panY;
int a = this.figure.getWidth() - iPanX;
int b = this.figure.getHeight() - (int) iPanY;
for (int i = -iPanX; i < a; i += 10) {
for (int j = -iPanY; j < b; j += 10) {
g.drawLine(i, j, i, j);
}
}
This allows me to pan the grid but not zoom. However, the performance when panning is terrible! I've done a lot of searching but I feel that I must be missing something obvious because I can't find anything on the subject.
Any help or pointers would be greatly appreciated.
--Stephen
Use a BufferedImage for the dot grid. Initialize it once and later only paint the image instead of drawing the grid over and over.
private init(){
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics g = image.getGraphics();
// then draw your grid into g
}
public void paint(Graphics g) {
g.drawImage(image, 0, 0, null);
// then draw the graphs
}
And zooming is easily achieved using this:
g.drawImage(image, 0, 0, null); // so you paint the grid at a 1:1 resolution
Graphics2D g2 = (Graphics2D) g;
g2.scale(zoom, zoom);
// then draw the rest into g2 instead of g
Drawing into the zoomed Graphics will lead to proportionally larger line width, etc.
I think re-drawing all your dots every time the mouse moves is going to give you performance problems. Perhaps you should look into taking a snapshot of the view as a bitmap and panning that around, redrawing the view 'properly' when the user releases the mouse button?

Categories

Resources