我希望通过以下代码生成网格,在单击时报告鼠标指针相对于pnlGrid
位置的x和y坐标。但无论我在哪里点击(在我添加JLayeredPane
之前),我都没有坐标,除非鼠标指针位于红色区域。
所以我添加了几行代码来制作JLayeredPane
并获得鼠标坐标输出,但没有网格线,如第二次屏幕截图所示。
如果点击网格中的任何位置,如何同时获取网格线和鼠标坐标报告?
package gridcellcoordinator;
import gbl.GBConstraints;
import static java.awt.Color.*;
import java.awt.Color;
import java.awt.Dimension;
import static java.awt.EventQueue.invokeLater;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import static javax.swing.JLayeredPane.DEFAULT_LAYER;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.LineBorder;
import javax.swing.event.MouseInputAdapter;
public class GridCellCoordinator {
final static int
GRID_PANEL_BORDER_WIDTH = 5,
N = 11,
CELLSIZE = 40;
//static final JLayeredPane layer = new JLayeredPane();
static final JPanel panel = new JPanel();
static final int SM_CELL_BORDER_WIDTH = 1;
static LineBorder SMcellBorder = new LineBorder(BLACK,SM_CELL_BORDER_WIDTH);
static JTextField[][] cells = new JTextField[N][N];
static JFrame frame = new JFrame();
public GridCellCoordinator(){
makeGrid();
}
private void makeGrid(){
JPanel pnlGrid = new JPanel();
pnlGrid.setLayout(new GridLayout(N,N));
pnlGrid.setBackground(BLUE);
pnlGrid.setBorder(BorderFactory.createLineBorder(Color.red,GRID_PANEL_BORDER_WIDTH));
pnlGrid.setLayout(new GridLayout(N, N));
for(int i = 0 ; i < N ; i++)
for(int j = 0; j < N; j++){
cells[i][j] = new JTextField();
cells[i][j].setText("X");
cells[i][j].setPreferredSize(new Dimension(CELLSIZE,CELLSIZE));
cells[i][j].setHorizontalAlignment(JTextField.CENTER);
cells[i][j].setFocusTraversalKeysEnabled(false);
cells[i][j].setBorder(SMcellBorder);
cells[i][j].setOpaque(true);
pnlGrid.add(cells[i][j], new GBConstraints());
}
panel.addMouseListener(new MouseInputAdapter()
{
public void mousePressed (MouseEvent e){panelMousePressed (e);}
});
pnlGrid.setPreferredSize(new Dimension(N*(CELLSIZE + 1) + 2*GRID_PANEL_BORDER_WIDTH ,
N*(CELLSIZE + 1) + 2*GRID_PANEL_BORDER_WIDTH));
panel.add(pnlGrid);
panel.setVisible(true);
panel.setOpaque(true);
panel.setPreferredSize(pnlGrid.getPreferredSize());
panel.setVisible(true);
//layer.add(pnlGrid, DEFAULT_LAYER);
//layer.setPreferredSize(pnlGrid.getPreferredSize());
//layer.setVisible(true);
frame.add(panel);
frame.setSize(new Dimension(pnlGrid.getPreferredSize()));
frame.setVisible(true);
frame.pack();
System.out.println("pnlGrid component count: " + pnlGrid.getComponentCount());
System.out.println("computed dimension: " + (N*(CELLSIZE + 1) + 2*GRID_PANEL_BORDER_WIDTH));
System.out.println("pnlGrid pref size: " + pnlGrid.getPreferredSize());
System.out.println("layer pref size: " + layer.getPreferredSize());
System.out.println("panel pref size: " + panel.getPreferredSize());
}
public void panelMousePressed(MouseEvent e){
JOptionPane.showMessageDialog(null,"Pressed:" + e.getX() + " " + e.getY());
}
public static void main(String[] args) {
invokeLater(new Runnable() {
public void run() {
new GridCellCoordinator();
}
});
}
}
P.S。因此,代码在左侧生成网格,但仅在红色边框内生成坐标。删除4层线上的注释栏以获取坐标但没有网格线。我喜欢BOTH网格线和坐标。
答案 0 :(得分:1)
但是,要修复代码,您需要更改焦点。您需要将其附加到文本字段,而不是将MouseListener
附加到pnlGrid
。这样做的原因是鼠标事件就像雨滴一样,任何带有附件MouseListener
的组件都会像伞一样,阻止MouseEvents
出现在视觉下方的组件上
要将MouseEvent
从一个组件上下文转换为另一个组件上下文,您可以使用SwingUtilities.convertMouseEvent
或SwingUtilities.convertPoint
例如......
import java.awt.Color;
import static java.awt.Color.BLACK;
import static java.awt.Color.BLUE;
import java.awt.Dimension;
import static java.awt.EventQueue.invokeLater;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
public class GridCellCoordinator {
final static int GRID_PANEL_BORDER_WIDTH = 5,
N = 11,
CELLSIZE = 40;
//static final JLayeredPane layer = new JLayeredPane();
static final JPanel panel = new JPanel();
static final int SM_CELL_BORDER_WIDTH = 1;
static LineBorder SMcellBorder = new LineBorder(BLACK, SM_CELL_BORDER_WIDTH);
static JTextField[][] cells = new JTextField[N][N];
static JFrame frame = new JFrame();
public GridCellCoordinator() {
makeGrid();
}
private void makeGrid() {
JPanel pnlGrid = new JPanel();
pnlGrid.setLayout(new GridLayout(N, N));
pnlGrid.setBackground(BLUE);
pnlGrid.setBorder(BorderFactory.createLineBorder(Color.red, GRID_PANEL_BORDER_WIDTH));
pnlGrid.setLayout(new GridLayout(N, N));
MouseListener mouseHandler = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
doMousePressed(e);
}
};
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cells[i][j] = new JTextField() {
@Override
public Dimension getPreferredSize() {
return new Dimension(20, 20);
}
};
cells[i][j].setText("X");
cells[i][j].setPreferredSize(new Dimension(CELLSIZE, CELLSIZE));
cells[i][j].setHorizontalAlignment(JTextField.CENTER);
cells[i][j].setFocusTraversalKeysEnabled(false);
cells[i][j].setBorder(SMcellBorder);
cells[i][j].addMouseListener(mouseHandler);
pnlGrid.add(cells[i][j]);
}
}
panel.add(pnlGrid);
panel.setVisible(true);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
public void doMousePressed(MouseEvent e) {
Point p = e.getPoint();
System.out.println("Source point = " + p + " within " + e.getComponent());
p = SwingUtilities.convertPoint(e.getComponent(), p, e.getComponent().getParent());
System.out.println("Converted point = " + p + " within " + e.getComponent().getParent());
}
public static void main(String[] args) {
invokeLater(new Runnable() {
public void run() {
new GridCellCoordinator();
}
});
}
}
您应该避免使用setPreferredSize
并在需要时依赖更多覆盖getPreferredSize
。有关详细信息,请参阅Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?
答案 1 :(得分:0)
好吧,在上面的例子中,每个单独的编辑小部件都是吃老鼠的。
普通的Java表只是在一个面板中显示该表,然后当它被单击时,它会在那时创建一个控件来处理编辑。因此,它不是一大堆编辑控件。结果证明效率很低。
所以,解决方案是“不做你正在做的事情”#34;。或者使用已经尝试过的分层窗格。
附录:
问题是你有一系列头等组件,每个组件都有自己的&#34; little&#34;矩形,而不是更大的单一组成部分。这就是您遇到的问题。 Swing正在处理所有这些标签和个别事物(因为它们是)。与容器相比,他们没有任何全球背景可以轻松报告。您必须根据转换为&#34;全球&#34;的本地坐标进行推断。在较大的小组内协调。