2017-02-01 17 views
0

Я разрабатываю карточную игру, и я хочу нарисовать (нарисовать) карту на панели. Однако, когда я рисую, отображается только небольшая часть изображения. Вы можете сортировать видеть на этом скриншоте:Только рисование части bufferedimage

Image of frame and small section of card

Я написал обертку класс (CardImage) для BufferedImage:

import java.awt.image.BufferedImage; 
import java.io.File; 

import javax.imageio.ImageIO; 

public class CardImage { 

BufferedImage img = null; 

public CardImage() { 

} 

public BufferedImage setImage(Card c) { 
    try { 
     img = ImageIO.read(new File("/media/billy/HOME/workspace/Shithead/src/cards/" + toName(c))); 
    } catch(Exception e) { 
     System.out.println(e); 
    } 

    /* 
    int scale_factor = 8; 
    System.out.println(img.getHeight()); 
    Image dimg = img.getScaledInstance((int)img.getWidth()/scale_factor, (int)img.getHeight()/scale_factor, Image.SCALE_SMOOTH); 


    Graphics g = img.createGraphics(); 
    g.drawImage(dimg, 0, 0, null); 
    g.dispose(); 
    */ 


    return img; 
} 

public String toName(Card c) { 
    String tmp = c.toString().replaceAll(" ", "_"); 
    tmp = tmp.toLowerCase(); 
    tmp = tmp + ".png"; 
    return tmp; 
} 

} 

и у меня есть HandPanel, который расширяет JPanel, в котором я хочу нарисовать CardImage BufferedImage:

import java.awt.Graphics; 

import java.awt.image.BufferedImage; 


import javax.swing.JPanel; 


public class HandPanel extends JPanel { 

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

    CardImage cardImage = new CardImage(); 

    Card card = new Card(2,2); 
    BufferedImage img = cardImage.setImage(card); 
    System.out.println(img.getHeight(null) + " " + img.getWidth(null)); 

    g.drawImage(img, 0, 0, null); 

} 


} 

И у меня есть еще один класс, чтобы содержать HandPanel:

import java.awt.Dimension; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 

public class ShitGUI { 
public static void main(String[] args) { 
    ShitGUI gui = new ShitGUI(); 
} 


JFrame frame = new JFrame(); 
JPanel mainPanel = new JPanel(); 
public ShitGUI() { 
    mainPanel.setPreferredSize(new Dimension(500,500)); 

    HandPanel pan = new HandPanel(); 

    mainPanel.add(pan); 

    frame.add(mainPanel); 
    frame.pack(); 
    frame.setVisible(true); 
} 



} 

Изображения карт довольно большие (создание карты (2,2) - это всего лишь 2 Сердца, и я знаю, что я правильно понял путь).

Любая помощь приветствуется. Благодаря!

N.B. Когда я раскомментирую раздел, содержащий dimg, я получаю уменьшенную красную карточку (а не черно-белое, а не масштабированное изображение, которое я получал в противном случае). Я понимаю масштабирование, но я не понимаю, почему мой подход дает мне черно-белое изображение.

+3

Вам не следует создавать новые экземпляры Card, CardImage или BufferedImage в вашем методе paintComponent(). Этот метод может быть вызван сотни раз - когда система думает, что она нуждается в обновлении. – FredK

+1

Вероятная причина вашей непосредственной проблемы заключается в том, что HandPanel не возвращает достаточно подсказок с размерами, чтобы позволить менеджеру компоновки выложить его, его предпочтительный размер по умолчанию равен 0x0 – MadProgrammer

+3

* Shithead/src/cards * - вы никогда не должны ссылаться на «src», , он не будет существовать, как только приложение будет построено, и вы не должны ссылаться на встроенные ресурсы, как с помощью файла – MadProgrammer

ответ

3

Вероятного неотложный вопрос является тем фактом, что HandPanel не предоставляет никаких проклейки подсказок, чтобы менеджеры компоновки, чтобы определить оптимальный размер для компонента Отката на нем по умолчанию предпочтительного размера 0x0

Я вернулся и модифицирован вас кода, чтобы сделать его несколько более многоразовым.

img = ImageIO.read(new File("/media/billy/HOME/workspace/Shithead/src/cards/" + toName(c))); - плохая идея.

Вы никогда не должны ссылаться на какой-либо путь, который содержит src, src не будет существовать после создания вашего приложения. Вы не должны ссылаться на встроенные ресурсы на File, они не являются (или, по крайней мере, не будут, когда приложение будет создано), вместо этого вам необходимо использовать Class#getResource.

public class CardImage { 

    BufferedImage img = null; 

    public CardImage(Card card) { 
     setImage(card); 
    } 

    public BufferedImage getImage() { 
     return img; 
    } 

    public BufferedImage setImage(Card c) { 
     try { 
      //img = ImageIO.read(new File("/media/billy/HOME/workspace/Shithead/src/cards/" + toName(c))); 
      img = ImageIO.read(getClass().getResource("/cards/" + toName(c))); 
     } catch (Exception e) { 
      System.out.println(e); 
     } 

     /* 
int scale_factor = 8; 
System.out.println(img.getHeight()); 
Image dimg = img.getScaledInstance((int)img.getWidth()/scale_factor, (int)img.getHeight()/scale_factor, Image.SCALE_SMOOTH); 


Graphics g = img.createGraphics(); 
g.drawImage(dimg, 0, 0, null); 
g.dispose(); 
     */ 
     return img; 
    } 

    public String toName(Card c) { 
     String tmp = c.toString().replaceAll(" ", "_"); 
     tmp = tmp.toLowerCase(); 
     tmp = tmp + ".png"; 
     return tmp; 
    } 

} 

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

Опять же, я модифицировал HandPanel, теперь он требует, чтобы пропускать Card к нему, и он использует это, чтобы сделать определения о том, что информация, которую он будет использовать для создания проклейки подсказки

public class HandPanel extends JPanel { 

    CardImage cardImage; 

    public HandPanel(Card card) { 
     cardImage = new CardImage(card); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     BufferedImage img = cardImage.getImage(); 
     return img == null ? super.getPreferredSize() : new Dimension(img.getWidth(), img.getHeight()); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     BufferedImage img = cardImage.getImage(); 
     g.drawImage(img, 0, 0, this); 
    } 

} 

Я бы также рекомендуем вам взглянуть на Perials of getScaledInstance и Java: maintaining aspect ratio of JPanel background image для некоторых альтернатив

+2

Поскольку к вопросу не было применено никаких новых или близких голосов, тогда вопрос должен быть приемлемым, это означает, что нисходящее отношение напрямую связано с ответом. Я каким образом отвечает на вопрос OPs? Что было пропущено? Что можно сделать, чтобы улучшить вопрос? Поскольку вы не смогли предоставить альтернативный ответ, я могу только предположить, что вы не знаете, как решить проблему самостоятельно, что вызывает вопрос о том, как вы знаете, что у меня нет? На данный момент я могу только предположить, что у вас есть личная проблема со мной, ответы на вопросы и попытки помочь людям :( – MadProgrammer

+0

Спасибо, это сработало отлично! – Billy

+0

@Billy Рад, что это могло бы помочь;) – MadProgrammer

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

  • Нет связанных вопросов^_^