让我的GUI从另一个类中识别我重写的paintComponent

时间:2013-12-23 07:28:00

标签: java swing user-interface override paintcomponent

编辑:我通过将动画移动到一个单独的线程来实现它。谢谢大家!

我正在自学Java,以便编写一个小小程序来演示海洋的水柱如何按密度分类。我有一个小动画,它自己包含在自己的类中,名为animationBox,我试图从我的GUI中调用它。 GUI是使用netbeans GUI创建器创建的,您只需单击并放下即可。我认为这个问题与Override paintComponent in Netbeans GUI是一个非常相似的问题,但我尝试交换到flowlayout并且问题没有解决。

GUI当前调用animationBox类,它创建自己的JFrame来运行动画。我知道动画的代码正在运行,因为我尝试了一些System.out.println()命令并且除了实际绘制动画的位之外,一切都运行得很顺利。我猜测基于我在这个网站上读到的内容,我的覆盖paintComponent没有被调用。

我的主要困惑是它在animationBox的main方法中工作,但是当我从GUI调用相同的方法时,animationBox中的main方法调用它不起作用。有关如何解决此问题的任何想法,或者我可以获取更多信息的地方?任何帮助将不胜感激!

这是我的代码,我试图用// RELEVANT标记我认为的相关部分

animationBox代码(更多相关内容):

package water_density_gui_2;

import javax.swing.*;
import java.awt.*;


