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