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