2013-11-20 4 views
2

Я пытаюсь загрузить фоновое изображение с помощью JFileChooser, но когда операция завершается, метод paintcomponent() не вызывается как ожидалось. [EDIT] по этой причине, вместо красного шарика над фоновым изображением, у меня есть только красный шар.paintComponent не вызывается при вызове JScrollPane

Я прочитал в нескольких другом тем, что экземпляр моей Маппы объекта должен быть добавлен к раме: Why is paint()/paintComponent() never called? paintComponent not being called at the right time PaintComponent is not being called

Но это не решает мою проблему: Я создал JScrollPane, который получает свой компонент в конструктор и связывает JScrollPane и добавили его в основной раме с

frmEditor.getContentPane().add(scrollabile, BorderLayout.CENTER);

Это код главного Gui

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.io.File; 

import javax.swing.ImageIcon; 
import javax.swing.JFileChooser; 
import javax.swing.JFrame; 
import javax.swing.JMenu; 
import javax.swing.JMenuBar; 
import javax.swing.JMenuItem; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.ScrollPaneConstants; 
import javax.swing.UIManager; 

public class Gui implements ActionListener { 

    private JFrame frmEditor; 

    Mappa content; 
    private JMenuItem mntmSfondo; 
    private JScrollPane scrollabile; 

    /** 
    * Launch the application. 
    */ 
    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       try { 
        Gui window = new Gui(); 
        window.frmEditor.setVisible(true); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
    } 

    /** 
    * Create the application. 
    */ 
    public Gui() { 
     initialize(); 
    } 

    /** 
    * Initialize the contents of the frame. 
    */ 
    private void initialize() { 
     frmEditor = new JFrame(); 
     frmEditor.setFont(UIManager.getFont("TextArea.font")); 
     frmEditor.setBounds(50, 50, 1024, 768); 
     frmEditor.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frmEditor.getContentPane().setLayout(new BorderLayout(0, 0)); 

     JPanel panelTile = new JPanel(); 
     panelTile.setLayout(new BorderLayout(0, 0)); 

     JPanel panelStrum = new JPanel(); 

     panelStrum.setLayout(new GridLayout(15, 2)); 

     content = new Mappa(null); 
     content.setMinimumSize(new Dimension(150, 150)); 
     scrollabile = new JScrollPane(content); 
     scrollabile 
       .setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 
     scrollabile 
       .setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); 
     frmEditor.getContentPane().add(scrollabile, BorderLayout.CENTER); 

     inizializzaMenu(); 
    } 

    /** 
    * Initialize the menu. 
    */ 
    private void inizializzaMenu() { 

     JMenuBar menuBar = new JMenuBar(); 
     frmEditor.setJMenuBar(menuBar); 
     JMenu mnFile = new JMenu("File"); 
     mnFile.setFont(UIManager.getFont("TextArea.font")); 

     JMenu mnAltro = new JMenu("Modify"); 
     mnAltro.setFont(UIManager.getFont("TextArea.font")); 
     menuBar.add(mnAltro); 

     mntmSfondo = new JMenuItem("Load Background"); 
     mntmSfondo 
       .setIcon(new ImageIcon(
         Gui.class 
           .getResource("/com/sun/java/swing/plaf/windows/icons/TreeOpen.gif"))); 
     mntmSfondo.setFont(UIManager.getFont("TextArea.font")); 
     mntmSfondo.addActionListener(this); 
     mnAltro.add(mntmSfondo); 
    } 

    public void actionPerformed(ActionEvent e) { 
     Object source = e.getSource(); 
     if (source == mntmSfondo) { 
      JFileChooser fc = new JFileChooser("tuttiSfondi"); 
      int result = fc.showOpenDialog(null); 
      if (result == JFileChooser.APPROVE_OPTION) { 
       File file = fc.getSelectedFile(); 
       try { 
        content = new Mappa(file); 
       } catch (Exception ex) { 
       } 
      } 
      if (result == JFileChooser.CANCEL_OPTION) { 
      } 
     } 
    } 

} 

в то время как это код класса Маппа, что я хотел бы использовать для загрузки фона от JFileChooser.

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

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

public class Mappa extends JPanel { 

    Image immagine; 

    public Mappa(File fileImmagine) { 

     if (fileImmagine != null) { 
      BufferedImage img = null; 
      try { 
       img = ImageIO.read(new File(fileImmagine.getPath())); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
      this.immagine = img; 
     } 
     repaint(); 
    } 

    public void paintComponent(Graphics g) { 

     super.paintComponent(g); 
     g.clearRect(0, 0, 4000, 4000); 
     g.drawImage(immagine, 0, 0, null); 

     g.setColor(Color.red); 
     g.fillOval(170, 170, 150, 150); 

     System.out.println("Called Repaint() on Mappa"); 

    } 


} 

Проблема не в неправильном пути изображения, так как он загружает, если я установить путь на классе Маппа «вручную», давая путь вместо того, чтобы использовать new File(fileImmagine.getPath()) в ImageIO.read, но paintComponent называется только один раз, когда конструктор Mappa вызывается из класса Gui

ответ

5

Когда вы устанавливаете фон, вы выделяете только новый экземпляр Mappa, но фактически не добавляете его в какой-либо контейнер. Попробуйте добавить следующее:

scrollabile.setViewportView(content); 

Или вместо того, чтобы заменить изображение в Mappa классе. То есть:

public void setImage(File file) throws IOException { 
    this.immagine = ImageIO.read(file); 
    repaint(); 
} 

Кроме того, в paintComponent(), можно использовать размеры панели, чтобы заполнить всю площадь:

g.drawImage(immagine, 0, 0, getWidth(), getHeight(), this); 

И не забудьте использовать действительный ImageObserver в JPanel реализует один.

+0

Я попытался добавить' scrollable.setViewportView (content); 'после и перед' frmEditor. getContentPane(). add (scrollabile, BorderLayout.CENTER); 'без каких-либо успехов. Предложение Вандала о добавлении функции setImage в класс Mappa фактически решило проблему, спасибо! – Kaeel

+0

@Kaeel, идея состояла в том, чтобы вызвать 'scrollabile.setViewportView (content);' in' actionPerformed() 'сразу после перераспределения' Mappa'. Но замена изображения в существующем 'Mappa' проще. – tenorsax

+0

Я только что пробовал; он действительно работает, и я также узнал новое. Простите, что у меня до сих пор нет репутации enuogh, чтобы поддержать вас обоих, я вернусь к этому вопросу и сделаю это, когда я получу 15 репутации! – Kaeel

3

Вы фактически не модифицируете экземпляр Mapa, который вы добавили в рамку. Линия

content = new Mappa(file); 

в actionPerformed() не меняет панель в кадре, он перераспределяет только локальную переменную. Вместо этого вы должны поместить метод updateImage() в Mapa, который обновит изображение, которое отображает Mapa. Вам также нужно будет позвонить repaint() после этого, чтобы он перерисовал новое изображение.

+0

+1 вы избили меня до этого :) – tenorsax

+0

Спасибо, похоже, это была настоящая проблема с кодом. Я создал метод updateImage в классе 'Mappa' и назвал его из GUI чем-то вроде этого' content.setImage (file); ' – Kaeel

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