public class animateBox extends JPanel {

//initial starting conditions for the moving box
int x = 200;
int y = 100;

public static void main(String[] args) {
    animateBox gui = new animateBox();
    gui.play(1.025); // random input density as placeholder
}

public void play(double boxDensity) {

    //initialize frame to hold animation
    //RELEVANT
    JFrame frame = new JFrame();
    JPanel panel = new JPanel();
    int height = 212;
    int width = 400;
    frame.setSize(width, height);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(panel); //this seems to do nothing, but I hoped it'd trigger the painting
    DrawPanel draw = new DrawPanel(); //this is the class with overriden paintComponent
    frame.getContentPane().add(draw);
    frame.setVisible(true);
    panel.repaint();//these work when I run animateBox, but the GUI stays white
    draw.repaint();


    //calculate density curve for pycnocline [not relevant to problem]

    pycnoclineCalculations pycno = new pycnoclineCalculations();
    double[][] pycnoclineAndDepth = pycno.summerPycnocline();
    double[] pycnocline = new double[212];
    double[] depth = new double[212];

    for (int i = 0; i < 212; i++) {
        pycnocline[i] = pycnoclineAndDepth[0][i];
        depth[i] = pycnoclineAndDepth[1][i];
    }//end density curve calculations

    //calculate differences between box density and density curve
    //also not relevant to problem

    double[] deltaDensity = new double[212];
    for (int i = 0; i < 212; i++) {
        deltaDensity[i] = Math.abs(pycnocline[i] - boxDensity);
    }
    //get index of minimum difference
    int depthIndex = getMinValueIndex(deltaDensity);
    int targetDepth = (int) Math.round((height * depth[depthIndex] / 2000));
    int deltaDepth = Math.abs(y - targetDepth);
    //catch if box density is not shown on curve
    if (boxDensity < 1.02346) {
        targetDepth = 0;
    } else if (boxDensity > 1.02852) {
        targetDepth = height;
    }//end box density calculations

    //kinda RELEVANT towards end of loop
    //most of the FOR loop is doing the calculations for where the box should go
    //the loop interacts with the drawing by changing x,y & calling draw.repaint()

    //initialize variables for FOR loop
    int t = 0; //time variable for damping term A*e^-kt
    boolean up = false; //direction box is moving
    boolean reached = false; //reached destination
    depthObj temp = new depthObj(y, false, false); //holds current depth, up, reached
    boolean cosine = false; //part of path that requires damping
    int currentTarget = targetDepth; //where the box is going to
    boolean done = false; //if the animation loop should end

    for (int i = 0; !done; i++) {
        if (!reached) { //if not at destination
            temp = incrementDepth(currentTarget, y); 
            y = temp.y;
            reached = temp.reached;
            if (!reached) {
                up = temp.up;
            }
        } else { //if reached, calculate new destination based off of damping term
            double A = deltaDepth / 8;
            double k = 0.5;
            int newTarget = 0;

            //new destination calculations
            if (Math.round(A * Math.pow(2.71828, -k * t)) != 0) {
                if (up & !cosine) {
                    newTarget = targetDepth - (int) Math.round(A * Math.pow(2.71828, -k * t));
                    if (newTarget < 0) {
                        newTarget = 0;
                    }
                    cosine = true;
                } else if (!up & !cosine) {
                    newTarget = targetDepth + (int) Math.round(A * Math.pow(2.71828, -k * t));
                    cosine = true;
                } else if (up & cosine) {
                    newTarget = targetDepth + (int) Math.round(A * Math.pow(2.71828, -k * t));
                } else if (!up & cosine) {
                    newTarget = targetDepth - (int) Math.round(A * Math.pow(2.71828, -k * t));
                    if (newTarget < 0) {
                        newTarget = 0;
                    }
                }
                t++; //increment time for damping
                temp = incrementDepth(currentTarget, y);
                currentTarget = newTarget;
                y = temp.y;
                reached = false;

            } else {

                //  System.out.println("Damping constant is zero");
                x++; //move box off of screen sideways

                if (x > 410) { //if box is off screen, get rid of frame
                    frame.setVisible(false); //RELEVANT....?
                    frame.dispose();
                    done = true; //end animation
                }
            }
        }

        //DEFINITELY RELEVANT PART
        draw.repaint();  //tells the panel to redraw itself so we can see the box in new location
        //should trigger with every iteration of the FOR loop. Works in this code, not in GUI. The frame is created, but stays white the hold time

        try {
            Thread.sleep(25); //slows down animation slightly
        } catch (Exception e) {
        }
    }
}

//increments the depth position of the box [probably not relevant]

public static depthObj incrementDepth(int target, int y) {
    boolean reached = false;
    boolean up;
    if (y < target) {
        y++;
        up = false;
    } else if (y > target) {
        y--;
        up = true;
    } else {
        reached = true;
        up = true; //default, caught above
    }
    depthObj temp = new depthObj(y, up, reached);
    return temp;
}

//calculates sigma-t density value from the water's temperature and salinity signatures
//probably not relevant to drawing problem

public static double calculateDensity(double salinity, double temp) {
    /**       rhos = density in kg/m^3 as a function of temperature and salinity
     *S = salinity in g/kg
     *rhos = rho + AS + BS^(3/2) + CS^2
     *A = 8.24493E-1 - 4.0899E-3*T + 7.6438E-5*T^2 -8.2467E-7*T^3 + 5.3675E-9*T^4
     *B = -5.724E-3 + 1.0227E-4*T - 1.6546E-6*T^2
     *C = 4.8314E-4
     * rho = density in kg/m^3 as a function of temperature
     *T = temperature in C
     *rho = 1000(1 - (T+288.9414)/(508929.2*(T+68.12963))*(T-3.9863)^2)
     */
    double density = 0;
    double rho = 0;
    double eqn1 = 0;
    double eqn2 = 0;
    double eqn3 = 0;
    double rhos = 0;

    rho = 1000 * (1 - ((temp + 288.9419) / (508929.2 * (temp + 68.12963))) * (Math.pow((temp - 3.9863), 2)));
    eqn1 = 0.824493 - temp * 0.0040899 + Math.pow(temp, 2) * Math.pow(10, -5) * 7.6438 - (Math.pow(10, -7) * 8.2467 * Math.pow(temp, 3)) + 5.3675 * Math.pow(10, -9) * Math.pow(temp, 4);
    eqn2 = -5.724 * Math.pow(10, -3) + 1.0227 * Math.pow(10, -4) * temp - 1.6546 * Math.pow(10, -6) * Math.pow(temp, 2);
    eqn3 = 4.8314 * Math.pow(10, -4);
    rhos = rho + eqn1 * salinity + eqn2 * Math.pow(salinity, (3 / 2)) + eqn3 * Math.pow(salinity, 2);
    density = rhos - 1000;
    density = (double) 1 + (Math.floor(density * 100) / 100) / 1000;
    return density;
}

//gets the index of the minimum value of an array
//also probably not relevant

public static int getMinValueIndex(double[] numbers) {
    double minValue = numbers[0];
    int minValueIndex = 0;
    for (int i = 1; i < numbers.length; i++) {
        if (numbers[i] < minValue) {
            minValue = numbers[i];
            minValueIndex = i;
        }
    }
    return minValueIndex;
}

//DEFINITELY RELEVANT PART
//draws the animation. Overriding paintComponent works when I run this program, but not in the GUI. In the GUI the frame gets created, but stays white the whole time

   class DrawPanel extends JPanel {

