Question

I have this code, and I want it to repaint so that when the user enters the details it prints out the acceleration and fuel consumption (calculated in another class), I can see it works because i have system.out.println's showing the values but they do not get updated to my JFrame.

window() is called in another constructor in another class, the JFrame opens fine but does not update

Any ideas?

Thanks

public class Vehicle extends JFrame {

    protected static double horsepower;
    protected static double aerodynamics;
    protected static double weight;
    protected static double acceleration;
    protected static double topspeed;
    protected double fuelconsumption;
    protected String userHorsepower;
    protected String userWeight;
    protected String userTopspeed;
    protected String userInput = "No Current Selection";

    JPanel panel = new JPanel();
    JButton Van = new JButton("Add Van");



    public Vehicle(double horsepower, double weight, double aerodynamics, double topspeed){
        super();
    }

    public void window(){

        JButton Van = new JButton("Add Van Car");
        Van.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {

                userHorsepower = JOptionPane.showInputDialog("Enter Horsepower");
                horsepower = Double.parseDouble(userHorsepower);
                userWeight = JOptionPane.showInputDialog("Enter Weight");
                weight = Double.parseDouble(userWeight);
                userTopspeed = JOptionPane.showInputDialog("Enter Topspeed");
                topspeed = Double.parseDouble(userTopspeed);
                aerodynamics = 0.9;
                userInput = "Van";
                TestConsumption.printVan();
                repaint();
                return;

            }});

        JButton SportCar = new JButton("Add Sports Car");
        SportCar.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                        userHorsepower = JOptionPane.showInputDialog("Enter Horsepower");
                        horsepower = Double.parseDouble(userHorsepower);
                        userWeight = JOptionPane.showInputDialog("Enter Weight");
                        weight = Double.parseDouble(userWeight);
                        userTopspeed = JOptionPane.showInputDialog("Enter Topspeed");
                        topspeed = Double.parseDouble(userTopspeed);
                        aerodynamics = 0.5;
                        userInput = "Sports Car";
                        TestConsumption.printCar();
                        panel.repaint();
            }});

        JLabel userChoice = new JLabel(userInput);
        JLabel accel = new JLabel("Acceleration: " + acceleration);
        JLabel fuel = new JLabel("Fuel Consumption: " + fuelconsumption);

        panel.setLayout(new GridLayout(5,5,0,0));
        panel.add(Van);
        panel.add(SportCar);
        panel.add(userChoice);
        panel.add(accel);
        panel.add(fuel);
        add(panel);
        pack();
        setTitle("Title Here");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(true);
        setSize(300,200);
        setLocationRelativeTo(null);
        setVisible(true);
        repaint();
    }

Window is called in this class

public class TestConsumption extends Vehicle {

    public TestConsumption(double horsepower, double weight, double aerodynamics, double topspeed) {
        super(horsepower, weight, aerodynamics, topspeed);
    }

    public static void main(String [] args){

        Vehicle vh = new Vehicle(500, 500, 500, 500);
        vh.window();
    }


    public static void printCar(){
        Vehicle Car = new SportCar(horsepower,weight,aerodynamics,topspeed);

        Car.acceleration();
        Car.showFuelConsumption();
    }

    public static void printVan(){

        Vehicle FirstVan = new Van(horsepower,weight,aerodynamics,topspeed);

        FirstVan.acceleration();
        FirstVan.showFuelConsumption();
    }
}
Was it helpful?

Solution

As far as we can see, you're never updating the text of your JLabels. You will need to call setText on each JLabel after calculating the new corresponding value for that label.

However, in your situation, your JLabel objects are created as local scope variables in the window() method, and so they're no longer easily accessible (technically there is a way to access them since you added them to your JPanel, but that's unnecessarily cumbersome).

Since TestConsumption.printVan() is apparently used to calculate the acceleration and fuel consumption, to make life easier, I suggest promoting JLabel accel and JLabel fuel to instance variables, and then making individual methods to calculate the two values in TestConsumption. So your action event might look something like this:

sportCar.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent e) {
        userHorsepower = JOptionPane.showInputDialog("Enter Horsepower");
        horsepower = Double.parseDouble(userHorsepower);

        userWeight = JOptionPane.showInputDialog("Enter Weight");
        weight = Double.parseDouble(userWeight);

        userTopspeed = JOptionPane.showInputDialog("Enter Topspeed");
        topspeed = Double.parseDouble(userTopspeed);

        aerodynamics = 0.5;
        userInput = "Sports Car";

        // These static methods would be added to your TestConsumption class
        acceleration = TestConsumption.calculateAcceleration(...whatever params required for this calculation...);
        fuelConsumption = TestConsumption.calculateFuelConsumption(...whatever params required for this calculation...);

        accel.setText("Acceleration: " + acceleration);
        fuel.setText("Fuel Consumption: " + fuelConsumption);

        panel.repaint();
}});

Alternatively, you don't have to promote the JLabels to instance variables; so long as you declare accel and fuel at the top of the window() method before you set up the ActionListener for both buttons, they will be accessible in the event action through the actionPerformed method's scope enclosure.

Some Side notes:

Remember that the Java naming convention for variable names is to begin them with a lower case letter. So your Van and SportCar variables should be van and sportCar. I have written them as such in my example. While it doesn't cause any issues, syntactically, it makes it difficult to know at a glance whether one is looking at a class or variable name.

As far as I can tell, your TestConsumption class doesn't need to extend Vehicle. It is not a vehicle; it seems to be both the starting point of your application, and a helper class (the static methods).

This appears to be a school assignment, so I am not certain whether you've been explicitly told to design your program in this manner, but from a design perspective, you're combining your conceptual "view" and "model" together. A JFrame is not a vehicle; it is a window, a view element used to help represent your data. You may find it will help clean up your code by extracting vehicle-specific fields and methods (such as acceleration, topspeed, etc), in to a separate class called Vehicle, which you can then subclass with SportCar and Van (as you seem to be doing as indicated in TestConsumption). Your JFrame subclass (lets call it MainWindow or something like that instead), would be responsible only for updating its data representations (meaning our accel and fuel JLabels, in this case).

OTHER TIPS

Call window() in constructor Vehicle(double horsepower, double weight, double aerodynamics, double topspeed)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top