Home > Back-end >  Java - how to make text show up in the spot you clicked?
Java - how to make text show up in the spot you clicked?

Time:07-06

I have created a Jframe that displays the x and y value based on where you click. The JFrame is 300x100px.

Right now when I click inside the JFrame i do get the correct x and y points but the text appears in random spots on the JFrame. I want the text to appear wherever the user clicks instead of in random spots because often times it shows up outside of the frame..what am i doing wrong in my code?

************************************************************/

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.event.MouseInputListener;

public class Proj06Runner {
    public static void main(String[] args) {
            System.out.println("NAME"); //replace with name 

        //creating jframe
        JFrame main = new JFrame("NAME"); //replace with name       

        //set size of frame
        main.setSize(300, 100);

        //creating lable
        JLabel j1 = new JLabel("");
        j1.setForeground(Color.RED);
        //make frmae visible
        main.setVisible(true);
        //addding mouselistner to frame
        main.addMouseListener(new MouseInputListener() {

            @Override
            public void mouseClicked(MouseEvent e) {
                String output = "x="   e.getX()   ",y="   e.getY();

                //add label to text which is shown
                j1.setText(output);
                Dimension size=j1.getPreferredSize();

                j1.setBounds(e.getX(),e.getY(),size.width,size.height);
                main.add(j1);
            }
            //MouseInputListner is interface so that we have to implement all methods
            @Override
            public void mousePressed(MouseEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mouseReleased(MouseEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mouseEntered(MouseEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mouseExited(MouseEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mouseDragged(MouseEvent e) {
                // TODO Auto-generated method stub

            }

            @Override
            public void mouseMoved(MouseEvent e) {
                // TODO Auto-generated method stub

            }

        });
        //make progrma terminate after clicking close button
        main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

CodePudding user response:

It is because of the layout. Layout managers are used to automatically determine the layout of components in a container. If you want to put components at specific coordinate locations, then you should not use a layout manager at all.

Either set layout of JFrame or JPanel as a null.

main.setLayout(null);

CodePudding user response:

You could...

Use a custom painting based solution, for example...

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private List<Point> points = new ArrayList<>(8);

        public TestPane() {
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    points.add(e.getPoint());
                    repaint();
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 100);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            FontMetrics fm = g2d.getFontMetrics();
            for (Point p : points) {
                g2d.drawString("x = "   p.x   ",y = "   p.y, p.x, p.y   fm.getAscent());
            }
            g2d.dispose();
        }

    }
}

See Painting in AWT and Swing and Performing Custom Painting for more details

You could...

Use a custom layout manager...

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.LayoutManager2;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {
        private List<Point> points = new ArrayList<>(8);

        public TestPane() {
            setLayout(new PointLayoutManager());
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    add(new JLabel("x="   e.getX()   ",y="   e.getY()), e.getPoint());
                    repaint();
                    revalidate();
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 100);
        }
    }

    public class PointLayoutManager implements LayoutManager2 {

        private Map<Component, Point> points = new HashMap<>();

        @Override
        public void addLayoutComponent(Component comp, Object constraints) {
            if (constraints instanceof Point) {
                points.put(comp, (Point)constraints);
            }
        }

        @Override
        public Dimension maximumLayoutSize(Container target) {
            return preferredLayoutSize(target);
        }

        @Override
        public float getLayoutAlignmentX(Container target) {
            return 0.5f;
        }

        @Override
        public float getLayoutAlignmentY(Container target) {
            return 0.5f;
        }

        @Override
        public void invalidateLayout(Container target) {
        }

        @Override
        public void addLayoutComponent(String name, Component comp) {
        }

        @Override
        public void removeLayoutComponent(Component comp) {
            points.remove(comp);
        }

        @Override
        public Dimension preferredLayoutSize(Container parent) {
            int maxX = 0;
            int maxY = 0;
            for (Component comp : parent.getComponents()) {
                Dimension size = comp.getPreferredSize();
                maxX = Math.max(comp.getX()   size.width, maxX);
                maxY = Math.max(comp.getY()   size.height, maxY);
            }

            return new Dimension(maxX, maxY);
        }

        @Override
        public Dimension minimumLayoutSize(Container parent) {
            return preferredLayoutSize(parent);
        }

        @Override
        public void layoutContainer(Container parent) {
            for (Component comp : parent.getComponents()) {
                Point p = points.get(comp);
                if (p == null) {
                    // This will deliberatly hide the component
                    comp.setSize(0, 0);
                    continue;
                }
                Dimension size = comp.getPreferredSize();
                comp.setBounds(new Rectangle(p, size));
            }
        }

    }
}

This will play nicely with other components and you could wrap the component in a JScrollPane and get a resizable window for free.

99.9% of the time when you think you don't need a layout manager, you're wrong, the other 0.1% of the time, you need a custom layout manager

  • Related