簡體   English   中英

使用帶有 Swing 的鼠標繪制(單色)數組的最簡單方法是什么?

[英]What's the easiest way to draw a (monochrome) array using a mouse with Swing?

我一直在尋找一種在屏幕上繪制黑白數組的方法。 這是一個簡單的數組,只有 20x20。 我打算做的是用鼠標在數組上繪制,以便每個像素在單擊時從黑色“切換”到白色並返回,然后將數組作為一組布爾值(或整數)傳遞給另一個函數。 目前我正在使用 Swing。 我記得曾經使用 Swing 在畫布上繪圖,但我仍然找不到實際用法。 我應該使用畫布,還是依賴 JToggleButtons?

您可以簡單地使用JFrame (或其他 Swing 組件)並覆蓋paint(Graphics)方法來繪制布爾矩陣的表示(請注意,對於像JPanel這樣的輕量級組件,您應該覆蓋paintComponent(Graphics) 。這將為您提供所需的單擊和拖動功能(使用單個 Swing 組件的網格很難實現)。

正如其他人評論的那樣,AWT Canvas不會為您提供 Swing 組件未提供的任何內容,您將在下面的示例中看到,我使用了JFrame上也存在的createBufferStrategy方法來確保非閃爍顯示。

笑臉

請注意,我的示例相當簡單,因為它切換您拖動的每個像素,而不是單擊操作確定您是處於“繪畫”模式還是“擦除”模式,然后在拖動期間專門應用黑色或白色像素.

public class Grid extends JFrame {
    private static final int SCALE = 10; // 1 boolean value == 10 x 10 pixels.
    private static final int SIZE = 20;

    private boolean[][] matrix = new boolean[SIZE][SIZE];
    private boolean painting;
    private int lastX = -1;
    private int lastY = -1;

    public Grid() throws HeadlessException {
        setPreferredSize(new Dimension(SIZE * SCALE, SIZE * SCALE));
        setResizable(false);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setBackground(Color.WHITE);

        addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                painting = true;
                tryAdjustValue(e.getPoint());
            }

            public void mouseReleased(MouseEvent e) {
                painting = false;
                lastX = -1;
                lastY = -1;
            }
        });

        addMouseMotionListener(new MouseMotionListener() {
            public void mouseDragged(MouseEvent e) {
                tryAdjustValue(e.getPoint());
            }

            public void mouseMoved(MouseEvent e) {
                tryAdjustValue(e.getPoint());
            }
        });
    }

    private void tryAdjustValue(Point pt) {
        int newX = pt.x / SCALE;
        int newY = pt.y / SCALE;

        if (painting && isInRange(newX) && isInRange(newY) && (newX != lastX || newY != lastY)) {
            // Only invert "pixel" if we're currently in painting mode, both array indices are valid
            // and we're not attempting to adjust the same "pixel" as before (important for drag operations).
            matrix[newX][newY] = !matrix[newX][newY];
            lastX = newX;
            lastY = newY;
            repaint();
        }
    }

    private boolean isInRange(int val) {
        return val >= 0 && val < SIZE;
    }

    public void paint(Graphics g) {
        super.paint(g);

        for (int x=0; x<SIZE; ++x) {
            for (int y=0; y<SIZE; ++y) {
                if (matrix[x][y]) {
                    g.fillRect(x * SCALE, y * SCALE, SCALE, SCALE);
                }
            }
        }
    }

    public static void main(String[] args) {
        Grid grid = new Grid();
        grid.pack();
        grid.setLocationRelativeTo(null);
        grid.createBufferStrategy(2);
        grid.setVisible(true);
    }
}

為什么不將簡單的 20 x 20 網格 JPanel 保存在 GridLayout(20, 20) 中,並在通過 MouseListener 的 mousePressed 方法單擊時翻轉面板的背景顏色。 您可以將面板保存在二維數組中,並在需要時查詢它們的背景顏色。

您也可以為此使用 JLabels,但您必須記住將它們的不透明屬性設置為 true。 JButton 或 JToggleButton 也可以工作,......選項幾乎是無限的。 我不建議您使用 AWT(畫布),因為它們不需要在功能上退步,因為 Swing 處理得很好。

如果您遇到了這個問題,為什么不回來向我們展示您的代碼,我們將更好地為您提供更具體的幫助。

解決此問題的另一種方法是使用單個 JPanel 並覆蓋其paintComponent 方法。 你可以給它一個 int[][] 數組作為它的模型,然后在paintComponent方法中根據模型的狀態繪制任何所需顏色的矩形。 然后給它一個 MouseListener 來改變模型的狀態並調用重繪。

例如,

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

@SuppressWarnings("serial")
public class BlackWhiteGridPanel extends JPanel {
   // can have multiple colors if desired
   // public static final Color[] COLORS = {Color.black, Color.red, Color.blue, Color.white}; 
   public static final Color[] COLORS = {Color.black, Color.white};
   public static final int SIDE = 20;
   private static final int BWG_WIDTH = 400;
   private static final int BWG_HEIGHT = BWG_WIDTH;

   private int[][] model = new int[SIDE][SIDE]; // filled with 0's.

   public BlackWhiteGridPanel() {
      addMouseListener(new MouseAdapter() {
         @Override
         public void mousePressed(MouseEvent e) {
            myMousePressed(e);
         }
      });
   }

   private void myMousePressed(MouseEvent e) {
      // find relative position of mouse press on grid.
      int i = (e.getX() * SIDE) / getWidth();
      int j = (e.getY() * SIDE) / getHeight();

      int value = model[i][j];
      // the model can only hold states allowed by the COLORS array. 
      // So if only two colors, then value can only be 0 or 1.
      value = (value + 1) % COLORS.length;
      model[i][j] = value;
      repaint();
   }

   public int[][] getModel() {
      // return a copy of model so as not to risk corruption from outside classes 
      int[][] copy = new int[model.length][model[0].length];
      for (int i = 0; i < copy.length; i++) {
         System.arraycopy(model[i], 0, copy[i], 0, model[i].length);
      }
      return copy;
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      int width = getWidth();
      int ht = getHeight();
      for (int i = 0; i < model.length; i++) {
         for (int j = 0; j < model[i].length; j++) {
            Color c = COLORS[model[i][j]];
            g.setColor(c);
            int x = (i * width) / SIDE;
            int y = (j * ht) / SIDE;
            int w = ((i + 1) * width) / SIDE - x;
            int h = ((j + 1) * ht) / SIDE - y;
            g.fillRect(x, y, w, h);
         }
      }
   }

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

   private static void createAndShowGui() {
      BlackWhiteGridPanel mainPanel = new BlackWhiteGridPanel();

      JFrame frame = new JFrame("BlackWhiteGrid");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM