2017-04-10 23 views
0

我正在實現從文件加載並可以對其進行編輯的Paint應用程序。 但我的Openfile函數不能正確運行,它會加載圖像並正確更改界限,但不要在Jpanel中繪製它。在Java Swing/Awt中實現圖像加載器

這是我的代碼。

public class OpenSave extends JPanel{ 

private static final long serialVersionUID = 1L; 

protected BufferedImage imagem; 

public OpenSave() {} 

public void open(JPanel panel) throws IOException { 
    JFileChooser escolher = new JFileChooser(); 
    escolher.setCurrentDirectory(new File(".")); 

    escolher.setFileFilter(new javax.swing.filechooser.FileFilter() { 
     public boolean accept(File f) { 
      return f.getName().toLowerCase().endsWith(".jpg") || f.isDirectory(); 
    } 
    public String getDescription() { 
     return "Imagens JPG"; 
    } 
    }); 

    escolher.setFileFilter(new javax.swing.filechooser.FileFilter() { 
     public boolean accept(File f) { 
      return f.getName().toLowerCase().endsWith(".png") || f.isDirectory(); 
     } 
    public String getDescription(){ 
     return "Imagens PNG"; 
    } 
    }); 


    JFrame frame = new JFrame(); 
    frame.setIconImage(Toolkit.getDefaultToolkit().getImage(OpenSave.class.getResource("/javax/swing/plaf/metal/icons/ocean/directory.gif"))); 
    int r = escolher.showOpenDialog(frame); 
    if (r == JFileChooser.APPROVE_OPTION) { 
     imagem = ImageIO.read(new File(escolher.getSelectedFile().getAbsolutePath())); 
     panel.setBounds(77, 13, imagem.getWidth(this), imagem.getHeight(this)); 
    } 
    } 


@Override 
public void paintComponent(Graphics g) {   
    super.paintComponent(g);       
    g.drawImage(imagem, 0, 0, this); 
    repaint(); 
} 
} 

與此我可以保存並正確加載,但加載的圖像不會去我的JPanel面板。

這裏是主要的簡化類。

