0

It's a simple question, maybe I just don't understand the tutorial I'm reading from. but I've been stuck on this for a while. My program is as simple as it gets aside from a "hello world". What I'm trying to do is this: when the user clicks the button, the "O" moves to the right. Simple enough, but where do I put repaint()? Do I need to add something.repaint(); to repaint the screen or just by itself? A nested class problem? T_T this is making me miserable how no one seems to have this problem that I can't comprehend. Thanks in advance.

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

public class GuiTest {

    static int x = 20;

    private static class moveTest extends JPanel {

        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawString("O", x, 30);
        }
    }

    private static class ButtonHandler implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            x += 1;
        }
    }

    public static void main(String[] args) {
        moveTest displayPanel = new moveTest();
        JButton okButton = new JButton("move");
        ButtonHandler listener = new ButtonHandler();
        okButton.addActionListener(listener);

        JPanel content = new JPanel();
        content.setLayout(new BorderLayout());
        content.add(displayPanel, BorderLayout.CENTER);
        content.add(okButton, BorderLayout.SOUTH);

        JFrame window = new JFrame("GUI Test");
        window.setContentPane(content);
        window.setSize(250, 100);
        window.setLocation(100, 100);
        window.setVisible(true);
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
Joel Ye
  • 63
  • 1
  • 4
  • You should be able to put it in the `actionPerformed()` method. – Code-Apprentice Jul 07 '13 at 14:06
  • just repaint();? cuz that doesn't work – Joel Ye Jul 07 '13 at 14:22
  • What does "doesn't work" mean? Please provide more information, such as error messages, if you want us to help you. – Code-Apprentice Jul 07 '13 at 14:27
  • I use eclipse and the in-editor error message says it's undefined ( the method repaint(); is not defined for type GuiTest.ButtonHandler ) Does that mean that I haven't imported something correctly...? – Joel Ye Jul 07 '13 at 14:40
  • 1
    I also suggest removing `static` from the declaration of `x`. Generally, static fields and methods should be used sparingly. – Code-Apprentice Jul 07 '13 at 14:41
  • I have to keep that because my methods use static references to x (x+=1 and the drawString), how would you change that without adding a static to x? – Joel Ye Jul 07 '13 at 14:43
  • You change it by also removing the static from the ActionListener subclass and moving most of the code from `main()` to a constructor or member method. See my answer for more details. – Code-Apprentice Jul 07 '13 at 14:48

2 Answers2

4

Consider letting your MoveTest panel export an Action for use by the GuiTest button.

GUI image

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

public class GuiTest {

    private static class MoveTest extends JPanel {

        private int x = 20;
        private int y = 20;

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawString("<O>", x, y);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(256, 128);
        }

        public Action getAction() {
            return new ButtonHandler("Move");
        }

        private class ButtonHandler extends AbstractAction {

            public ButtonHandler(String name) {
                super(name);
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                x += 2;
                y += 1;
                repaint();
            }
        }
    }

    public static void main(String[] args) {
        MoveTest displayPanel = new MoveTest();
        JButton moveButton = new JButton(displayPanel.getAction());

        JFrame window = new JFrame("GUI Test");
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.add(displayPanel);
        window.add(moveButton, BorderLayout.SOUTH);
        window.pack();
        window.setLocationByPlatform(true);
        window.setVisible(true);
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • See also [*Initial Threads*](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html) and [`setPreferredSize()`](http://stackoverflow.com/q/7229226/230513). – trashgod Jul 07 '13 at 15:59
2

You need a component to call repaint() on. The simplest solution is to call repaint() like this:

((JComponent)e.getSource()).getTopLevelAncestor().repaint();

The issue is that your ActionListener is declared as a static member class, so it does not have access to the non-static members of the enclosing class because it is not associated with an instance of the enclosing class. Usually I put all of my GUI initialization code inside the constructor for my own JPanel subclasses. I also use anonymous inner classes for listeners. You can just as easily use named classes as long as they are not static. Then you can call JPanel methods inside the the listeners methods.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268