Question

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);
    }
}
Was it helpful?

Solution 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.

OTHER TIPS

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);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top