2009-02-02 62 views
3

我正在研究一個簡單的小擺動組件,並且我正在撕掉我的頭髮,試圖弄清爲什麼我的繪畫方法不起作用。Java Paint方法不繪製?

這個組件背後的想法是它是一個帶標籤的小型JPanel。背景(標籤後面)應該是白色的,左側的彩色矩形表示兩個度量的比例:「實際」和「預期」。

如果你有一堆這些組件垂直對齊,它們會形成一個條形圖,由橫條組成。

這種事情應該是超級簡單的。

總之,這裏的代碼:

package com.mycompany.view; 

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Rectangle; 

import javax.swing.JLabel; 
import javax.swing.JPanel; 

public class BarGraphPanel extends JPanel { 

    private static final Color BACKGROUND = Color.WHITE; 
    private static final Color FOREGROUND = Color.BLACK; 

    private static final Color BORDER_COLOR = new Color(229, 172, 0); 
    private static final Color BAR_GRAPH_COLOR = new Color(255, 255, 165); 

    private int actual = 0; 
    private int expected = 1; 

    private JLabel label; 

    public BarGraphPanel() { 
     super(); 
     label = new JLabel(); 
     label.setOpaque(false); 
     label.setForeground(FOREGROUND); 
     super.add(label); 
     super.setOpaque(true); 
    } 

    public void setActualAndExpected(int actual, int expected) { 
     this.actual = actual; 
     this.expected = expected; 
    } 

    @Override 
    public void paint(Graphics g) { 

     double proportion = (expected == 0) ? 0 : ((double) actual)/expected; 
     Rectangle bounds = super.getBounds(); 

     g.setColor(BACKGROUND); 
     g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height); 

     g.setColor(BAR_GRAPH_COLOR); 
     g.fillRect(bounds.x, bounds.y, (int) (bounds.width * proportion), bounds.height); 

     g.setColor(BORDER_COLOR); 
     g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height); 

     label.setText(String.format("%s of %s (%.1f%%)", actual, expected, proportion * 100)); 
     super.paint(g); 
     g.dispose(); 
    } 

} 

而這裏的簡單的測試工具:

package com.mycompany.view; 

import java.awt.Dimension; 
import java.awt.GridLayout; 

import javax.swing.JFrame; 
import javax.swing.UIManager; 

public class MyFrame extends JFrame { 

    public MyFrame() { 
     super(); 
     super.setLayout(new GridLayout(3, 1)); 
     super.setPreferredSize(new Dimension(300, 200)); 

     BarGraphPanel a = new BarGraphPanel(); 
     BarGraphPanel b = new BarGraphPanel(); 
     BarGraphPanel c = new BarGraphPanel(); 

     a.setActualAndExpected(75, 100); 
     b.setActualAndExpected(85, 200); 
     c.setActualAndExpected(20, 300); 

     super.add(a); 
     super.add(b); 
     super.add(c); 
    } 

    public static void main(String[] args) { 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGUI(); 
     } 
     }); 
    } 

    public static void createAndShowGUI() { 

     try { 
     UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
     } catch (Throwable t) { } 

     MyFrame frame = new MyFrame(); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

} 

測試工具創建一個簡單的框架,然後添加這三個控件。

這些標籤都被正確渲染,這表明paint()方法實際上被調用,但矩形並未被繪製到Graphics對象。

我在做什麼錯?

爲什麼Swing編程吸這麼多?


這是我的最終代碼。謝謝大家,爲您的幫助!

public void paintComponent(Graphics g) { 

    double proportion = (expected == 0) ? 0 : ((double) actual)/expected; 

    Rectangle bounds = super.getBounds(); 

    g.setColor(BACKGROUND); 
    g.fillRect(0, 0, bounds.width, bounds.height); 

    g.setColor(BAR_GRAPH_COLOR); 
    g.fillRect(0, 0, (int) (bounds.width * proportion), bounds.height); 

    g.setColor(BORDER_COLOR); 
    g.drawRect(0, 0, bounds.width - 1, bounds.height - 1); 

    FontMetrics metrics = g.getFontMetrics(); 
    String label = String.format("%s of %s (%.1f%%)", actual, expected, proportion * 100); 
    Rectangle2D textBounds = metrics.getStringBounds(label, g); 

    g.setColor(FOREGROUND); 
    g.drawString(label, 5, (int) ((bounds.height + textBounds.getHeight())/2)); 
} 
+0

嘗試刪除「super.paint(g)」和「g.dispose()」,看看會發生什麼。 – 2009-02-02 18:17:09

+0

有趣。如果我刪除「super.paint(g)」和「g.dispose()」,那麼我得到正確的背景矩形,但是我在前景中丟失了標籤的渲染。 – benjismith 2009-02-02 18:21:36

+0

嗯......如何在畫棒之前加上「super.paint(g)」?或者,您可以使用「g.drawString()」來呈現文本。 – 2009-02-02 18:26:43

回答

4

我想你已經幾乎回答了你自己的問題的意見,以及David的回答。將paint(Graphics g)更改爲paintComponent(Graphics g)並刪除該方法的最後兩行,並且您應該沒問題。

編輯:奇怪的是,這隻適用於三個第一欄。更多測試正在進行中...

順便說一下,您在邊框繪製代碼中出現了錯誤的錯誤。它應該是:

g.setColor(BORDER_COLOR); 
g.drawRect(bounds.x, bounds.y, bounds.width - 1, bounds.height - 1); 

EDIT2:好,知道了。你的全paintComponent方法應該如下:

@Override 
public void paintComponent(Graphics g) { 
    double proportion = (expected == 0) ? 0 : ((double) actual)/expected; 
    Rectangle bounds = super.getBounds(); 
    g.setColor(BACKGROUND); 
    g.fillRect(0, 0, bounds.width, bounds.height); 
    g.setColor(BAR_GRAPH_COLOR); 
    g.fillRect(0, 0, (int) (bounds.width * proportion), bounds.height); 
    g.setColor(BORDER_COLOR); 
    g.drawRect(0, 0, bounds.width-1, bounds.height-1); 
    label.setText(String.format("%s of %s (%.1f%%)", actual, expected, proportion * 100)); 
} 

注意給g.fillRect()g.drawRect()座標是相對於組件,因此他們必須在(0,0)開始。

不,我不能幫你解決你的最後一個問題,雖然我感到你的痛苦。 :)

0

不知道這是你的問題的根源,但在Swing你應該重寫paintComponent(Graphics2D),而不是...

1

在你的JPanel中,你調用了super.setOpaque(true)。當您調用super.paint()並覆蓋您的retangles時,JPanel將完全填充背景。

0

如果有什麼,我想你應該打電話給super.paint(g);在你的方法的頂部,而不是在最底部。超類可能會吸引你的東西。