    @Override
    public void paintComponent(Graphics g) {

        super.paintComponent(g);//call method on...JPanel? Not exactly sure what this does
        Graphics2D g2d = (Graphics2D) g; 
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

        //get dimensions of window
        int w = getWidth();
        int h = getHeight();
        int h1 = (int) Math.round(h * 200 / 2000); //first color change point
        int h2 = (int) Math.round(h * 600 / 2000); //second color change point

        //add background gradients (NOTE: color corresponds to pycnocline)
        Color color1 = Color.RED;
        Color color2 = Color.BLUE;
        GradientPaint gp = new GradientPaint(0, 0, color1, 0, h1, color1);
        GradientPaint gp2 = new GradientPaint(0, h1, color1, 0, h2, color2);
        GradientPaint gp3 = new GradientPaint(0, h2, color2, 0, h, color2);
        g2d.setPaint(gp);
        g2d.fillRect(0, 0, w, h1);
        g2d.setPaint(gp2);
        g2d.fillRect(0, h1, w, h2);
        g2d.setPaint(gp3);
        g2d.fillRect(0, h2, w, h);

        //add box
        g.setColor(Color.BLACK);
        g.fillRect(x - 2, y - 2, 19, 19);
        g.setColor(Color.GREEN);
        g.fillRect(x, y, 15, 15);
    }
}

//object to hold information about depth, direction, if at destination
// probably not relevant to problem
static class depthObj {

    int y = 0;
    boolean up = false;
    boolean reached = false;

    public depthObj(int ycur, boolean direction, boolean there) {
        this.y = ycur;
        this.up = direction;
        this.reached = there;
    }
}

}


GUI代码(最后的相关部分):

 //not really relevant....? 

    package water_density_gui_2;
    import java.awt.*;
    import javax.swing.*;

    public class thermohalineCirculationGUI2 extends javax.swing.JFrame {

/** Creates new form WaterDensity */
public thermohalineCirculationGUI2() {
    initComponents();
}

/** This method is called from within the constructor to
 * initialize the form.
 * WARNING: Do NOT modify this code. The content of this method is
 * always regenerated by the Form Editor.
 */
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {

    seasonsButtons = new javax.swing.ButtonGroup();
    tempPermLabel = new javax.swing.JLabel();
    tempTextField = new javax.swing.JFormattedTextField();
    salPermLabel = new javax.swing.JLabel();
    salTextField = new javax.swing.JFormattedTextField();
    densityPermLabel = new javax.swing.JLabel();
    densityLabel = new javax.swing.JLabel();
    runButton = new javax.swing.JButton();
    seasonLabel = new javax.swing.JLabel();
    summerRadioButton = new javax.swing.JRadioButton();
    winterRadioButton = new javax.swing.JRadioButton();
    runSimulationButton = new javax.swing.JButton();
    jMenuBar1 = new javax.swing.JMenuBar();
    fileMenu = new javax.swing.JMenu();
    exitMenuComand = new javax.swing.JMenuItem();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    setTitle("Water_Density_GUI");
    setBounds(new java.awt.Rectangle(0, 0, 0, 0));
    setMinimumSize(new java.awt.Dimension(400, 33));
    setResizable(false);
    getContentPane().setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));

    tempPermLabel.setText("Temperature (C):");
    getContentPane().add(tempPermLabel);

    double defaultTemp = 20;
    tempTextField.setValue(new Double(defaultTemp));
    tempTextField.setColumns(3);
    getContentPane().add(tempTextField);

    salPermLabel.setText("Salinity:");
    getContentPane().add(salPermLabel);

    double defaultSal = 35;
    salTextField.setValue(new Double(defaultSal));
    salTextField.setColumns(3);
    getContentPane().add(salTextField);

    densityPermLabel.setText("Sigma-t:");
    getContentPane().add(densityPermLabel);

    densityLabel.setText("_______");
    getContentPane().add(densityLabel);

    runButton.setText("Calculate Density");
    runButton.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            runButtonActionPerformed(evt);
        }
    });
    getContentPane().add(runButton);

    seasonLabel.setText("Season:");
    getContentPane().add(seasonLabel);

    seasonsButtons.add(summerRadioButton);
    summerRadioButton.setText("Summer");
    getContentPane().add(summerRadioButton);

    seasonsButtons.add(winterRadioButton);
    winterRadioButton.setText("Winter");
    getContentPane().add(winterRadioButton);

    runSimulationButton.setText("Run Simulation");
    runSimulationButton.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            runSimulationButtonActionPerformed(evt);
        }
    });
    getContentPane().add(runSimulationButton);

    fileMenu.setText("File");

    exitMenuComand.setText("Exit");
    exitMenuComand.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            exitMenuComandActionPerformed(evt);
        }
    });
    fileMenu.add(exitMenuComand);

    jMenuBar1.add(fileMenu);

    setJMenuBar(jMenuBar1);

    pack();
}// </editor-fold>

