2012-05-31 37 views
3

由於本週六在學校項目上工作時,遇到了我遇到過的最煩人的bug。我似乎無法在萬維網上的任何地方找到解決方案。即使我的好朋友谷歌似乎讓我失望。所以,這裏的問題:轉換後的JTabbedPane轉換內容

我正在與JTabbedPane。在這個JTabbedPane中,我會展示不同的JPanes,每個都顯示他們的信息。在其中一個JPane中,我正在繪製一個條形圖。

分別測試條形圖時,它一切正常。當我在JTabbedPane的正確選項卡中加載我的信息時也會這樣。但是,只要切換回此選項卡,繪圖過程中的柱狀圖就會向上移動,並且看起來都是扭曲的東西(參見圖片)。

我知道一個事實,即我正在繪製正確的coördinates,所以它必須是我的JPanel取代JTabbedPane的選項卡。你們有什麼想法是什麼導致這種奇怪的行爲?

enter image description here 右:它應該如何。左:切換回此選項卡後的外觀。

我BarGraphPanel類是一個真正的混亂,這裏是代碼:

/* 
* To change this template, choose Tools | Templates 
* and open the template in the editor. 
*/ 
package gui; 

import java.awt.Color; 
import java.awt.FontMetrics; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.geom.AffineTransform; 
import java.text.DecimalFormat; 
import java.util.ArrayList; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 

/** 
* 
* @author Scuba Kay 
*/ 
public class BarGraphPanel extends JPanel implements ManagementPanel { 


private ArrayList<String[]> info; 
    private String infoName; 
    private double maxValue; 
    private int size; 
    private int barWidth; 
    private double left; 
    private double right; 
    private double width; 
    private double height; 
    private double bottom; 
    private double top; 
    private int barSpacing; 
    private double barPart; 
    private double graphHeight; 
    private double graphWidth; 
    private int cap; 

    public BarGraphPanel(){ 
     super(); 

     width = 600; 
     height = 480; 
     setSize((int) width, (int) height); 

     // The maximum number of results to show 
     cap = 30; 

     this.infoName = "Management information"; 
     this.add(new JLabel("This query is not suited for Bar Graph view: please select another one.")); 
    } 

    /** 
    * Sets both x and y, min and max and the info list 
    * @author Kay van Bree 
    * @param info 
    */ 
    @Override 
    public void setManagementInfo(ArrayList<String[]> info) { 
     reset(); 
     this.info = info; 

     // Set important values 
     this.maxValue = getMaxValue(info); 
     this.size = info.size(); 

     setSizes(); 
     repaint(); 
    } 

    /** 
    * Resets the panel, taken from TablePanel 
    * @author Joepe Kemperman 
    */ 
    public void reset() { 
     removeAll(); 
     invalidate(); 
     validate(); 
    } 

    /** 
    * Set the sizes needed for calculating bar heights etc. 
    * @author Kay van Bree 
    */ 
    protected void setSizes(){  
     left = (width/100) * 7; 
     right = width - left*3; 
     top = (height/100) * 7; 
     bottom = height - top*3; 

     // The dimensions of the graph 
     graphHeight = bottom - top; 
     graphWidth = right - left; 

     // barWidth is... Just guess what it is. 
     barWidth = (int) ((double) (graphWidth/size) * 0.95); 

     // barSpacing is the space between the bars 
     barSpacing = (int) (graphWidth - (barWidth*size))/size; 
     if(barSpacing == 0){ 
      barSpacing++; 
      barWidth--; 
     } 

     // barPart is the height of a bar of value 1 
     barPart = graphHeight/maxValue; 
    } 

    /** 
    * Return the max value of the info arraylist 
    * @author Kay van Bree 
    * @param info 
    */ 
    private int getMaxValue(ArrayList<String[]> info){ 
     int max = 0; 
     for(String[] row: info){  
      if(Integer.valueOf(row[1]) > max){ 
       max = Integer.valueOf(row[1]); 
      } 
     } 
     return max; 
    } 

    /** 
    * Draw the damn thing! 
    * @author Kay van Bree 
    * @param g 
    */ 
    @Override 
    protected void paintComponent(Graphics g){ 
     super.paintComponent(g); 
     if(info != null){ 
      g.setColor(Color.BLACK); 
      drawTitle(g); 
      drawBlocks(g); 
      if(size <= cap){ 
       drawBars(g); 
      } else { 
       drawError(g); 
      } 
      drawAxes(g); 
     } else { 
      this.setInformationNotSuitable(); 
     } 
    } 

