Абсолютное позиционирование Графический JPanel внутри JFrame, заблокированный пустыми разделами

Я пытаюсь улучшить свое понимание Java, особенно Java GUI, путем создания головоломки. В настоящее время пользователь выбирает изображение, которое разрезается на указанное количество частей. Части рисуются случайным образом на экране, но они, кажется, покрыты пустым участком других частей, и не все из них появляются, но я могу распечатать все координаты. Я использую абсолютное позиционирование, потому что LayoutManager, похоже, не работает. Я кратко попробовал слоистые панели, но они смутили меня и, похоже, не решили проблему. Я бы очень признателен за помощь.
Вот два соответствующих classа:

import javax.swing.*; import java.awt.*; import java.awt.image.*; import java.awt.event.*; public class PuzzlePieceDriver extends JFrame { private static Dimension SCREENSIZE = Toolkit.getDefaultToolkit().getScreenSize(); private static final int HEIGHT = SCREENSIZE.height; private static final int WIDTH = SCREENSIZE.width; public static int MY_WIDTH; public static int MY_HEIGHT; private static BufferedImage image; private int xPieces = PuzzleMagicDriver.getXPieces(); private int yPieces = PuzzleMagicDriver.getYPieces(); private PuzzlePiece[] puzzle = new PuzzlePiece[xPieces*yPieces]; public Container pane = this.getContentPane(); private JLayeredPane layeredPane = new JLayeredPane(); public PuzzlePieceDriver(ImageIcon myPuzzleImage) { MY_WIDTH = myPuzzleImage.getIconWidth()+(int)myPuzzleImage.getIconHeight()/2; MY_HEIGHT = myPuzzleImage.getIconHeight()+(int)myPuzzleImage.getIconHeight()/2; setTitle("Hot Puzz"); setSize(MY_WIDTH,MY_HEIGHT); setLocationByPlatform(true); pane.setLayout(null); image = iconToImage(myPuzzleImage); //pass image into bufferedImage form puzzle = createClip(image); //pane.add(layeredPane); setVisible(true); }//end constructor public static BufferedImage iconToImage(ImageIcon icon) { Image img = icon.getImage(); int w = img.getWidth(null); int h = img.getHeight(null); BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics g = image.createGraphics(); // Paint the image onto the buffered image g.drawImage(img, 0, 0, null); g.dispose(); return image; }//end BufferedImage protected int randomNumber(int min, int max) { int temp = min + (int)(Math.random() * ((max - min) + 1)); return temp; }//end randomNumber private PuzzlePiece[] createClip(BufferedImage passedImage) { int cw, ch; int w,h; w = image.getWidth(null); h = image.getHeight(null); cw = w/xPieces; ch = h/yPieces; int[] cells=new int[xPieces*yPieces]; int dx, dy; BufferedImage clip = passedImage; //layeredPane.setPreferredSize(new Dimension(w,h)); for (int x=0; x<xPieces; x++) { int sx = x*cw; for (int y=0; y<yPieces; y++) { int sy = y*ch; int cell = cells[x*xPieces+y]; dx = (cell / xPieces) * cw; dy = (cell % yPieces) * ch; clip= passedImage.getSubimage(sx, sy, cw, ch); int myX = randomNumber(0,(int)w); int myY = randomNumber(0,(int)h); PuzzlePiece piece=new PuzzlePiece(clip,myX,myY); puzzle[x*xPieces+y]=piece; piece.setBounds(myX,myY,w,h); //layeredPane.setBounds(myX,myY,w,h); //layeredPane.add(piece,new Integer(x*xPieces+y)); pane.add(piece); piece.repaint(); }//end nested for }//end for return puzzle; }//end createClip }//end class 

Извините, если промежуток немного испорчен!

 import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; public class PuzzlePiece extends JPanel { private Point imageCorner; //the image's top-left corner location private Point prevPt; //mouse location for previous event private Boolean insideImage =false; private BufferedImage image; public PuzzlePiece(BufferedImage clip, int x, int y) { image = clip; imageCorner = new Point(x,y); //repaint(); }//end constructor public void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(image, (int)getImageCornerX(),(int)getImageCornerY(), this); System.out.println("paint "+getImageCornerX()+" "+getImageCornerY()); //repaint(); //g.dispose(); }//end paintComponent public Point getImageCorner() { return imageCorner; }//end getImageCorner public double getImageCornerY() { return imageCorner.getY(); }//end getImageCornerY public double getImageCornerX() { return imageCorner.getX(); }//end getPoint }//end class PuzzlePiece 

Любая помощь будет оценена, я действительно застрял! Благодаря!!

3 Solutions collect form web for “Абсолютное позиционирование Графический JPanel внутри JFrame, заблокированный пустыми разделами”

Я был очень заинтригован этой идеей, поэтому я сделал еще один пример, используя собственный менеджер макетов.

 public class MyPuzzelBoard extends JPanel { public static final int GRID_X = 4; public static final int GRID_Y = 4; private BufferedImage image; public MyPuzzelBoard(BufferedImage image) { setLayout(new VirtualLayoutManager()); setImage(image); addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { removeAll(); generatePuzzel(); } else { Component comp = getComponentAt(e.getPoint()); if (comp != null && comp != MyPuzzelBoard.this) { setComponentZOrder(comp, 0); invalidate(); revalidate(); repaint(); } } } }); } public void setImage(BufferedImage value) { if (value != image) { image = value; removeAll(); generatePuzzel(); } } public BufferedImage getImage() { return image; } protected float generateRandomNumber() { return (float) Math.random(); } protected void generatePuzzel() { BufferedImage image = getImage(); if (image != null) { int imageWidth = image.getWidth(); int imageHeight = image.getHeight(); int clipWidth = imageWidth / GRID_X; int clipHeight = imageHeight / GRID_Y; for (int x = 0; x < GRID_X; x++) { for (int y = 0; y < GRID_Y; y++) { float xPos = generateRandomNumber(); float yPos = generateRandomNumber(); Rectangle bounds = new Rectangle((x * clipWidth), (y * clipHeight), clipWidth, clipHeight); MyPiece piece = new MyPiece(image, bounds); add(piece, new VirtualPoint(xPos, yPos)); } } } invalidate(); revalidate(); repaint(); } public class VirtualPoint { private float x; private float y; public VirtualPoint(float x, float y) { this.x = x; this.y = y; } public float getX() { return x; } public float getY() { return y; } public void setX(float x) { this.x = x; } public void setY(float y) { this.y = y; } } public class VirtualLayoutManager implements LayoutManager2 { private Map mapConstraints; public VirtualLayoutManager() { mapConstraints = new WeakHashMap<>(25); } @Override public void addLayoutComponent(Component comp, Object constraints) { if (constraints instanceof VirtualPoint) { mapConstraints.put(comp, (VirtualPoint) constraints); } } @Override public Dimension maximumLayoutSize(Container target) { return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } @Override public float getLayoutAlignmentX(Container target) { return 0.5f; } @Override public float getLayoutAlignmentY(Container target) { return 0.5f; } @Override public void invalidateLayout(Container target) { } @Override public void addLayoutComponent(String name, Component comp) { } @Override public void removeLayoutComponent(Component comp) { mapConstraints.remove(comp); } @Override public Dimension preferredLayoutSize(Container parent) { return new Dimension(400, 400); } @Override public Dimension minimumLayoutSize(Container parent) { return preferredLayoutSize(parent); } @Override public void layoutContainer(Container parent) { int width = parent.getWidth(); int height = parent.getHeight(); for (Component comp : parent.getComponents()) { VirtualPoint p = mapConstraints.get(comp); if (p != null) { int x = Math.round(width * p.getX()); int y = Math.round(height * p.getY()); Dimension size = comp.getPreferredSize(); x = Math.min(x, width - size.width); y = Math.min(y, height - size.height); comp.setBounds(x, y, size.width, size.height); } } } } } 

