user1719605
user1719605

Reputation: 189

Java drawLine() method not taking class variable as input

kinda new to swing and making guis in general, I have been using the drawLine method to create a "floors" and it has been working for the variables of the coordinates are local the the paintComponent class, however I want to change the coordinates using an actionListerner / Timer, so I need the variables to be accessible to the whole class.

This is probably a real simple fix (??) and I'll look like a fool for asking it here, but I can't work it out.

Here is the code.

class Elevator extends JPanel implements ActionListener {

    private int numberOfLines = 0;
    private int j = 60;

    int yco = j - 125;

    final private int HEIGHT = 50;
    final private int WIDTH = 80;
    final private boolean UP = true;
    final private int TOP = 60;
    final private int BOTTOM = j - 125;

    private int mi = 5;

    private Timer timer = new Timer(100, this);

    public Elevator(int x) {

        this.numberOfLines = x;

    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        for (int i = 0; i < numberOfLines; i++) {

            g.drawLine(0, j, getWidth(), j);
            j += 75;

        }

        g.drawRect(getWidth() / 2, yco, WIDTH, HEIGHT);

    }

        @Override
        public void actionPerformed(ActionEvent e) {

        }
    }

Any help is appreciated thanks in advance.

Upvotes: 0

Views: 363

Answers (1)

Sam
Sam

Reputation: 1206

The reason your lines are not showing now that your variables (specifically j in your example code) are class variables, is that they are "remembering" state between calls to paintComponent(). Specifically, when j was local, it always got set back to its initial value (presumably j=60). Now however, it gets incremented in your for loop in the line

j += 75;

and never reset to a lower value. This means the second or third time that paintComponent() gets called, the value of j is too large, and your lines are being drawn outside the visible area (off screen). A Java Swing component can easily have its paintComponent() method called two, three, or more times before the component is even rendered on the screen, which is why your lines are no longer getting drawn (well, technically they are getting drawn, just not anywhere you can see them).

To fix this, you can add to your paintComponent() method the single line

j = 60;

just before the for loop. But at this point, you might as well just keep j local (unless you need to read its value but not change it with the timer).

Alternatively, if j needs to change over time, just make sure it gets set inside actionPerformed() by the timer, thenwork with a copy of the value inside of paintComponent() instead of directly with the value of j. As an example:

public void paintComponent(Graphics g) {
    ...
    int jCopy = j;
    for (int i = 0; i < numberOfLines; i++) {

        g.drawLine(0, jCopy, getWidth(), jCopy);
        jCopy += 75;

    }
    ...
}

public void actionPerformed(ActionEvent e) {
    ...
    j += 5;
    //If you don't cap it at some max,
    //it will go off the bottom of the screen again
    if (j > 300) {
        j = 60;
    }
    ...
}

This will help stop consistency issues that could be caused by modifying j in both paintComponent() and actionPerformed().

Upvotes: 2

Related Questions