Java - 使用带有鼠标交互式JPanel的GridLayout创建JFrame

时间:2015-05-20 17:31:18

标签: java swing jpanel mouselistener

(初级)
嗨,对不起具体的问题,但是我有错误不断地用一个我希望非常简单的程序埋伏我。

我计划创建一个程序,允许用户在GridLayout中单击JPanels以更改其颜色。想象一个穷人的像素艺术节目,就像旧的MS Paint一样 计划是创建一个设置为GridLayout的JFrame,它具有整数宽度和高度,并使用带有2d数组和for循环的JPanels填充网格。然后我会将一个MouseListener放入每个单独的JPanel中以监听mouseClicked,这将改变所点击面板的背景颜色。

package pixelpainter;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
import static javax.swing.JFrame.EXIT_ON_CLOSE;

public class PixelPainter extends JPanel {
int width = 20;
int height = 20;
int pixSize = 10;
Color bGColor = Color.WHITE;
Dimension pixDim = new Dimension(pixSize,pixSize);
private JPanel panelClicked = null;
JFrame frame= new JFrame();

/**
 * @param args the command line arguments
 */
public PixelPainter()
{
    initGUI();
}

public void initGUI() {

    frame.setLayout(new GridLayout(height, width, 0, 0));
    frame.setSize((height * pixSize), (width * pixSize));
    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
    int[][] pixGrid = new int [width][height];

    for (int row = 0; row < height; row++)
    {
        for (int col = 0; col < width; col++)
        {
            JPanel pixel[][] = new JPanel[width][height];
            frame.add(pixel[row][col]);
            pixel[row][col].setBackground(bGColor);
            pixel[row][col].setPreferredSize(pixDim);
            pixel[row][col].setBorder(BorderFactory.createLineBorder(Color.BLACK));
            pixel[row][col].addMouseListener(new MouseAdapter()
            {
                @Override
                public void mouseClicked(MouseEvent click)
                {
                    JPanel selectedPixel = (JPanel) getComponentAt(click.getPoint());
                    if (selectedPixel == null || selectedPixel == PixelPainter.this)
                    {
                        return;
                    }
                    if (selectedPixel != null)
                    {
                        selectedPixel.setBackground(Color.BLACK);
                    }
                }
                @Override
                public void mousePressed(MouseEvent press)
                {

                }
            });
        }
    }
}

public static void main(String[] args){
    EventQueue.invokeLater(new Runnable(){
        @Override
                public void run(){
                    new PixelPainter().setVisible(true);
                }
            });     
    }

}

理想情况下,我会在填充颜色时使用2d数组JFrame,但显然它们必须是最终的或有效的最终。

2 个答案:

答案 0 :(得分:2)

我重新安排了你的代码,将它们组合在一起。

这是我创建的GUI。

Pixel Art GUI

我对您的代码进行了以下更改。

  1. 我有主类实现Runnable。由于EventQueue invokeLater方法需要Runnable,因此您也可以将主类设为Runnable。

  2. 我将JPanel创建移动到了createPixels方法中。你的方法应该做一件事,做好一件事。

  3. initGUI方法现在只创建JFrame。

  4. 我将大小整数移动到新的PixelPanel类中。扩展JPanel的类必须提供首选大小。然后,JFrame pack方法创建一个正确大小的JFrame。

  5. 在PixelPanel类的paintComponent方法中,我所做的只是绘画。除了在paintComponent方法中绘制外,您不应该做任何其他事情。

  6. 我将像素设置得更大,因此我可以更容易地点击并右键点击像素。左键单击使像素变为蓝色,右键单击则会删除蓝色(使像素变为白色)。

  7. 由于model / view / controller pattern,我将鼠标适配器代码拉入其自己的类中。分离关注点使得GUI的每个部分都能够更加轻松地工作。

  8. 这是代码。

    package com.ggl.testing;
    
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.GridLayout;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    
    import javax.swing.BorderFactory;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    public class PixelPainter implements Runnable {
    
        private JFrame frame;
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new PixelPainter());
        }
    
        @Override
        public void run() {
            initGUI();
        }
    
        public void initGUI() {
            frame = new JFrame("Pixel Art");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            frame.add(createPixels());
    
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        private JPanel createPixels() {
            int width = 30;
            int height = 20;
    
            JPanel panel = new JPanel();
            panel.setLayout(new GridLayout(height, width, 0, 0));
    
            for (int row = 0; row < height; row++) {
                for (int column = 0; column < width; column++) {
                    PixelPanel pixelPanel = new PixelPanel();
                    pixelPanel.addMouseListener(new ColorListener(pixelPanel));
                    panel.add(pixelPanel);
                }
            }
    
            return panel;
        }
    
        public class PixelPanel extends JPanel {
    
            private static final long serialVersionUID = 8465814529701152253L;
    
            private static final int PIXEL_SIZE = 20;
    
            private Color backgroundColor;
    
            public PixelPanel() {
                this.backgroundColor = Color.WHITE;
                this.setBorder(BorderFactory.createLineBorder(Color.BLACK));
                this.setPreferredSize(new Dimension(PIXEL_SIZE, PIXEL_SIZE));
            }
    
            public Color getBackgroundColor() {
                return backgroundColor;
            }
    
            public void setBackgroundColor(Color backgroundColor) {
                this.backgroundColor = backgroundColor;
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
    
                g.setColor(getBackgroundColor());
                g.fillRect(0, 0, getWidth(), getHeight());
            }
        }
    
        public class ColorListener extends MouseAdapter {
    
            private PixelPanel panel;
    
            public ColorListener(PixelPanel panel) {
                this.panel = panel;
            }
    
            @Override
            public void mousePressed(MouseEvent event) {
                if (event.getButton() == MouseEvent.BUTTON1) {
                    panel.setBackgroundColor(Color.BLUE);
                    panel.repaint();
                } else if (event.getButton() == MouseEvent.BUTTON3) {
                    panel.setBackgroundColor(Color.WHITE);
                    panel.repaint();
                }
            }
        }
    
    }
    

答案 1 :(得分:1)

您的代码正在循环中创建一个新的像素阵列。我的想法是在loo中创建Array out,然后创建一个新的JPanel以添加到循环内的Array。

类似的东西:

int[][] pixGrid = new int [width][height];
JPanel pixel[][] = new JPanel[width][height];

 //JPanel pixel[][] = new JPanel[width][height];
 pixel[row][col] = new JPanel();

现在在侦听器中,因为您将侦听器添加到每个面板,您可以直接访问该面板而无需担心鼠标点:

 //JPanel selectedPixel = (JPanel) getComponentAt(click.getPoint());
 JPanel selectedPixel = (JPanel)click.getSource();

实际上,您可以创建一个MouseListener来添加到每个面板,而不是为每个面板创建不同的侦听器,因为上面的代码是通用的。