private void runButtonActionPerformed(java.awt.event.ActionEvent evt) {                                          
    // update sigma-t value on GUI when run button is pressed
    if (!(tempTextField.getText().equals("") | salTextField.getText().equals(""))) {
        double temp = Double.parseDouble(tempTextField.getText());
        double sal = Double.parseDouble(salTextField.getText());
        double density = calculateDensity(sal, temp);
        densityLabel.setText(Double.toString(density));


    } else {
        densityLabel.setText("N/a");
    }



}                                         

private void exitMenuComandActionPerformed(java.awt.event.ActionEvent evt) {                                               
    // exit GUI
    System.exit(0);
}                                              

    //RELEVANT

   //This is the method run when the button is pushed to start the animation

   private void runSimulationButtonActionPerformed(java.awt.event.ActionEvent evt) {
    //try to retrieve density value. If that fails, do nothing
    try {

        double density = Double.parseDouble(densityLabel.getText());
        startAnimation(density); //this method is below

    } catch (Exception e) {
    }

}

//no longer relevant until next break
public static double calculateDensity(double salinity, double temp) {
    /**       rhos = density in kg/m^3 as a function of temperature and salinity
     *S = salinity in g/kg
     *rhos = rho + AS + BS^(3/2) + CS^2
     *A = 8.24493E-1 - 4.0899E-3*T + 7.6438E-5*T^2 -8.2467E-7*T^3 + 5.3675E-9*T^4
     *B = -5.724E-3 + 1.0227E-4*T - 1.6546E-6*T^2
     *C = 4.8314E-4
     * rho = density in kg/m^3 as a function of temperature
     *T = temperature in C
     *rho = 1000(1 - (T+288.9414)/(508929.2*(T+68.12963))*(T-3.9863)^2)
     */
    double density = 0;
    double rho = 0;
    double eqn1 = 0;
    double eqn2 = 0;
    double eqn3 = 0;
    double rhos = 0;

    rho = 1000 * (1 - ((temp + 288.9419) / (508929.2 * (temp + 68.12963))) * (Math.pow((temp - 3.9863), 2)));
    eqn1 = 0.824493 - temp * 0.0040899 + Math.pow(temp, 2) * Math.pow(10, -5) * 7.6438 - (Math.pow(10, -7) * 8.2467 * Math.pow(temp, 3)) + 5.3675 * Math.pow(10, -9) * Math.pow(temp, 4);
    eqn2 = -5.724 * Math.pow(10, -3) + 1.0227 * Math.pow(10, -4) * temp - 1.6546 * Math.pow(10, -6) * Math.pow(temp, 2);
    eqn3 = 4.8314 * Math.pow(10, -4);
    rhos = rho + eqn1 * salinity + eqn2 * Math.pow(salinity, (3 / 2)) + eqn3 * Math.pow(salinity, 2);
    density = rhos - 1000;
    density = (double) 1 + (Math.floor(density * 100) / 100) / 1000;
    return density;

}

/**
 * @param args the command line arguments
 */
public static void main(String args[]) {
    java.awt.EventQueue.invokeLater(new Runnable() {

        public void run() {
            new thermohalineCirculationGUI2().setVisible(true);
        }
    });
}
// Variables declaration - do not modify
private javax.swing.JLabel densityLabel;
private javax.swing.JLabel densityPermLabel;
private javax.swing.JMenuItem exitMenuComand;
public javax.swing.JMenu fileMenu;
public javax.swing.JMenuBar jMenuBar1;
public javax.swing.JButton runButton;
private javax.swing.JButton runSimulationButton;
private javax.swing.JLabel salPermLabel;
private javax.swing.JFormattedTextField salTextField;
private javax.swing.JLabel seasonLabel;
private javax.swing.ButtonGroup seasonsButtons;
private javax.swing.JRadioButton summerRadioButton;
public javax.swing.JLabel tempPermLabel;
private javax.swing.JFormattedTextField tempTextField;
private javax.swing.JRadioButton winterRadioButton;
// End of variables declaration


   //RELEVANT

   //This is where I try to run the animation
    public void startAnimation(double density) {

    animateBox gui = new animateBox();
    int height = 212; //dimensions of frame I want
    int width = 400;

    gui.play(density); //this calls the play() method from animateBox
}  

}

