2016-09-24 2 views
0

Я проверил этот код в течение нескольких часов, но прямоугольник не отображается, может кто-нибудь сказать мне, почему он не показывает ?:Почему прямоугольник не отображается?

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.FlowLayout; 
import java.awt.Graphics; 
import java.awt.event.KeyEvent; 
import java.io.File; 
import java.io.IOException; 

import javax.imageio.ImageIO; 
import javax.swing.ImageIcon; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 

public class Main { 

    public static void main(String[] args) { 

     JFrame frame = new JFrame(); 
     int resx = 700,resy = 500; 
     frame.setSize(resx,resy); 
     frame.setLocationRelativeTo(null); 
     frame.setTitle("Game"); 
     frame.setResizable(false); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setLayout(new FlowLayout()); 
     try { 
      frame.setContentPane(new JLabel(new ImageIcon(ImageIO.read(new File("C:\\Users\\ivans\\Pictures\\Cookies.png"))))); 
     } catch (IOException e) { 
     } 
     frame.repaint(); 
     frame.setLayout(new FlowLayout()); 
     frame.add(new JPanel(){ 
      @Override 
      public void paintComponent(Graphics g){ 
       super.paintComponent(g); 
       g.setColor(Color.WHITE); 
       g.fillRect(50,50,450,650); 
      } 
     }, BorderLayout.CENTER); 
     frame.repaint(); 
     frame.setVisible(true); 
    } 

} 

Каждый раз, когда я пытаюсь активировать фон, прямоугольник не отображается, и каждый раз, когда я активирую прямоугольник, фон не отображается. Пожалуйста помоги!

+0

Вы уверены, что ваша попытка {...} выполняется успешно? с пустым разделом catch {} очень плохой практикой –

+0

Что я должен поставить в «За исключением» Serction? – user3150362

+0

Вы должны распечатать трассировку стека и завершить программу. Вы не захотите его запускать, если чтение в изображении вызывает исключение. –

ответ

1

Вы устанавливаете область содержимого JFrame в JLabel, контейнер, который не использует макет, и поэтому добавление компонента к нему не позволит отображать этот компонент, если вы не полностью укажете размер и положение этого компонента, то есть его границы. Это одна из причин, почему я избегаю использования JLabels для contentPanes (также, что он не будет устанавливать свой предпочтительный размер на основе компонентов, которые он содержит), и вместо этого в целом предпочитает делать мой рисунок в фоновом методе paintanomponent JPanel.

Боковых рекомендации:

  • Вы слишком много происходите в основном методе - если эта программа не является ни для чего, кроме демонстрационных целей
  • Вы установили оригинальный ContentPane фрейма (A JPanel) в FlowLayout, но поймите, что это бессмысленно после изменения contentPane.
  • Несмотря на то, что в contentPane используется FlowLayout, вы пытаетесь добавить чертеж JPanel в положение BorderLayout, что не имеет смысла.
  • У вас есть пустой блок catch, что почти никогда не должно быть сделано.
  • Получите ваши изображения как ресурсы, а не файлы.
  • Избегайте использования абсолютных путей к файлам и предпочитайте использовать относительные пути к ресурсам.
  • Не устанавливайте размеры предметов, если их можно избежать.
  • Избегайте так называемых «магических чисел», например, g.fillRect(50,50,450,650);, так как это затрудняет отладку и улучшение вашего кода.

Например, что-то вроде:

import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.image.BufferedImage; 
import java.io.IOException; 
import java.net.URL; 
import javax.imageio.ImageIO; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class ShowRectangle extends JPanel { 
    private static final int RECT_X = 50; 
    private static final int RECT_Y = RECT_X; 
    private static final int RECT_W = 200; 
    private static final int RECT_H = 200; 
    private static final String URL_SPEC = "https://duke.kenai.com/guitar/DukeAsKeith-daylightSmall.png"; 
    private BufferedImage img; 

    public ShowRectangle(BufferedImage img) { 
     this.img = img; 
    } 

    // have same JPanel draw image and graphic element 
    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     if (img != null) { 
      g.drawImage(img, 0, 0, this); 
     } 

     // avoid magic numbers 
     // g.fillRect(50,50,450,650); 
     g.fillRect(RECT_X, RECT_Y, RECT_W, RECT_H); 
    } 

    // Size the JPanel to the image size 
    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet() || img == null) { 
      return super.getPreferredSize(); 
     } 
     return new Dimension(img.getWidth(), img.getHeight()); 
    } 

    private static void createAndShowGui(BufferedImage image) { 
     ShowRectangle mainPanel = new ShowRectangle(image); 

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

    public static void main(String[] args) { 

     try { 
      URL imageUrl = new URL(URL_SPEC); 
      BufferedImage img = ImageIO.read(imageUrl); 
      SwingUtilities.invokeLater(() -> createAndShowGui(img)); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      System.exit(-1); 
     } 
    } 
} 

Если вы не использовать «магическое» число, например, это легко сделать черный прямоугольник перетаскиваемым, так как он теперь нарисован значениями переменных, значение что вы можете изменить внутри MouseAdapter (MouseListener и MouseMotionListener в сочетании). Например:

import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Point; 
import java.awt.Rectangle; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.image.BufferedImage; 
import java.io.IOException; 
import java.net.URL; 

