编程语言
首页 > 编程语言> > java-JTabbedPane的内容在切换回后移位

java-JTabbedPane的内容在切换回后移位

作者:互联网

在上周六的一个学校项目中,我遇到了迄今为​​止从未遇到过的最烦人的错误.我似乎无法在万维网上的任何地方找到解决方案.甚至我的好朋友Google都让我失望.所以,这是一个问题:

我正在使用JTabbedPane.在此JTabbedPane中,我将显示不同的JPanes,每个JPanes都显示其信息.在一个JPanes中,我正在绘制一个条形图.

分别测试条形图时,一切正常.当我在JTabbedPane的右侧选项卡中加载我的信息时,也是如此.但是,一旦我切换回该选项卡,条形图就会在绘画过程中上移,并且看起来像是扭曲的东西(参见图片).

我知道事实上我一直在吸引合适的同事,所以这一定是我的JPanel取代了JTabbedPane的标签.你们对导致这种奇怪行为的原因有任何想法吗?

正确:应该如何.左:切换回此标签后的外观.

我的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也有关系,有人解决此问题吗?

解决方法:

好.那很棘手:

问题是drawName方法-您正在转换图形实例而不是还原它-您只需重置转换矩阵(所有值都为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,而不要编写自己的Charts库.

标签:jtabbedpane,swing,jpanel,java
来源: https://codeday.me/bug/20191101/1982310.html