    /** 
    * Set an error displaying to many results 
    * @author Kay van Bree 
    * @param g 
    */ 
    private void drawError(Graphics g){ 
     g.setColor(Color.BLACK); 
     g.drawString("Too many results to show!", (int)(right-left*2)/2, (int)(bottom-top*2)/2); 
    } 

    /** 
    * Draw the names under the bars 
    * @author Kay van Bree 
    * @param g 
    */ 
    private void drawName(Graphics g, String name, int x){ 
     Graphics2D g2d = (Graphics2D)g; 

     // clockwise 90 degrees 
     AffineTransform at = new AffineTransform(); 
     // thanks to M.C. Henle for the bug fix! 
     at.setToRotation(Math.PI/2.0, x + (barWidth/4), bottom + 3); 
     g2d.setTransform(at); 

     g2d.setColor(Color.BLACK); 
     g2d.drawString(name, (int) (x + (barWidth/4)), (int) bottom + 3); 

     g2d.setTransform(new AffineTransform()); 
    } 

    /** 
    * Draw the lines behind the bars 
    * @author Kay van Bree 
    * @param g 
    */ 
    private void drawBlocks(Graphics g){ 
     g.setColor(Color.lightGray); 
     // Ten parts 
     double part = maxValue/10; 
     double total = maxValue; 

     // Draw the numbers 
     for(int i=0; i<10; i++){ 
      double y = (((bottom-top)/10)*i)+top; 
      g.drawLine(((int) left)-5, (int) y, ((int) right), (int) y); 
     } 
     g.drawLine((int) right, (int) top, (int) right, (int) bottom); 
    } 

    /** 
    * Draw the title of the Graph 
    * @author Kay van Bree 
    * @param g 
    */ 
    private void drawTitle(Graphics g){ 
     int tLeft = 100; 
     g.drawString(infoName, tLeft, (int) top/2); 
    } 

    /** 
    * Draw the axes of this Bar Graph 
    * @author Kay van Bree 
    * @param g 
    */ 
    private void drawAxes(Graphics g){ 
     g.setColor(Color.BLACK); 
     // draw lines from (x, y) to (x, y) 
     g.drawLine((int) left, (int) top, (int) left, (int) bottom); 
     g.drawLine((int) left, (int) bottom, (int) right, (int) bottom); 

     // Ten parts 
     double part = maxValue/10; 
     double total = maxValue; 

     // Draw the numbers 
     for(int i=0; i<10; i++){ 
      double y = (((bottom-top)/10)*i)+top; 
      String number = round(total); 
      FontMetrics fontMetrics = g.getFontMetrics(); 
      g.drawString(number, (int) (left * 0.80) - fontMetrics.stringWidth(number), ((int) y)+5); 
      total = (total - part); 
      g.drawLine(((int) left)-5 , (int) y, ((int) left), (int) y); 
     } 
    } 

    /** 
    * Rounds the number to 1 decimal 
    * @author Kay van Bree 
    * @param number 
    * @return 
    */ 
    private String round(double number){ 
     DecimalFormat df = new DecimalFormat("#.#"); 
     Double dubbel = new Double(number); 
     return df.format(dubbel); 
    } 

    /** 
    * Round a number, make it int 
    * @author Kay van Bree 
    * @param number 
    * @return 
    */ 
    private int roundToInt(double number){ 
     DecimalFormat df = new DecimalFormat("#"); 
     Double dubbel = new Double(number); 
     return Integer.valueOf(df.format(dubbel)); 
    } 


    /** 
    * We need info right? 
    * Then draw the damn bars already! 
    * @author Kay van Bree 
    * @param g 
    */ 
    private void drawBars(Graphics g){  
     double currentX = left + barSpacing + 1; 
     for(String[] row: info){ 
      double value = Integer.valueOf(row[1]); 
      double barHeight = (value * barPart); 

      System.out.println("Value: " + value + " height: " + barHeight + " top: " + top); 
      double barStart = bottom - barHeight; 
      System.out.println("Barstart: " + barStart); 
      barHeight = ((int) bottom - (int) barStart); 
      g.setColor(Color.BLUE); 
      g.fillRect((int) currentX, (int) barStart, (int) barWidth, roundToInt(barHeight)); 
      drawName(g, row[0], (int) currentX); 

      currentX = (currentX + barSpacing + barWidth); 
     } 
    } 