import javax.imageio.ImageIO; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class ShowRectangle extends JPanel { 
    private static final int RECT_X = 50; 
    private static final int RECT_Y = RECT_X; 
    private static final int RECT_W = 200; 
    private static final int RECT_H = 200; 
    private static final String URL_SPEC = "https://duke.kenai.com/guitar/DukeAsKeith-daylightSmall.png"; 
    private int rectX = RECT_X; 
    private int rectY = RECT_Y; 
    private BufferedImage img; 

    public ShowRectangle(BufferedImage img) { 
     this.img = img; 
     MouseAdapter myMouse = new MyMouse(); 
     addMouseListener(myMouse); 
     addMouseMotionListener(myMouse); 
    } 

    // have same JPanel draw image and graphic element 
    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     if (img != null) { 
      g.drawImage(img, 0, 0, this); 
     } 

     // avoid magic numbers 
     // g.fillRect(50,50,450,650); 
     g.fillRect(rectX, rectY, RECT_W, RECT_H); 
    } 

    // Size the JPanel to the image size 
    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet() || img == null) { 
      return super.getPreferredSize(); 
     } 
     return new Dimension(img.getWidth(), img.getHeight()); 
    } 

    private class MyMouse extends MouseAdapter { 
     private Point p1; 
     private Point rectP = null; 

     @Override 
     public void mousePressed(MouseEvent e) { 
      p1 = e.getPoint(); 
      if (new Rectangle(rectX, rectY, RECT_W, RECT_H).contains(p1)) { 
       rectP = new Point(rectX, rectY); 
      } 
     } 

     @Override 
     public void mouseDragged(MouseEvent e) { 
      moveRect(e.getPoint()); 
     } 

     @Override 
     public void mouseReleased(MouseEvent e) { 
      moveRect(e.getPoint()); 
      rectP = null; 
     } 

     private void moveRect(Point p2) { 
      if (rectP == null) { 
       return; 
      } 
      rectX = rectP.x + p2.x - p1.x; 
      rectY = rectP.y + p2.y - p1.y; 
      repaint(); 
     } 

    } 

    private static void createAndShowGui(BufferedImage image) { 
     ShowRectangle mainPanel = new ShowRectangle(image); 

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

    public static void main(String[] args) { 

     try { 
      URL imageUrl = new URL(URL_SPEC); 
      BufferedImage img = ImageIO.read(imageUrl); 
      SwingUtilities.invokeLater(() -> createAndShowGui(img)); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      System.exit(-1); 
     } 
    } 
} 
+0

Спасибо за ответ, но как вы добавляете макет в JLabel? – user3150362

+0

@ user3150362: на мой взгляд, вы этого не делаете. Я бы использовал фоновый JPanel. Подождите ..... –

+0

@ user3150362: см. Примеры выше того, что я имею в виду. \ –

0

Его там только что оно выходит из границы и, следовательно, не видно.

заменить эти две строки и проверить

g.setColor(Color.BLACK); 
g.fillRect(0,0,250,250); 

Попробуйте это,

@Override 
      public void paintComponent(Graphics g){ 
       super.paintComponent(g); 
       Rectangle clipBounds = g.getClipBounds(); 
           System.out.println(clipBounds.getX() +" "+ clipBounds.getY() + " "+ clipBounds.getHeight() + " " + clipBounds.getWidth()); 

       g.setColor(Color.BLACK); 
       g.fillRect(0,0,450,450); 
      } 

вы получите 0,0 0,0 10,0 10.0 в качестве выходного сигнала, означающего контейнер заполнения reactangle начинается от 0,0 до 10,10 и, следовательно, не было показано

Измените расположение к GridLayout() будет решить вашу проблему,

frame.setLayout(new GridLayout()); 
     frame.add(new JPanel(new GridLayout()){ 
      /** 
      * 
      */ 
      private static final long serialVersionUID = 1L; 

      @Override 
      public void paintComponent(Graphics g){ 
       super.paintComponent(g); 
       Rectangle clipBounds = g.getClipBounds(); 
       System.out.println(clipBounds.getX() +" "+ clipBounds.getY() + " "+ clipBounds.getHeight() + " " + clipBounds.getWidth()); 
       g.setColor(Color.BLACK); 
            g.fillRect(frame.getWidth()/2,0,frame.getWidth(),frame.getWidth()); 

      } 
     }, BorderLayout.CENTER); 

В соответствии с док,

недействительного java.awt.Graphics.fillRect (целое х, у INT, ширина INT, INT высота)

Заполняет указанный прямоугольник. Левый и правый края прямоугольника находятся в x и x + width - 1. Верхний и нижний края расположены на y и y + height - 1. Получаемый прямоугольник охватывает ширину области шириной пикселей по высоте в высоту. Прямоугольник заполняется текущим цветом графического контекста. Параметры: x координата x прямоугольника, подлежащего заполнению. y координата y прямоугольника для заполнения. Ширина ширины прямоугольника для заполнения. Высота высоты заполняемого прямоугольника.

Так что это вопрос

+0

Спасибо! Хотя я проблема, почему он выглядит как маленький черный квадрат, а не занимает 1/2 из jframe? – user3150362

+0

В этом случае изображение не отображается – user3150362

Смежные вопросы