В основном это использует «виртуальную» систему координат, где вместо того, чтобы подавать абсолютные позиции x / y в пикселях, вы предоставляете их в процентах от родительского контейнера. Теперь, если честно, не нужно много переводить обратно в абсолютное позиционирование, именно так вы также получите масштабирование макета.

В этом примере также показана Z-запись (на всякий случай), а двойной щелчок – простая повторная рандомизация головоломки

О, я также сделал кусок прозрачным ( opaque = false )

Рандомизированное расположение

О, одна вещь, которую я должен упомянуть, проходя через этот пример, я обнаружил, что можно было отделить фигуры от экрана (полностью и частично).

Вы можете проверить свой код позиционирования, чтобы убедиться, что изображения, когда они выложены, не были удалены с экрана;)

Попробуйте использовать setBorder(new LineBorder(Color.RED)) в своем конструкторе кусочка головоломки, чтобы увидеть, где находятся границы ваших головоломок. Если они там, где вы ожидаете, что это будет, вероятно, ваше позиционирование неверно. Также сделайте, чтобы ваши кусочки головоломки расширяли JComponent или использовали setOpaque(false) если вы расширяете JPanel .

Есть много предложений, которые я хотел бы сделать, но сначала …

То, как вы выбираете случайную позицию, отключено …

 int myX = randomNumber(0,(int)w); int myY = randomNumber(0,(int)h); 

