如何使用swing类Java绘制网格并在单击和拖动时检测鼠标位置
我正在尝试使用Swing类创建一个网格UI(5*5)。我尝试了一个嵌套循环,并向jFrame动态添加了一个jPanel。我还尝试在用户点击并落在每个jPanel上时改变其背景颜色。 但是在我的代码中,每个单元格之间都有巨大的间隙,我无法让拖动事件正常工作如何使用swing类Java绘制网格并在单击和拖动时检测鼠标位置,java,swing,grid,jpanel,mouseover,Java,Swing,Grid,Jpanel,Mouseover,我正在尝试使用Swing类创建一个网格UI(5*5)。我尝试了一个嵌套循环,并向jFrame动态添加了一个jPanel。我还尝试在用户点击并落在每个jPanel上时改变其背景颜色。 但是在我的代码中,每个单元格之间都有巨大的间隙,我无法让拖动事件正常工作 public class clsCanvasPanel extends JPanel { private static final int intRows = 5; private static final int intCol
public class clsCanvasPanel extends JPanel {
private static final int intRows = 5;
private static final int intCols = 5;
private List<JPanel> jpllist = new ArrayList<JPanel>();
public clsCanvasPanel() {
/*
*
* Add eventListener to individual JPanel within CanvasPanel
*
*
* TODO :
* 1) mousePressed --> update Temperature and HeatConstant of clsElement Class
* 2) start a new thread and
* 3) call clsElement.run() method
*
*
* Right Now : it updates the colours of the JPanel
* */
MouseListener mouseListener = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
JPanel panel = (JPanel) e.getSource();
Component[] components = panel.getComponents();
for (Component component : components) {
component.setVisible(!component.isVisible());
component.setBackground(new Color(255,255,0));
}
panel.revalidate();
panel.repaint();
}
};
//TODO : refactoring
GridLayout gdlyPlates = new GridLayout();
gdlyPlates.setColumns(intCols);
gdlyPlates.setRows(intRows);
gdlyPlates.setHgap(0);
gdlyPlates.setVgap(0);
setLayout(gdlyPlates);
//TODO : refactoring
for (int row = 0; row < intRows; row++) {
for (int col = 0; col < intCols; col++) {
JPanel panel = new JPanel(new GridBagLayout());
panel.setOpaque(false);
JPanel jl = new JPanel();
jl.setVisible(true);
panel.add(jl);
panel.addMouseListener(mouseListener);
jpllist.add(panel);
add(panel);
}
}
}
}
public类clsCanvasPanel扩展了JPanel{
私有静态最终int intRows=5;
私有静态final int intCols=5;
private List jpllist=new ArrayList();
公共clsCanvasPanel(){
/*
*
*将eventListener添加到CanvasPanel中的单个JPanel
*
*
*待办事项:
*1)鼠标按下-->更新clsElement类的温度和热常数
*2)启动一个新线程并
*3)调用clsElement.run()方法
*
*
*现在:它更新了JPanel的颜色
* */
MouseListener MouseListener=新的MouseAdapter(){
@凌驾
公共无效鼠标按下(MouseEvent e){
JPanel面板=(JPanel)e.getSource();
Component[]components=panel.getComponents();
用于(组件:组件){
setVisible(!component.isVisible());
组件。立根(新颜色(255255,0));
}
panel.revalidate();
panel.repaint();
}
};
//TODO:重构
GridLayout gdlyPlates=新的GridLayout();
gdlyPlates.setColumns(intCols);
gdlyPlates.设置行(插入);
gdlyPlates.setHgap(0);
gdlyPlates.setVgap(0);
设置布局(gdlyPlates);
//TODO:重构
for(int行=0;行
所以现在我尝试创建一个面板,在上面画网格,然后检测鼠标在网格上的位置,进一步改变每个单元格的颜色
有没有人能给我一些建议,告诉我如何在JPanel上实现这个网格,以及如何更改所选单元格的颜色。根据您想要实现的目标,有很多方法可以实现这个功能 第一个示例仅使用2D Graphics API渲染单元格,并使用
MouseMotionListener
监视高亮显示的单元格
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
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.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestGrid01 {
public static void main(String[] args) {
new TestGrid01();
}
public TestGrid01() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private int columnCount = 5;
private int rowCount = 5;
private List<Rectangle> cells;
private Point selectedCell;
public TestPane() {
cells = new ArrayList<>(columnCount * rowCount);
MouseAdapter mouseHandler;
mouseHandler = new MouseAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
Point point = e.getPoint();
int width = getWidth();
int height = getHeight();
int cellWidth = width / columnCount;
int cellHeight = height / rowCount;
selectedCell = null;
if (e.getX() >= xOffset && e.getY() >= yOffset) {
int column = (e.getX() - xOffset) / cellWidth;
int row = (e.getY() - yOffset) / cellHeight;
if (column >= 0 && row >= 0 && column < columnCount && row < rowCount) {
selectedCell = new Point(column, row);
}
}
repaint();
}
};
addMouseMotionListener(mouseHandler);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
public void invalidate() {
cells.clear();
selectedCell = null;
super.invalidate();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int width = getWidth();
int height = getHeight();
int cellWidth = width / columnCount;
int cellHeight = height / rowCount;
int xOffset = (width - (columnCount * cellWidth)) / 2;
int yOffset = (height - (rowCount * cellHeight)) / 2;
if (cells.isEmpty()) {
for (int row = 0; row < rowCount; row++) {
for (int col = 0; col < columnCount; col++) {
Rectangle cell = new Rectangle(
xOffset + (col * cellWidth),
yOffset + (row * cellHeight),
cellWidth,
cellHeight);
cells.add(cell);
}
}
}
if (selectedCell != null) {
int index = selectedCell.x + (selectedCell.y * columnCount);
Rectangle cell = cells.get(index);
g2d.setColor(Color.BLUE);
g2d.fill(cell);
}
g2d.setColor(Color.GRAY);
for (Rectangle cell : cells) {
g2d.draw(cell);
}
g2d.dispose();
}
}
}
在MuleMeRever方法中的Mouististor示例中,您可能需要考虑XOffice/YOffice,以获得更平滑的小区识别。
int column = (x - xOffset) / cellWidth;
int row = (y - yOffset) / cellHeight;
我不喜欢渲染边框,因为在网格内,如果有超过示例的边框,则会复制一些边框。我认为这个解决方案更好:
private int width;
private int height;
// ...
for (int row = 0; row <= this.height; row++) {
for (int col = 0; col <= this.width; col++) {
gbc.gridx = col;
gbc.gridy = row;
CellPane cellPane = new CellPane();
Border border = new MatteBorder(1, 1, (row == this.height ? 1 : 0), (col == this.width ? 1 : 0), Color.GRAY);
cellPane.setBorder(border);
this.add(cellPane, gbc);
}
}
private int-width;
私人内部高度;
// ...
对于(int row=0;row你好,我意识到这是一篇非常古老的帖子。嘿@MadProgrammer,你的代码太棒了!我抓起它来修补我的作业,但我有点为难,这正是我需要的,但我需要使窗口1080x760,有1700个单元格,每个单元格都是20x20。现在我已经重新划分了窗口,并制作了1700个单元格,我遇到的问题是,当我尝试将单元格大小调整为20x20时,鼠标侦听器会发疯,无法正常工作……我尝试过更改cellWidth和cellHeight变量……但效果不太好……有什么想法吗?@Twhite1195哪个版本,第一个还是第二个?@MadProgrammer first,第二个非常有效。。。直到我调整了cells@Twhite1195你的columnCount
和rowCount
值是多少?@MadProgrammercolumnCount
是50,而rowCount
是36。你能回答一下为什么你的解决方案能解决这个问题吗?
private int width;
private int height;
// ...
for (int row = 0; row <= this.height; row++) {
for (int col = 0; col <= this.width; col++) {
gbc.gridx = col;
gbc.gridy = row;
CellPane cellPane = new CellPane();
Border border = new MatteBorder(1, 1, (row == this.height ? 1 : 0), (col == this.width ? 1 : 0), Color.GRAY);
cellPane.setBorder(border);
this.add(cellPane, gbc);
}
}