2013-07-26 35 views
2

我在JTextArea背景上繪製圖像時,使用其他外觀和感覺(金屬,Windows等)繪製圖像,但是當使用Nimbus時看起來和感覺它不繪製圖像什麼是可能的問題,以及如何解決這個問題? 這裏是我使用使用Nimbus時無法在JTextArea背景上繪製圖像外觀和感覺

圖片TextArea類

public class ImageTextArea extends JTextArea{ 
    File image; 
    public ImageTextArea(File image) 
    { 
     setOpaque(false); 
     this.image=image; 
    } 

    @Override 
    public void paintComponent(final Graphics g) 
    { 
     try 
     { 
      // Scale the image to fit by specifying width,height 
      g.drawImage(new ImageIcon(image.getAbsolutePath()).getImage(),0,0,getWidth(),getHeight(),this); 
      super.paintComponent(g); 
     }catch(Exception e){} 
    } 
} 

,並且測試類

public class TestImageTextArea extends javax.swing.JFrame { 

    private ImageTextArea tx; 

    public TestImageTextArea() { 
     tx = new ImageTextArea(new File("img.jpg")); 
     setTitle("this is a jtextarea with image"); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 
     JPanel mainp = new JPanel(new BorderLayout()); 
     add(mainp); 
     mainp.add(new JScrollPane(tx), BorderLayout.CENTER); 
     setSize(400, 400); 
    } 

    public static void main(String args[]) { 
/* 
     try { 
      for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { 
       if ("Nimbus".equals(info.getName())) { 
        javax.swing.UIManager.setLookAndFeel(info.getClassName()); 
        break; 
       } 
      } 
     } catch (Exception ex) { 
      System.out.println("Unable to use Nimbus LnF: "+ex); 
     } 
*/ 
     java.awt.EventQueue.invokeLater(new Runnable() { 

      public void run() { 
       new TestImageTextArea().setVisible(true); 
      } 
     }); 
    } 

} 

當我刪除評論它不會繪製圖像的代碼。

+0

爲了更快提供更好的幫助,請發佈[SSCCE](http://sscce.org/)。 –

+0

Nimbus可能忽略組件的不透明狀態 – MadProgrammer

回答

6

基本上,當您撥打super.paintComponent時,它會調用UI delgate的update方法。這是魔術發生的地方。

下面是雨雲的SynthTextAreaUI實施

public void update(Graphics g, JComponent c) { 
    SynthContext context = getContext(c); 

    SynthLookAndFeel.update(context, g); 
    context.getPainter().paintTextAreaBackground(context, 
         g, 0, 0, c.getWidth(), c.getHeight()); 
    paint(context, g); 
    context.dispose(); 
} 

正如你所看到的,它實際上繪製背景,用了該組件的不透明狀態方面,然後調用paint,這將調用BasicTextUI.paint方法(通過super.paint

這很重要,因爲BasicTextUI.paint實際上描繪了文字。

那麼,這對我們有什麼幫助?通常情況下,我會將某人拒絕撥打電話super.paintComponent,但這正是我們要做的,但我們會事先知道我們正在承擔什麼責任。

首先,我們將接管update的職責,填寫背景,繪製我們的背景,然後在UI委託上調用paint

enter image description here

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class NimbusTest { 

    public static void main(String[] args) { 
     new NimbusTest(); 
    } 

    public NimbusTest() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new JScrollPane(new TestTextArea())); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestTextArea extends JTextArea { 

     private BufferedImage bg; 

     public TestTextArea() { 
      try { 
       bg = ImageIO.read(new File("C:\\Users\\swhitehead\\Documents\\My Dropbox\\Ponies\\Rainbow_Dash_flying_past_3_S2E16.png")); 
      } catch (IOException ex) { 
       Logger.getLogger(NimbusTest.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      Graphics2D g2d = (Graphics2D) g.create(); 
      // Fill the background, this is VERY important 
      // fail to do this and you will have major problems 
      g2d.setColor(getBackground()); 
      g2d.fillRect(0, 0, getWidth(), getHeight()); 
      // Draw the background 
      g2d.drawImage(bg, 0, 0, this); 
      // Paint the component content, ie the text 
      getUI().paint(g2d, this); 
      g2d.dispose(); 
     } 

    } 
} 

沒有錯。如果你沒有做到這一點,它不僅會使用這個組件,而且可能會把你屏幕上的大部分其他組件都擰緊。

+0

全文區域填充是通過使用'g2d.drawImage(bg,0,0,getWidth(),getHeight(),this);'而且不使用'setColor和fillRect'?爲什麼你使用'Graphics2D'? –

+0

+1我認爲repaint()代替了getUI,但是卻懶得去試一試:-) – mKorbel

+0

'Graphics2D'是一種習慣。我可以使用'g2d.fill(new Rectangle(0,0,getWidth(),getHeight()))',但效果是一樣的。小心。正如我所說的,你負責準備繪畫的圖形環境,這可能很容易就在你的臉上炸開。 – MadProgrammer