Это позволяет создавать дублирующиеся позиции (и накладывать ячейки)

ОБНОВЛЕНИЯ (с использованием диспетчера компоновки)

Хорошо, так что это небольшое изменение в парадигме. Вместо того, чтобы создать клип и передать его в кусок, я позволил куску сделать выбор о том, как он собирается сделать кусок. Вместо этого я передал ему Rectangle, за который он отвечал.

Это означает, что вы можете просто использовать что-то вроде setCell(Rectangle) чтобы изменить часть (если вы не нагнетесь на drag’n’drop;))

Я закончил использование панели Board из-за некоторого интересного поведения в Java 7, но это еще один вопрос;)

 package puzzel; import java.awt.BorderLayout; import java.awt.EventQueue; import javax.swing.*; public class PuzzlePieceDriver extends JFrame { public PuzzlePieceDriver(ImageIcon myPuzzleImage) { setTitle("Hot Puzz"); setDefaultCloseOperation(EXIT_ON_CLOSE); setLayout(new BorderLayout()); add(new Board(myPuzzleImage)); pack(); setVisible(true); }//end constructor public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException ex) { } catch (InstantiationException ex) { } catch (IllegalAccessException ex) { } catch (UnsupportedLookAndFeelException ex) { } ImageIcon image = new ImageIcon(PuzzlePieceDriver.class.getResource("/issue459.jpg")); PuzzlePieceDriver driver = new PuzzlePieceDriver(image); driver.setLocationRelativeTo(null); driver.setVisible(true); } }); } }//end class 

Панель элементов … Панель отменяет preferred и minimum методы … пока это работает для этого примера, скорее всего, лучше использовать setPreferredSize и setMiniumumSize 😉

 /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package puzzel; import javax.swing.*; import java.awt.*; import java.awt.image.*; public class PuzzlePiece extends JPanel { private BufferedImage masterImage; private Rectangle pieceBounds; private BufferedImage clip; public PuzzlePiece(BufferedImage image, Rectangle bounds) { masterImage = image; pieceBounds = bounds; // Make sure the rectangle fits the image int width = Math.min(pieceBounds.x + pieceBounds.width, image.getWidth() - pieceBounds.x); int height = Math.min(pieceBounds.y + pieceBounds.height, image.getHeight() - pieceBounds.y); clip = image.getSubimage(pieceBounds.x, pieceBounds.y, width, height); }//end constructor @Override public Dimension getPreferredSize() { return pieceBounds.getSize(); } @Override public Dimension getMinimumSize() { return getPreferredSize(); } public void paintComponent(Graphics g) { super.paintComponent(g); int x = 0; int y = 0; g.drawImage(clip, x, y, this); g.setColor(Color.RED); g.drawRect(0, 0, getWidth() - 1, getHeight() - 1); }//end paintComponent }//end class PuzzlePiece 

Панель панели … используется в основном из-за некоторых интересных проблем, с которыми я сталкивался с Java 7 … Реализует MouseListener , когда вы запускаете программу, нажимаете на нее, это весело;)

 package puzzel; import java.awt.Graphics; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Image; import java.awt.Rectangle; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; import javax.swing.ImageIcon; import javax.swing.JPanel; /** * * @author shane */ public class Board extends JPanel { public static final int X_PIECES = 4; public static final int Y_PIECES = 4; private PuzzlePiece[] puzzle = new PuzzlePiece[X_PIECES * Y_PIECES]; private static BufferedImage image; public Board(ImageIcon myPuzzleImage) { image = iconToImage(myPuzzleImage); //pass image into bufferedImage form puzzle = createClip(); addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { removeAll(); invalidate(); createClip(); // doLayout(); invalidate(); revalidate(); repaint(); } }); } public static BufferedImage iconToImage(ImageIcon icon) { Image img = icon.getImage(); int w = img.getWidth(null); int h = img.getHeight(null); BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics g = image.createGraphics(); // Paint the image onto the buffered image g.drawImage(img, 0, 0, null); g.dispose(); return image; }//end BufferedImage protected int randomNumber(int min, int max) { int temp = min + (int) (Math.random() * ((max - min) + 1)); return temp; }//end randomNumber private PuzzlePiece[] createClip() { int cw, ch; int w, h; w = image.getWidth(null); h = image.getHeight(null); cw = w / X_PIECES; ch = h / Y_PIECES; // Generate a list of cell bounds List lstBounds = new ArrayList<>(25); for (int y = 0; y < h; y += ch) { for (int x = 0; x < w; x += cw) { lstBounds.add(new Rectangle(x, y, cw, ch)); } } BufferedImage clip = image; setLayout(new GridBagLayout()); for (int x = 0; x < X_PIECES; x++) { for (int y = 0; y < Y_PIECES; y++) { // Get a random index int index = randomNumber(0, lstBounds.size() - 1); // Remove the bounds so we don't duplicate any positions Rectangle bounds = lstBounds.remove(index); PuzzlePiece piece = new PuzzlePiece(clip, bounds); puzzle[x * X_PIECES + y] = piece; GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = x; gbc.gridy = y; gbc.fill = GridBagConstraints.BOTH; add(piece, gbc); piece.invalidate(); piece.repaint(); }//end nested for }//end for invalidate(); repaint(); return puzzle; }//end createClip } 

Теперь я знаю, что в конечном итоге вы спросите о том, как перемещать кусок, GridBagLayout имеет этот замечательный метод под названием getConstraints, который позволяет вам получить ограничения, используемые для компоновки рассматриваемого компонента. Затем вы можете изменить значения gridx и gridy и использовать setConstraints для его обновления (не забудьте вызвать invalidate и repaint ;))

Я бы рекомендовал прочитать о том, как использовать GridBagLayout для получения дополнительной информации;)

В конце концов вы получите что-то вроде:

Головоломка 1Головоломка 2

  • Печать JPanel с прокручиваемым Jtable На нем
  • Как я могу сделать изображение случайным образом отображаемым каждые x секунд в java, используя таймер?
  • Как переключить JPanels внутри JFrame
  • Нельзя ли добавить компонент Swing в несколько контейнеров?
  • Добавить фоновое изображение на панель
  • Проблема с перерисованием JPanel
  • Повернуть BufferedImage внутри JPanel
  • paintComponent () vs paint () и JPanel vs Canvas в графическом интерфейсе типа кисти
  • Java: сохранение формата изображения JPanel
  • Имея изображения в качестве фона JPanel
  • Рисование прямоугольника, который не исчезнет в следующей краске
  • Interesting Posts

    Войдите в систему как администратор?

    Не удается установить iTunes, так как не удалось получить доступ к службе установщика Windows

    Как уменьшить размер системы Windows 8?

    Есть ли способ переносить сообщение из препроцессора C?

    Сервлет против RESTful

    Динамическое рендеринг asp: изображение из записи BLOB в ASP.NET

    Можно ли «tail -f» выводить «dmesg»?

    Как получить информацию об изображении (картинке) из командной строки Linux?

    Могу ли я маршрутизировать программы на два интернет-соединения одновременно в Windows 7?

    Adobe Acrobat: как объединить несколько файлов PDF?

    Не удалось найти допустимый путь сертификации для запрошенной целевой ошибки даже после импорта сертификата

    Локальные папки в папке res?

    Планировщик задач Windows при смене файла

    Окна 10 не могут получить доступ к сетевым ресурсам медиацентра

    Добавление вызывает java.lang.IllegalStateException: не удается создать сеанс после того, как ответ был зафиксирован

    Давайте будем гением компьютера.