    public void setInformationNotSuitable() { 
    //  JOptionPane.showMessageDialog(this, "This query is not suited for Bar Graph view. Please select another", "INSANE WARNING!", JOptionPane.WARNING_MESSAGE); 
    } 
} 

一些有益的信息:

setManagementInformation由JTabbedPane中調用一次。在這裏,它加載的所有內容(也其他標籤)

編輯 奧凱,所以至強的回答幾乎固定我的問題。我每次切換回該選項卡時,我的圖形條都會完美對齊。但是,切換回來時,欄下方的名稱仍然在移動。這裏是我更新的代碼:

/** 
* Draw the names under the bars 
* @author Kay van Bree 
* @param g 
*/ 
private void drawName(Graphics g, String name, int x){ 
    Graphics2D g2d = (Graphics2D) g.create(); 

    // Clockwise 90 degrees 
    AffineTransform at = new AffineTransform(); 
    // Rotate the text 
    at.setToRotation(Math.PI/2.0, x + (barWidth/4), bottom + 3); 
    AffineTransform prev = g2d.getTransform(); 
    g2d.setTransform(at); 

    g2d.setColor(Color.BLACK); 
    g2d.drawString(name, (int) (x + (barWidth/4)), (int) bottom + 3); 

    g2d.dispose(); 
} 

那麼,這是否也有一些做的的AffineTransform,並沒有任何人有一個解決這個問題?

+0

僅供參考,在將來,[功課]標籤添加到事情學校項目。 (這次我已經爲你添加了它。) –

+0

我會懷疑在設置組件的大小和JTabbedPane的默認佈局管理器之間存在衝突。不是在構造函數中設置大小,而是設置首選大小並告訴我們它是如何發生的。 –

+0

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

回答

1

之後做一些研究,並與至強的答案的幫助:在OTN Discussion Forums發現

/** 
* Draw the names under the bars 
* @author Kay van Bree 
* @param g 
*/ 
private void drawName(Graphics g, String name, int x){ 
    Graphics2D g2d = (Graphics2D) g.create(); 

    // Rotate 
    g2d.rotate(Math.PI/2.0, x + (barWidth/4), bottom + 3); 

    // Print 
    g2d.setColor(Color.BLACK); 
    g2d.drawString(name, (int) (x + (barWidth/4)), (int) bottom + 3); 

    // Reset transformation 
    g2d.dispose(); 
} 

答:

你忽略當前變換的圖形,請使用以下,而不是一個setTransform的() :

g2D.rotate(-Math.PI/2.0, 0, 0); 

這解決了我所有的問題。

3

好的。這是棘手的:

問題是drawName方法 - 您正在轉換graphics實例,而不是恢復它 - 你只是重置變換矩陣(所有值爲0)。

你應該恢復它:

private void drawName(Graphics g, String name, int x) { 
    Graphics2D g2d = (Graphics2D) g; 

    // clockwise 90 degrees 
    AffineTransform at = new AffineTransform(); 
    // thanks to M.C. Henle for the bug fix! 
    at.setToRotation(Math.PI/2.0, x + (barWidth/4), bottom + 3); 
    AffineTransform prev = g2d.getTransform(); 
    g2d.setTransform(at); 

    g2d.setColor(Color.BLACK); 
    g2d.drawString(name, (int) (x + (barWidth/4)), (int) bottom + 3); 

    g2d.setTransform(prev); 
} 

,或者你甚至可以使用:

Graphics2D g2d = (Graphics2D) g.create(); 
    ... 
    // free to manipulate Graphics2D 
    ,,, 
    d2d.dispose(); 

我建議使用JFreeChart,而不是寫自己的圖表庫。

+1

用於提示JFreeChart的+1。 –

+0

問題是,我們不能使用任何第三方庫,因爲這是一個學校項目。否則,我可能會使用它。 –

+0

謝謝,這固定了我的酒吧和斧頭!然而,名字仍然是扭曲的,所以我編輯了我的問題。 –

0

稍微注意一下,如果有人將直接使用AffineTransform

protected void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    final Graphics2D g2d = (Graphics2D) g; 
    final AffineTransform oldT = g2d.getTransform(); 
    try { 
     final AffineTransform t = g2d.getTransform(); // returns a copy! of current transform 
     t.concatenate(viewMatrix); // so we can modify it 
     g2d.setTransform(t); 
     // draw... 
    } finally { 
     // restoring transform 
     g2d.setTransform(oldT); 
    } 
} 

處置Graphics2D是不是在這種情況下neccessary