private JPanel contentPane; 
    private Jpanel panel; 

    public static void main(String[] args) { 
    EventQueue.invokeLater(new Runnable() { 
     public void run() { 
      try { 
       TelaMain frame = new TelaMain(); 
       frame.setVisible(true); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }); 
    } 

    public TelaMain() { 

    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    setBounds(100, 100, 600, 400); 

    JMenuBar menuBar = new JMenuBar(); 
    menuBar.setFocusTraversalKeysEnabled(true); 
    setJMenuBar(menuBar); 

    JMenu mnArchive = new JMenu("Archive"); 
    menuBar.add(mnArchive); 
    JMenuItem mntmOpen = new JMenuItem("Open"); 
    mnArquivo.add(mntmOpen); 

    panel = new JPanel(); 
    panel.setAutoscrolls(true); 
    panel.setBorder(new LineBorder(new Color(0, 0, 0))); 
    panel.setBackground(Color.WHITE); 
    panel.setBounds(77, 13, 498, 307); 
    contentPane.add(panel); 

    mntmAbrir.addActionListener(
     new ActionListener() { 
      public void actionPerformed(ActionEvent abrir) { 
        OpenSave a = new OpenSave(); 
        try { 
         a.open(panel); 
         a.repaint(); 

        } catch (IOException e) { 
         e.printStackTrace(); 
        } 
       } 

      } 
     } 
    ); 

我打開任何其他編輯要求我的問題。

+2

1)爲了更好地幫助更快分開,張貼[MCVE]或[簡要,獨立的,正確的示例](HTTP://www.sscce .org等/)。 2)獲取圖像的一種方法是通過[本問答](http://stackoverflow.com/q/19209650/418556)中的圖像進行熱鏈接。顯然(我希望),因爲問題是加載圖像,保存圖像的所有代碼都可以被刪除。 –

+0

您似乎誤解了我在發佈MCVE/SSCCE時提供的建議。你讀過鏈接文件嗎? –

+0

仍在閱讀,但我還沒有找到解決方案。 –

回答

4

您的代碼看起來很混亂。具體來說:

  • 你創建一個JFrame,但從不顯示它,也許只是作爲你的文件選擇器的參數?
  • 您將JPanel傳遞到您的open方法中,只是改變它的大小,但是除此之外別無其他。
  • 我有一種感覺,你認爲這在JPanel中通過會以某種方式獲得你正在閱讀的圖像,但如果是這樣,你錯了。
  • 圖像可能會在OpenSave JPanel中顯示,但我們永遠不會知道,因爲我們從來沒有看到您將它添加到任何頂級窗口(如JFrame) - 所以您當前的代碼給我們提供了不完整的圖片這樣做。
  • 您的paintComponent方法很危險,因爲它試圖在OpenSave JPanel中繪製圖像,而不檢查圖像是否爲空。如果沒有圖像當前可用,這會冒代碼投擲NullPointerException的風險。
  • 您正在使用setBounds(...)做一件危險的事情。雖然Swing的新手可能看起來像是創建複雜GUI的最簡單也是最好的方式,但更多Swing GUI的創建使用它們時會遇到更嚴重的困難。它們不會在GUI大小調整時調整組件的大小,它們是增強或維護的皇室女巫,當它們放在滾動窗格中時它們會完全失敗,在所有平臺或屏幕分辨率與原始視圖不同時,它們看起來會非常糟糕。

建議:

  • 確保你把你的OpenSave的JPanel進入顯示的JFrame
  • 在它的paintComponent方法,只畫圖像,如果它不爲空。換句話說在if塊檢查空,只畫if (imagem != null) {}
  • 向我們展示你的相關代碼
  • 其餘傳遞當前顯示的JFrame到JFileChooser中,沒有一個不顯示的。
  • 讓您的OpenSave JPanel覆蓋getPreferredSize,並將該大小設置爲其保存的圖像的大小。
  • 我自己,我會分開我的圖像文件打開並保存視圖代碼,GUI代碼中的代碼。一個例子的

部分:

public void setImagem(BufferedImage imagem) { 
    this.imagem = imagem; 
    repaint(); 
} 

@Override 
protected void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    if (imagem != null) { 
     g.drawImage(imagem, 0, 0, this); 
    } 
} 

@Override 
public Dimension getPreferredSize() { 
    Dimension sz = super.getPreferredSize(); 
    if (imagem != null) { 
     sz = new Dimension(imagem.getWidth(), imagem.getHeight()); 
    } 
    return sz; 
} 

private static void createAndShowGui() { 
    MyOpenSave openSave = new MyOpenSave(); 

    JFrame frame = new JFrame("MyOpenSave"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.getContentPane().add(openSave); 
    frame.pack(); 
    frame.setLocationRelativeTo(null); 
    frame.setVisible(true); 
} 

public static void main(String[] args) { 
    SwingUtilities.invokeLater(() -> createAndShowGui()); 
} 

更完整的示例:

TestOpenSave.java - 「驅動程序」 類

public class TestOpenSave { 

    private static void createAndShowGui() { 
     OpenSave openSave = new OpenSave(); 
     JFrame frame = new JFrame("OpenSave"); 

     JPanel btnPanel = new JPanel(); 
     btnPanel.add(new JButton(new GetImageAction("Open Image", frame, openSave))); 

     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(openSave); 
     frame.add(btnPanel, BorderLayout.PAGE_END); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
} 

OpenSave.java ,「視圖」類顯示圖像

@SuppressWarnings("serial") 
public class OpenSave extends JPanel { 
    private BufferedImage imagem; 

    public void setImagem(BufferedImage imagem) { 
     this.imagem = imagem; 
     repaint(); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     if (imagem != null) { 
      g.drawImage(imagem, 0, 0, this); 
     } 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     Dimension sz = super.getPreferredSize(); 
     if (imagem != null) { 
      sz = new Dimension(imagem.getWidth(), imagem.getHeight()); 
     } 
     return sz; 
    } 
} 

GetImageAction文件加載類或「控制器」類。需要注意的是它是從上述圖像顯示或「視圖類」

@SuppressWarnings("serial") 
public class GetImageAction extends AbstractAction { 
    private JFrame myFrame; 
    private OpenSave openSave; 

    public GetImageAction(String name, JFrame myFrame, OpenSave openSave) { 
     super(name); 
     this.myFrame = myFrame; 
     this.openSave = openSave; 
     int mnemonic = (int) name.charAt(0); 
     putValue(MNEMONIC_KEY, mnemonic); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     JFileChooser escolher = new JFileChooser(); 
     escolher.setMultiSelectionEnabled(false); 
     escolher.setCurrentDirectory(new File(".")); 
     escolher.setFileFilter(new FileFilter() { 

      @Override 
      public String getDescription() { 
       return "Imagens JPG and PNG"; 
      } 

      @Override 
      public boolean accept(File f) { 
       String ext = f.getName().toLowerCase(); 
       if (f.isDirectory() || ext.endsWith(".jpg") || ext.endsWith(".png")) { 
        return true; 
       } 
       return false; 
      } 
     }); 
     int reply = escolher.showOpenDialog(myFrame); 
     if (reply == JFileChooser.APPROVE_OPTION) { 
      try { 
       BufferedImage img = ImageIO.read(escolher.getSelectedFile()); 
       openSave.setImagem(img); 
       myFrame.pack(); 
       myFrame.setLocationRelativeTo(null); 
      } catch (IOException e1) { 
       e1.printStackTrace(); 
      } 
     } 
    } 
} 
+0

對不起,如果它看起來很困惑,我會盡量按照你的建議。 –

+0

@MatheusSimões:請參閱更完整的示例。請注意圖像打開代碼和顯示代碼的分離。你應該有一個完全獨立的圖像保存代碼的類。 –

+0

感謝您的樣品!我會研究它,並嘗試實施我自己,如果我成功的話,反饋你。非常感謝你 ! –

0

我不完全確定,但問題可能是您在初始化JFrame時沒有包含frame.add(this),這會告訴程序在您的類中使用paint方法。

+0

我發佈的這段代碼是加載並保存的類OpenSave,因爲我希望。在主代碼中有正確啓動我的程序所需的所有初始化。不過謝謝@Llama –