问题描述
如果我在GridLayout中有几个JPanels,每个都有一个MouseAdapter,然后创建JLabel(带文本)并添加到每个JPanels。请注意,JLabel没有侦听器。
如果我渲染它并尝试点击JPanel,或者最终尝试点击JLabel,MouseAdapter会将其注册为事件吗?
If I have a few JPanels in a GridLayout, each one with a MouseAdapter, and then create JLabels (with text) and add to each one of the JPanels. Note the JLabels have no listeners.If I render this and try to click on a JPanel, or, ultimately try to click on the JLabel, will the MouseAdapter register that as an event?
基本上我希望JPanels注册事件和JPanels只显示JPanels上面的文本。此外,面板具有背景颜色。
Basically I want the JPanels to register events and the JPanels to just display text on-top of the JPanels. Also, the panels have background color.
如果JLabel确实隐藏了注册事件,我该如何解决这个问题?
If the JLabel does "hide" the events from registering, how can I go around this?
推荐答案
顶部组件将点击鼠标。 JLabel将涵盖多少将取决于其大小和JPanel的布局管理器。一种方法是将听众提供给JLabel(如上所述),但另一种方法是按照我在下面描述的方式,虽然可能不是最好的方式,但它对我来说效果很好:
The top component will get the mouse click. How much the JLabel will cover will depend on its size and on the JPanel's layout manager. One way is to give the listener to the JLabel (as has also been mentioned above), but another way to do it is as I describe below, and while perhaps not the best way, it worked well for me:
1)JLayeredPane包含所有内容并且有一个MouseAdapter,它被添加为MouseListener和MouseMotionListener。
1) A JLayeredPane holds everything and has a MouseAdapter that is added as a MouseListener and MouseMotionListener.
2)一个JPanel,名为board,它使用GridLayout(8,8)并且是JLayeredPane添加到分层窗格底层的确切大小,或者确切地说,是JLayeredPane.DEFAULT_LAYER。
2) A JPanel, called "board", that uses GridLayout(8, 8) and is the exact size as the JLayeredPane is added to the layered pane's bottom layer, or to be precise, the JLayeredPane.DEFAULT_LAYER.
3)这个JPanel在GridLayout中拥有64个其他小的JPanel方块(实际上是从JPanel扩展的方块),每个都使用GridBagLayout。
3) This JPanel holds 64 other small JPanel squares in the GridLayout (actually the squares extend from JPanel), and each uses GridBagLayout.
4)国际象棋片段是JLabel并由JPanel广场持有。
4) The chess pieces are JLabels and are held by the JPanel squares.
5)在MouseAdapter mousePressed方法中,我得到了鼠标位于via e的Point,p。 getPoint(如果e是传递给方法的MouseEvent对象)。然后我通过在JPanel板上调用findComponentAt(p)找出哪个方块能够解决这个问题。然后我检查这个方块是否有一块。如果是这样,则将该块从正方形中移除并直接添加到JLayeredPane的JLayeredPane.DRAG_LAYER中。
5) In the MouseAdapter mousePressed method, I get the Point, p, that the mouse is located at via e.getPoint (if e is the MouseEvent object passed to the method). I then find out which square holds this point by calling findComponentAt(p) on the board JPanel. I then check to see if this square holds a piece. If so, the piece is removed from the square and added directly to the JLayeredPane's JLayeredPane.DRAG_LAYER.
6)如果在JLayeredPane的JLayeredPane.DRAG_LAYER中保存了一个棋子,MouseAdapter的mouseDragged方法将控制该棋子的位置。
6) If a chess piece is held in the JLayeredPane's JLayeredPane.DRAG_LAYER the MouseAdapter's mouseDragged method will control the piece's location.
7)在mouseRelease上,我再次使用findComponentAt(p)通过与上面相同的技术找出哪个方块保持鼠标的位置或Point,如果它是一个有效的方块,我从JLayeredPane的JLayeredPane中移除棋子.DRAG_LAYER并将其放在广场上。如果它不在棋盘上或不是有效的方格,我将棋子返回到原始位置。
7) On mouseRelease, I again find out which square holds the mouse's location or Point by the same technique as above, using findComponentAt(p) and if it is a valid square, I remove the chess piece from the JLayeredPane's JLayeredPane.DRAG_LAYER and place it in the square. If it's off the board or not a valid square, I return the chess piece to the original location.
注意如果棋盘JPanel没有完全填满JLayeredPane,然后,在调用findComponentAt(p)之前,必须使用它在JLayeredPane中的偏移量来校正位置Point,p,因为MouseAdapter将返回相对于JLayeredPane而不是棋盘JPanel的点数。
Note that if the board JPanel doesn't completely fill the JLayeredPane, then its offset within the JLayeredPane must be used to correct the location Point, p before calling findComponentAt(p) since the MouseAdapter will return Points relative to the JLayeredPane not the board JPanel.
例如:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class Chess2 {
private static void createAndShowUI() {
JFrame frame = new JFrame("Chess 2");
frame.getContentPane().add(new Chess2Gui().getMainComponent());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
class Chess2Gui {
private static final int RANKS = 8;
private static final int FILES = 8;
private static final Color DARK_COLOR = new Color(0, 100, 0);
private static final Color LIGHT_COLOR = new Color(200, 200, 200);
private static final Color DARK_PIECE_COLOR = Color.black;
private static final int SQR_WIDTH = 80;
private static final int PIECE_WIDTH = 60;
private static final Dimension SQR_SIZE = new Dimension(SQR_WIDTH, SQR_WIDTH);
private JLayeredPane mainLayeredPane = new JLayeredPane();
private JPanel board = new JPanel(new GridLayout(RANKS, FILES));
private JPanelSquare[][] jPanelSquareGrid = new JPanelSquare[RANKS][FILES];
public Chess2Gui() {
for (int rank = 0; rank < RANKS; rank++) {
for (int file = 0; file < FILES; file++) {
Color bkgd = DARK_COLOR;
if (rank % 2 == file % 2) {
bkgd = LIGHT_COLOR;
}
jPanelSquareGrid[rank][file] = new JPanelSquare(rank, file, bkgd);
jPanelSquareGrid[rank][file].setPreferredSize(SQR_SIZE);
board.add(jPanelSquareGrid[rank][file]);
}
}
board.setSize(board.getPreferredSize());
board.setLocation(0, 0);
mainLayeredPane.add(board, JLayeredPane.DEFAULT_LAYER);
mainLayeredPane.setPreferredSize(board.getPreferredSize());
ImageIcon icon = new ImageIcon(ImageUtils2.createImage(PIECE_WIDTH, DARK_PIECE_COLOR));
JLabel chessPiece = new JLabel(icon, SwingConstants.CENTER);
jPanelSquareGrid[1][3].add(chessPiece);
MyMouseAdapter mouseAdapter = new MyMouseAdapter();
mainLayeredPane.addMouseListener(mouseAdapter);
mainLayeredPane.addMouseMotionListener(mouseAdapter);
}
public JComponent getMainComponent() {
return mainLayeredPane;
}
private class MyMouseAdapter extends MouseAdapter {
private JLabel piece = null;
private Point delta = null;
private int oldRank = -1;
private int oldFile = -1;
@Override
public void mousePressed(MouseEvent e) {
Point p = e.getPoint();
Component c = board.getComponentAt(p);
for (int rank = 0; rank < jPanelSquareGrid.length; rank++) {
for (int file = 0; file < jPanelSquareGrid[rank].length; file++) {
if (jPanelSquareGrid[rank][file] == c) {
if (jPanelSquareGrid[rank][file].getChessPiece() != null) {
// the jPanelSquares are derived from JPanel but have a
// few of their own methods
piece = jPanelSquareGrid[rank][file].getChessPiece();
jPanelSquareGrid[rank][file].remove(piece);
oldRank = rank;
oldFile = file;
mainLayeredPane.add(piece, JLayeredPane.DRAG_LAYER);
int x = p.x - PIECE_WIDTH/2;
int y = p.y - PIECE_WIDTH/2;
piece.setLocation(x, y);
delta = new Point(p.x - x, p.y - y);
board.revalidate();
mainLayeredPane.repaint();
return;
}
}
}
}
oldFile = -1;
oldRank = -1;
}
@Override
public void mouseDragged(MouseEvent e) {
if (piece != null) {
Point p = e.getPoint();
int x = p.x - delta.x;
int y = p.y - delta.y;
piece.setLocation(x, y);
mainLayeredPane.revalidate();
mainLayeredPane.repaint();
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (piece != null) {
JPanelSquare sqr = (JPanelSquare) board.getComponentAt(e.getPoint());
mainLayeredPane.remove(piece);
if (sqr == null || !validMove(sqr)) {
jPanelSquareGrid[oldRank][oldFile].add(piece);
} else {
sqr.add(piece);
}
piece = null;
delta = null;
oldRank = -1;
oldFile = -1;
board.revalidate();
mainLayeredPane.repaint();
}
}
// just a pawn's moves
private boolean validMove(JPanelSquare sqr) {
int rank = sqr.getRank();
int file = sqr.getFile();
if (file != oldFile) {
return false;
}
if (oldRank == 1 && (rank != 2 && rank != 3)) {
return false;
}
if (oldRank != 1 && rank != oldRank + 1) {
return false;
}
return true;
}
}
}
@SuppressWarnings("serial")
class JPanelSquare extends JPanel {
private int rank;
private int file;
private JLabel chessPiece = null;
public JPanelSquare(int rank, int file, Color bkgrnd) {
this.rank = rank;
this.file = file;
setBackground(bkgrnd);
setLayout(new GridBagLayout());
}
public int getRank() {
return rank;
}
public int getFile() {
return file;
}
@Override
public Component add(Component c) {
chessPiece = (JLabel)c;
return super.add(c);
}
@Override
public void remove(Component comp) {
chessPiece = null;
super.remove(comp);
}
public JLabel getChessPiece() {
return chessPiece;
}
}
class ImageUtils2 {
public static BufferedImage createImage(int size, Color color) {
BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setColor(color);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.fillOval(size/3, 0, size/3, size/3);
g2.fillOval(size/4, size/4, size/2, 2*size/3);
g2.fillOval(size/6, 2*size/3, 2*size/3, size/2);
g2.dispose();
return img;
}
}
这篇关于是否将JLabel添加到JPanel“隐藏” JPanel?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!