如何使用swing class Java绘制网格,并在单击并拖动时检测鼠标位置 [英] How to draw grid using swing class Java and detect mouse position when click and drag

查看:115
本文介绍了如何使用swing class Java绘制网格,并在单击并拖动时检测鼠标位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Swing类创建网格UI(5 * 5)。我尝试了一个嵌套循环,并动态添加jPanel到jFrame。而且我还尝试在用户点击并下降时更改每个jPanel的背景颜色。
但是在我的代码中,每个单元格之间存在巨大的差距,我无法使拖动事件发挥作用。

  public class clsCanvasPanel extends JPanel {
private static final int intRows = 5;
private static final int intCols = 5;
私人列表< JPanel> jpllist = new ArrayList< JPanel>();

public clsCanvasPanel(){
/ *
*
*将eventListener添加到CanvasPanel中的单个JPanel
*
*
* TODO:
* 1)mousePressed - >更新clsElement Class的温度和HeatConstant
* 2)启动一个新线程和
* 3)调用clsElement.run()方法
*
*
*立即:它更新JPanel的颜色
* * /
MouseListener mouseListener = new MouseAdapter(){
@Override
public void mousePressed(MouseEvent e){
JPanel panel =(JPanel)e.getSource();

Component []组件= panel.getComponents();
for(Component component:components){
component.setVisible(!component.isVisible());
component.setBackground(new Color(255,255,0));
}
panel.revalidate();
panel.repaint();
}
};

// TODO:重构
GridLayout gdlyPlates = new GridLayout();
gdlyPlates.setColumns(intCols);
gdlyPlates.setRows(intRows);
gdlyPlates.setHgap(0);
gdlyPlates.setVgap(0);
setLayout(gdlyPlates);
$ b $ // TODO:重构
(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);
}
}
}
}

现在我正在尝试创建一个面板并在其上绘制网格,然后检测网格上的鼠标位置,进一步更改每个单元格的颜色。



有人可以给我一些关于如何在JPanel上实现这个网格的建议,以及改变所选单元格的颜色。

解决方案

根据你想要达到的目标,这些方法可以起作用。

这第一个例子简单地使用2D图形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){
TestGrid01();

$ b $ public TestGrid01(){
EventQueue.invokeLater(new Runnable(){
@Override
public void run(){
尝试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch(ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex){
}

JFrame框架= 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 {
$ b $ private int columnCount = 5;
private int rowCount = 5;
私人列表< Rectangle>细胞;
私人点selectedCell;
$ b $ 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; (e.getX()> = xOffset& e.getY()> = yOffset){

int column =(e.getX() - xOffset) / cellWidth;
int row =(e.getY() - yOffset)/ cellHeight; (列> = 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; (int col = 0; col< 0; row< rowCount; row ++){
for(cells.isEmpty()){
for(int row = 0; row< rowCount; 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();





这个例子确实调整了网格的大小与窗口,但这将是一个微不足道的变化,使细胞的大小固定。



查看 2D Graphics 了解更多详情

更新组件示例



这个例子使用一系列 JPanel 来表示每个单元格。



每个单元格的宽度和高度都是固定的,并且不会在主窗口中调整大小。 i.stack.imgur.com/UzgS1.pngalt =

在这个例子中,每个单元面板都有它自己的鼠标监听器。对代码进行重新编码并不会太困难,因此主面板只有一个鼠标监听器,而是自己管理工作负载。

  import java.awt.BorderLayout; 
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
import javax.swing.border.MatteBorder;

public class TestGrid02 {

public static void main(String [] args){
new TestGrid02();

$ b $ public TestGrid02(){
EventQueue.invokeLater(new Runnable(){
@Override
public void run(){
尝试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch(ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex){
}

JFrame框架= 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 {
$ b $ public TestPane(){
setLayout(new GridBagLayout());

GridBagConstraints gbc = new GridBagConstraints(); (int col = 0; col <5; col ++){
gbc.gridx = col;
for(int row = 0; row< 5; row ++)
gbc.gridy = row;

CellPane cellPane = new CellPane();
Border border = null; (行<4){
if(col <4){
border = new MatteBorder(1,1,0,0,Color.GRAY);
if
} else {
border = new MatteBorder(1,1,0,1,Color.GRAY);

} else {
if(col <4){
border = new MatteBorder(1,1,1,0,Color.GRAY);
} else {
border = new MatteBorder(1,1,1,Color.GRAY);
}
}
cellPane.setBorder(border);
add(cellPane,gbc);




$ b public class CellPane extends JPanel {

private color defaultBackground;

public CellPane(){
addMouseListener(new MouseAdapter(){
@Override
public void mouseEntered(MouseEvent e){
defaultBackground = getBackground );
setBackground(Color.BLUE);
}

@Override
public void mouseExited(MouseEvent e){
setBackground(defaultBackground);
}
});
}

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


I am trying to create a grid UI (5*5) using Swing classes. I tried a nested loop and adding a jPanel dynamically to the jFrame. And I also tried to change the background colour of each jPanel when user clicks and drops over it. But with my code there are huge gaps between each cell and I can't get the drag event to work.

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);
              }
           }
    }
}

So now I am trying to create one panel and draw grids on it, then detects the mouse position on the grid, further change the colour of each cell.

Could someone give me some advices on how to implement this grid on JPanel, and change the colour of a chosen cell.

解决方案

There are any number of ways to get this to work, depending on what it is you want to achieve.

This first example simply uses the 2D Graphics API to render the cells and a MouseMotionListener to monitor which cell is highlighted.

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();
        }
    }
}

This example does resize the grid with the window, but it would be a trivial change to make the cells fixed size.

Check out 2D Graphics for more details

Update with component example

This example uses a series of JPanels to represent each cell.

Each cell is defined with a fixed width and height and do not resize with the main window.

In this example, each cell panel has it's own mouse listener. It wouldn't be overly difficult to re-code it so that the main panel had a single mouse listener and managed the work load itself instead.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
import javax.swing.border.MatteBorder;

public class TestGrid02 {

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

    public TestGrid02() {
        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 {

        public TestPane() {
            setLayout(new GridBagLayout());

            GridBagConstraints gbc = new GridBagConstraints();
            for (int row = 0; row < 5; row++) {
                for (int col = 0; col < 5; col++) {
                    gbc.gridx = col;
                    gbc.gridy = row;

                    CellPane cellPane = new CellPane();
                    Border border = null;
                    if (row < 4) {
                        if (col < 4) {
                            border = new MatteBorder(1, 1, 0, 0, Color.GRAY);
                        } else {
                            border = new MatteBorder(1, 1, 0, 1, Color.GRAY);
                        }
                    } else {
                        if (col < 4) {
                            border = new MatteBorder(1, 1, 1, 0, Color.GRAY);
                        } else {
                            border = new MatteBorder(1, 1, 1, 1, Color.GRAY);
                        }
                    }
                    cellPane.setBorder(border);
                    add(cellPane, gbc);
                }
            }
        }
    }

    public class CellPane extends JPanel {

        private Color defaultBackground;

        public CellPane() {
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseEntered(MouseEvent e) {
                    defaultBackground = getBackground();
                    setBackground(Color.BLUE);
                }

                @Override
                public void mouseExited(MouseEvent e) {
                    setBackground(defaultBackground);
                }
            });
        }

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

这篇关于如何使用swing class Java绘制网格,并在单击并拖动时检测鼠标位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