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 ;).
Related
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?
Ok dear folks, i've got this question and i don't really know a certain way to solve it.
I'm doing like a "Paint application" in java, i know everything is ready, but I need to paint the shapes with Computer Graphics Algorithms.
So, the thing is, once the shape is painted in the container how could I convert it like sort of an "Object" to be able to select the shape and move it around (I have to move it with another algorithm) I just want to know how could I know that some random point clicked in the screen belongs to an object, knowing that, I would be able to fill it(with algorithm).
I was thinking that having a Point class, and a shape class, if i click on the screen, get the coordinates and look within all the shapes and their points, but this may not be very efficient.
Any ideas guys ?
Thanks for the help.
Here is some of my code:
public class Windows extends JFrame{
private JPanel panel;
private JLabel etiqueta,etiqueta2;
public Windows() {
initcomp();
}
public void initcomp()
{
panel = new JPanel();
panel.setBounds(50, 50, 300, 300);
etiqueta = new JLabel("Circulo Trigonometrico");
etiqueta.setBounds(20, 40, 200, 30);
etiqueta2 = new JLabel("Circulo Bresenham");
etiqueta2.setBounds(150, 110, 200, 30);
panel.setLayout(null);
panel.add(etiqueta);
panel.add(etiqueta2);
panel.setBackground(Color.gray);
this.add(panel);
this.setLayout(null);
this.setVisible(true);
this.setSize(400,400);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void paint(Graphics g){
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.red);
g2d.setStroke(new BasicStroke(2));
dibujarCirculo_bresenham(g2d, 50, 260, 260);
dibujarCirculo_trigonometrico(g2d, 50, 130, 200);
}
/*This functions paints a Circle*/
public void dibujarCirculo_trigonometrico(Graphics g,int R,int xc,int yc)
{
int x,y;
for (int i = 0; i < 180; i++) {
double angulo = Math.toRadians(i);
x = (int) (Math.cos(angulo)*R);
y = (int) (Math.sin(angulo)*R);
g.drawLine(x+xc, y+yc, x+xc, y+yc);
g.drawLine((-x+xc), (-y+yc), (-x+xc), (-y+yc));
}
}
I assume that any image is a valid (isn't constrained to a particular set of shapes). To get an contiguous area with similar properties, try using a flood fill.
To colour in or move a particular shape around, you can use flood fill to determine the set of pixels and manipulate the set accordingly. You can set a tolerance for similar hue, etc so that it's not as rigid as in Paint, and becomes more like the magic selection tool in Photoshop.
There are a couple of approaches to take here depending on what precisely you want.
1) is to have objects, one for each drawn thing on screen, with classes like Circle and Rectangle and Polygon so on. They would define methods like paint (how to draw them on screen), isCLickInsideOf (is a click at this point on screen contained by this shape, given size/position/etc?) and so on. Then, to redraw the screen draw each object, and to test if an object is being clicked on ask each object what it thinks.
2) is, if objects have the property of being uniform in colour, you can grab all pixels that make up a shape when the user clicks on one of the pixels by using a floodfill algorithm. Then you can load these into some kind of data structure, move them around as the user moves the mouse around, etc. Also, if every object is guaranteed to have a unique colour, you can test which object is being clicked on by just looking at colour. (Libraries like OpenGL use a trick like this sometimes to determine what object you have clicked on - drawing each object as a flat colour on a hidden frame and testing what pixel colour under the mouse pointer is)
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.
How can I mousedrag different BufferedImages in Java2D?
For instance, if I have ten or more images, how can I move that images which my mouse is over?
Now I'm importing an BufferedImage with
BufferedImage img = new BufferdImage(new File("filename"));
And I'm painting this with Graphics2D with
public void paintComponent(Graphics g) {
super.paintComponent(g);
g2d = (Graphics2D) g;
g2d.drawImage(img, x1, y1, null);
g2d.drawImage(img2, x2, y2,null);
}
Everytime I'm moving on a image I'm repaint()-ing the entire screen.
My mousemove class is as follows
class MouseMotionHandler extends MouseMotionAdapter {
#Override
public void mouseDragged(MouseEvent e) {
x1 = e.getX() - (img.getWidth() / 2);
y1 = e.getY() - (img.getHeight() / 2);
repaint();
}
}
With this method I'm able to "drag" one picture, but what to do when I will drag more individually?
Use the BufferedImage to create an ImageIcon which you use to create a JLabel. Then you add the JLabel to the panel that uses a null layout. No custom painting code is required to do this.
Now if you want to drag the label around you can use the Component Mover.
You can try making a custom component that contains only a single image. Along with your painting and mouse motion handling code, the component overrides the contains method so that it returns true only if the coordinates are within the image.
These components are then stacked in a JLayeredPane, (hopefully) only moving the images that the mouse is on top of.
From what you ask I suppose that your current repainting logic is global. You need to apply it to every image you have. So, if you for instance display every image in JPanel attach MouseMotionListener to every such panel and make this logic happen in JPanel.
If you post more code - especially of the component you show your images in - I will be able to go into more details.
Here's is a simple example that implements dragging for either single- or multiple-selections. The object Node would correspond roughly to your object Card.
Addendum: Also considered the Overlap Layout mentioned in this answer to a related question. Instead of List<Node>, your program would manage a List<Card>, where each Card is a JLabel having a card image.
I should make tree arrays:
one for the x-values
one for the y-values
one for the BufferedImages
So, something like this:
int[] xValues = new int[10];
int[] yValues = new int[10];
BufferedImage[] imgs = new BufferedImage[10];
Then the
class MouseMotionHandler extends MouseMotionAdapter {
#Override
public void mouseDragged(MouseEvent e) {
for (int i = 0; i < 10; i++)
{
xValues[i] = e.getX() - (imgs[i].getWidth() / 2);
yValues[i] = e.getY() - (imgs[i].getHeight() / 2);
}
repaint();
}
}
Then paint them like this:
public void paintComponent(Graphics g) {
super.paintComponent(g);
g2d = (Graphics2D) g;
for (int i = 0; i < 10; i++)
{
g2d.drawImage(imgs[i], xValues[i], yValues[i], null);
}
}
I think something like this is what you need.
Here's the code for my JLayeredPane init. My problem here is that my images don't show up...
layeredPane = new JLayeredPane();
layeredPane.setPreferredSize(new java.awt.Dimension(500, 410));
layeredPane.setBorder(javax.swing.BorderFactory.createTitledBorder(
"Center deck"));
for(BufferedImage imgs : images){
JLabel label = new JLabel(new ImageIcon(imgs));
layeredPane.add(label, JLayeredPane.DEFAULT_LAYER);
}
add(layeredPane);
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?