Какой самый простой способ нарисовать (монохромный) массив, используя мышь с Swing? - PullRequest
2 голосов
/ 04 октября 2011

Я искал способ нарисовать черно-белый массив на экране. Это простой массив, всего 20х20. Я планирую нарисовать массив с помощью мыши, чтобы каждый пиксель «переключался» с черного на белый и обратно при нажатии, а затем передавал массив как набор логических значений (или целых чисел) другой функции. В настоящее время я использую Swing. Я помню, что использовал Swing для рисования на холсте, но я все еще не могу найти фактическое использование. Стоит ли использовать холст или вместо этого полагаться на JToggleButtons?

Ответы [ 2 ]

5 голосов
/ 04 октября 2011

Вы можете просто использовать JFrame (или другой компонент Swing) и переопределить метод paint(Graphics), чтобы нарисовать представление логической матрицы (обратите внимание, что в случае облегченного компонента, такого как JPanel, вы должны переопределитьpaintComponent(Graphics). Это даст вам необходимую возможность щелкать и перетаскивать (что очень трудно сделать, используя сетку отдельных компонентов Swing).

Как прокомментировали другие люди, AWT Canvas не делаетне предоставит вам ничего, что не предоставляется компонентами Swing, и вы увидите в примере ниже, что я использовал метод createBufferStrategy, также присутствующий в JFrame, чтобы обеспечить отображение без мерцания.

smiley face

Обратите внимание, что мой пример довольно прост в том, что он переключает каждый пиксель, по которому вы перетаскиваете, а не операцию щелчка, определяющую, находитесь ли вы в режиме «рисования» или в режиме «стирания», а затем применяете только черныйбелые пиксели на время перетаскивания.

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);
    }
}
3 голосов
/ 04 октября 2011

Почему бы не использовать простую сетку JPanel размером 20 x 20 в GridLayout (20, 20) и перевернуть цвет фона панели, если щелкнуть с помощью метода MousePistener mousePressed.Вы можете удерживать панели в 2D-массиве и запрашивать их цвет фона всякий раз, когда в этом возникает необходимость.

Вы также можете использовать JLabels для этого, но вам придется помнить, что их непрозрачные свойства должны иметь значение true.JButton будет работать так же хорошо, как JToggleButton, ... варианты практически безграничны.Однако я не рекомендую вам использовать AWT (Canvas), так как им нет необходимости отступать по функциональности, поскольку 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();
         }
      });
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...