有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

swing Java使用GridLayout和鼠标交互式JPanel创建JFrame

(初学者)
您好,很抱歉问您一个具体的问题,但我一直在用一个我认为非常简单的程序,不知从哪里冒出错误来埋伏我

我计划创建一个程序,允许用户在GridLayout中单击JPanel,以更改其颜色。想象一下一个穷人的像素艺术程序,比如旧的MS画作
计划是将JFrame设置为GridLayout,宽度和高度均为整数,并用一个2d数组和一个for循环填充网格。然后,我会在每个单独的JPanel中放一个鼠标听筒,听是否有鼠标点击,这会改变点击面板的背景颜色

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) 个答案

  1. # 1 楼答案

    我重新整理了你的代码,把类似的东西组合在一起

    这是我创建的GUI

    Pixel Art GUI

    我对你的代码做了以下更改

    1. 我让主类实现可以运行。由于EventQueue invokeLater方法需要一个可运行的类,因此您不妨将主类设置为可运行的

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

    3. initGUI方法现在只创建JFrame

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

    5. 在PixelPanel类的paintComponent方法中,我所做的就是绘制。除了使用paintComponent方法进行绘制外,不应执行其他任何操作

    6. 我把像素变大了,这样我可以左键点击和右键点击一个像素更容易。左键单击会使像素变为蓝色,右键单击会擦除蓝色(使像素变为白色)

    7. 由于model / view / controller pattern,我将鼠标适配器代码拉入了它自己的类中。分离关注点可以使GUI的每个部分正常工作变得更容易

    这是代码

    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();
                }
            }
        }
    
    }
    
  2. # 2 楼答案

    您的代码正在循环中创建一个新的像素阵列。这个想法是在loo外面创建一个数组,然后创建一个新的JPanel添加到循环内部的数组中

    比如:

    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来添加到每个面板,而不是为每个面板创建不同的侦听器,因为上面的代码是通用的