其他代码(用于计算pycnocline,未在图纸中使用)

      package water_density_gui_2;


     public class pycnoclineCalculations {

    public static void main(String[] args){
        double[][] pycnocline = summerPycnocline();

     }
     public static double[][] summerPycnocline() {
        double[] pycnocline = new double[212];
        double[] depth = {0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 2000, 3000, 4000};
        double[] thermocline = {27, 27, 27, 24, 20, 15, 10, 8, 7, 6, 5, 5, 2, 2};
        double[] halocline = {35, 35, 35, 34.9, 34.8, 34.7, 34.4, 34.4, 34.4, 34.45, 34.5, 34.5, 34.5, 34.5};
        double[] pycnoclineDiscreet = new double[12];

        for (int i = 0; i < 12; i++) {
            pycnoclineDiscreet[i] = calculateDensity(halocline[i], thermocline[i]);

        }
        for (int i = 0; i < 11; i=i+1) {
            double[] interpdVals = interp2dens(pycnoclineDiscreet[i], pycnoclineDiscreet[i + 1], depth[i], depth[i + 1], 10);

            for (int j = 0; j < 10; j++) {
                pycnocline[i*10 + j] = interpdVals[j];
            }
        }

        double[] temp = interp2dens(pycnoclineDiscreet[10],pycnoclineDiscreet[11],depth[10],depth[11],102);

        for(int i=0;i<102;i++){
            pycnocline[i+110]=temp[i];
        }

double[] depthsFull=new double[212];
        for(int k=0;k<212;k++){
          depthsFull[k] = k*10;
        }

        double[][] pycnoclineAndDepth = {pycnocline, depthsFull};
        return pycnoclineAndDepth;
    }


     public static double[] interp2dens(double val1, double val2, double depth1, double depth2, int numPointsWanted) {

        int size = numPointsWanted;
        double[] interpdVal = new double[size];
        //y = mx+b
        //slope = y2-y1/(x2-x1)
        //intercept b = y-mx
        double slope = (val2 - val1) / (depth2 - depth1);
        double intercept = val2 - slope * depth2;
        double distanceStep = Math.abs(depth2 - depth1) / numPointsWanted;
        interpdVal[0]=val1;
        interpdVal[size-1]=val2;
        for(int i =1;i<size-1;i++){
            interpdVal[i]=slope*(depth1+distanceStep*i)+intercept;
        }       
        return interpdVal;
    }


    public static double calculateDensity(double salinity, double temp) {
        /**       rhos = density in kg/m^3 as a function of temperature and salinity
         *S = salinity in g/kg
         *rhos = rho + AS + BS^(3/2) + CS^2
         *A = 8.24493E-1 - 4.0899E-3*T + 7.6438E-5*T^2 -8.2467E-7*T^3 + 5.3675E-9*T^4
         *B = -5.724E-3 + 1.0227E-4*T - 1.6546E-6*T^2
         *C = 4.8314E-4
         * rho = density in kg/m^3 as a function of temperature
         *T = temperature in C
         *rho = 1000(1 - (T+288.9414)/(508929.2*(T+68.12963))*(T-3.9863)^2)
         */
        double density = 0;
        double rho = 0;
        double eqn1 = 0;
        double eqn2 = 0;
        double eqn3 = 0;
        double rhos = 0;

        rho = 1000 * (1 - ((temp + 288.9419) / (508929.2 * (temp + 68.12963))) * (Math.pow((temp - 3.9863), 2)));
        eqn1 = 0.824493 - temp * 0.0040899 + Math.pow(temp, 2) * Math.pow(10, -5) * 7.6438 - (Math.pow(10, -7) * 8.2467 * Math.pow(temp, 3)) + 5.3675 * Math.pow(10, -9) * Math.pow(temp, 4);
        eqn2 = -5.724 * Math.pow(10, -3) + 1.0227 * Math.pow(10, -4) * temp - 1.6546 * Math.pow(10, -6) * Math.pow(temp, 2);
        eqn3 = 4.8314 * Math.pow(10, -4);
        rhos = rho + eqn1 * salinity + eqn2 * Math.pow(salinity, (3 / 2)) + eqn3 * Math.pow(salinity, 2);
        density = rhos - 1000;
        density = (double) 1 + (Math.floor(density * 100) / 100) / 1000;
        return density;

    }
}

0 个答案:

没有答案