Asked  7 Months ago    Answers:  5   Viewed   23 times

This is the JFrame

package client.connection;

import java.awt.Dimension;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import javax.swing.JFrame;


class DrawFrameRemoteControl extends JFrame
{
    private DrawPanelRemoteControl imagePanel;
    private ClientRemoteControlConnection clientRemoteControlConnection;
    private ObjectInputStream clientInputStream;
    private ObjectOutputStream clientOutputStream;
    private Dimension imageDimension;
    private Dimension serverDimension;

    public DrawFrameRemoteControl(Dimension imageDimension,ClientRemoteControlConnection clientRemoteControlConnection,ObjectInputStream clientInputStream,ObjectOutputStream clientOutputStream,Dimension serverDimension)
    {
        super("Remote Desktop Control");

        this.clientRemoteControlConnection=clientRemoteControlConnection;
        this.clientInputStream=clientInputStream;
        this.clientOutputStream=clientOutputStream;
        this.imageDimension=imageDimension;
        this.serverDimension=serverDimension;

        imagePanel=new DrawPanelRemoteControl(imageDimension);
        add(imagePanel);


        setSize(imageDimension.width,imageDimension.height);
        setResizable(false);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
        setLocationRelativeTo(null);
    }

    void drawNewImageGrayscale(byte[] array)
    {
        imagePanel.setNewImageGrayscale(array);
        imagePanel.repaint();
    }
}

And this is the extended JPanel class-

package client.connection;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.MemoryImageSource;
import java.awt.image.Raster;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;

class DrawPanelRemoteControl extends JPanel
{
    private byte[] byteArray=null;
    private Image image;
    private JLabel imageLabel=new JLabel();
    private Dimension imageDimension;

    public DrawPanelRemoteControl(Dimension imageDimension)
    {
        this.imageDimension=imageDimension;
        add(imageLabel);
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        System.out.println(".");
        if(byteArray!=null)
        {
            image=getGrayscaleImageFromArray(byteArray,imageDimension.width,imageDimension.height);
            imageLabel.setIcon(new ImageIcon(image));
        }
    }

    private Image getGrayscaleImageFromArray(byte[] buffer, int width, int height)
    {
        ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
        int[] nBits = { 8 };
        ColorModel cm = new ComponentColorModel(cs, nBits, false, true,Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
        SampleModel sm = cm.createCompatibleSampleModel(width, height);
        DataBufferByte db = new DataBufferByte(buffer, width * height);
        WritableRaster raster = Raster.createWritableRaster(sm, db, null);
        BufferedImage result = new BufferedImage(cm, raster, false, null);
        return result;
    }

    void setNewImageGrayscale(byte[] array)
    {
        this.byteArray=array;
        this.intArray=null;
    }
}

I have tried debugging the code, even though imagePanel.repaint() is being executed many times, the program never reaches the paintComponent() method of DrawPanelRemoteControl class.

Can anybody give me any idea why this might be happening? Has it got anything to do with the imageDimension object?

Additional Information : In main() method, a DrawFrameRemoteControl object is created and it's drawNewImageGrayscale(byte[] arr) method is being updated from main() every second.

 Answers

16

It's not clear why you're passing around byte[], but it looks like you want to update a component's Icon with a gray thumbnail. The example below creates grayscale icons from existing sample icons and uses setIcon() to do the update. A similar approach works with any Image. See also this example that suggests ColorConvertOp, and this example that updates whole components rather than icons.

Gray Icons Aqua

Gray Icons Nimbus

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.Timer;
import javax.swing.UIManager;

/**
 * @see https://stackoverflow.com/a/12228640/230513
 * @see https://stackoverflow.com/a/7935040/230513
 */
public class GrayIcons extends JPanel {

    private List<Icon> list = new ArrayList<Icon>();
    private List<JToggleButton> buttons = new ArrayList<JToggleButton>();
    private Timer timer = new Timer(1000, new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            update();
        }
    });

    public GrayIcons() {
        this.setLayout(new GridLayout(1, 0));
        list.add(getGray(UIManager.getIcon("OptionPane.errorIcon")));
        list.add(getGray(UIManager.getIcon("OptionPane.informationIcon")));
        list.add(getGray(UIManager.getIcon("OptionPane.warningIcon")));
        list.add(getGray(UIManager.getIcon("OptionPane.questionIcon")));
        for (Icon icon : list) {
            JToggleButton jtb = new JToggleButton(icon);
            buttons.add(jtb);
            this.add(jtb);
        }
        timer.start();
    }

    private void update() {
        Collections.shuffle(list);
        int index = 0;
        for (JToggleButton b : buttons) {
            b.setIcon(list.get(index++));
        }
    }

    /**
     * @see https://stackoverflow.com/q/5830533/230513
     * @see https://stackoverflow.com/a/3106550/230513
     */
    private Icon getGray(Icon icon) {
        final int w = icon.getIconWidth();
        final int h = icon.getIconHeight();
        GraphicsEnvironment ge =
            GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice gd = ge.getDefaultScreenDevice();
        GraphicsConfiguration gc = gd.getDefaultConfiguration();
        BufferedImage image = gc.createCompatibleImage(w, h);
        Graphics2D g2d = image.createGraphics();
        g2d.setPaint(new Color(0x00f0f0f0));
        g2d.fillRect(0, 0, w, h);
        icon.paintIcon(null, g2d, 0, 0);
        BufferedImage gray = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);
        ColorConvertOp op = new ColorConvertOp(
            image.getColorModel().getColorSpace(),
            gray.getColorModel().getColorSpace(), null);
        op.filter(image, gray);
        return new ImageIcon(gray);
    }

    private void display() {
        JFrame f = new JFrame("GrayIcons");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new GrayIcons().display();
            }
        });
    }
}
Tuesday, June 1, 2021
 
themihai
answered 7 Months ago
77

This is intended. It's even possible to access the private members of the same class. So think of the modifiers to be class wise modifiers, not objectwise modifiers.

PHP is not the only language that has this feature. Java for example has this too.

Saturday, May 29, 2021
 
codingb
answered 7 Months ago
68

So, there are a number of issues...

You should call setVisible on the JFrame last, this will ensure that components are laid out

Your keybindings issue seem to related to the fact that you're using the movement Set, but you never actually add anything to it. Instead you should be checking the dir value.

And probably a bunch of other things. Your code is tightly coupled and there isn't any centralised management of the state.

I'd start by having a better understand of the Model-View-Controller paradigm and separate the code into appropriate areas of responsibility.

The "data" for the game should separate from the "rendering" of the game, which should be separate from the decisions about how the game is to be updated.

What I'm about to present is an oversimplification intended to spark ideas, rather than been a concrete solution, as there are a number of ways you could achieve the physical implementation...

So, what we need is, a concept of something in the game, AKA an "entity", entities take many forms, but I'm going to focus on renderable/displayable entities. You need some kind of model that is responsible for modeling the current state of the game and which is responsible for implementing the rules. You need some kind of view, which is responsible for rendering the model and responding to user input. You need some kind of controller which controls how the model and the view bridged.

It's always a good idea to start with a series of interfaces which define the contractual expectations and outlines the expected means by which elements are expected to communicate with each other. Again, I've taken a simple, direct approach, but it's by no means the only...

public static enum Direction {
    LEFT,
    RIGHT,
    SPACE
}

public interface Entity {
    public void paint(Graphics2D g2d);
    public Point getLocation();
    public void setLocation(Point p);
    public Dimension getSize();
}

public interface GameModel {
    public Entity[] getEntities();
    public void update(Rectangle bounds, Set<Direction> keys);
}

public interface GameController {
    public Entity[] getEntities();
    public void setDirection(Direction direction, boolean pressed);
    public void start();
}

public interface GameView {
    public void setController(GameController controller);
    public GameController getController();
    public Rectangle getViewBounds();
    public void repaint();
}

Let's take a look at the implementation of the entities. This example has two entities, a Player and a Bullet...

public abstract class AbstractEntity implements Entity {

    private final Point location = new Point(0, 0);

    @Override
    public Point getLocation() {
        return new Point(location);
    }

    @Override
    public void setLocation(Point p) {
        location.setLocation(p);
    }

}

public class Player extends AbstractEntity {

    public Player(Rectangle bounds) {
        int x = bounds.x + ((bounds.width - getSize().width) / 2);
        int y = bounds.y + (bounds.height - getSize().height);
        setLocation(new Point(x, y));
    }

    @Override
    public Dimension getSize() {
        return new Dimension(40, 17);
    }

    @Override
    public void paint(Graphics2D g2d) {
        Point p = getLocation();
        Dimension size = getSize();
        g2d.setColor(Color.BLUE);
        g2d.fillRect(p.x, p.y + 7, size.width, 10);
        g2d.fillRect(p.x + 18, p.y, 4, 7);
    }

}

public class Bullet extends AbstractEntity {

    @Override
    public void paint(Graphics2D g2d) {
        Rectangle bullet = new Rectangle(getLocation(), getSize());
        g2d.setColor(Color.RED);
        g2d.fill(bullet);
    }

    @Override
    public Dimension getSize() {
        return new Dimension(4, 8);
    }

}

Nothing spectacular, but they each define their parameters and can render their states when asked.

Next, we have the model, controller and view. This example uses the controller as the primary game loop, responsible for updating the game (model) state and scheduling repaints. This is done with the use of a Swing Timer as this prevents possible race conditions between the update loop and the painting loop. A more complex implementation would need to take over the painting process through the use of a BufferStrategy and BufferStrategy and BufferCapabilities.

The model simply takes the current view boundaries and the current state of the keys and updates the state of the entities.

The view monitors user input, notifying the controller, and renders the current state of the game.

You'll note that the view and model never communicate directly with each other, this is the domain of the controller.

public class DefaultGameModel implements GameModel {

    private final List<Entity> entities;
    private Player player;

    private Long lastShot;

    public DefaultGameModel() {
        entities = new ArrayList<>(25);
    }

    @Override
    public Entity[] getEntities() {
        return entities.toArray(new Entity[0]);
    }

    @Override
    public void update(Rectangle bounds, Set<Direction> keys) {
        if (player == null) {
            player = new Player(bounds);
            entities.add(player);
        }

        Point p = player.getLocation();
        int xDelta = 0;
        if (keys.contains(Direction.LEFT)) {
            xDelta = -4;
        } else if (keys.contains(Direction.RIGHT)) {
            xDelta = 4;
        }
        p.x += xDelta;
        if (p.x <= bounds.x) {
            p.x = bounds.x;
        } else if (p.x + player.getSize().width >= bounds.x + bounds.width) {
            p.x = bounds.width - player.getSize().width;
        }
        player.setLocation(p);

        Iterator<Entity> it = entities.iterator();
        while (it.hasNext()) {
            Entity entity = it.next();
            if (entity instanceof Bullet) {
                Point location = entity.getLocation();
                Dimension size = entity.getSize();
                location.y -= size.height;
                if (location.y + size.height < bounds.y) {
                    it.remove();
                } else {
                    entity.setLocation(location);
                }
            }
        }

        if (keys.contains(Direction.SPACE)) {
            if (lastShot == null || System.currentTimeMillis() - lastShot > 100) {
                lastShot = System.currentTimeMillis();
                Bullet bullet = new Bullet();
                int x = p.x + ((player.getSize().width - bullet.getSize().width) / 2);
                int y = p.y - bullet.getSize().height;
                bullet.setLocation(new Point(x, y));

                entities.add(bullet);
            }
        }
    }

}

public class DefaultGameController implements GameController {

    private GameModel model;
    private GameView view;

    private Timer timer;

    private Set<Direction> keys = new HashSet<>(25);

    public DefaultGameController(GameModel gameModel, GameView gameView) {
        gameView.setController(this);

        view = gameView;
        model = gameModel;
    }

    @Override
    public Entity[] getEntities() {
        return model.getEntities();
    }

    @Override
    public void setDirection(Direction direction, boolean pressed) {
        if (pressed) {
            keys.add(direction);
        } else {
            keys.remove(direction);
        }
    }

    @Override
    public void start() {
        if (timer != null && timer.isRunning()) {
            timer.stop();
        }
        timer = new Timer(40, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                model.update(view.getViewBounds(), Collections.unmodifiableSet(keys));
                view.repaint();
            }
        });
        timer.start();
    }

}

public class DefaultGameView extends JPanel implements GameView {

    private GameController controller;

    public DefaultGameView() {
        addKeyBinding("left.pressed", KeyEvent.VK_LEFT, true, new DirectionAction(Direction.LEFT, true));
        addKeyBinding("left.released", KeyEvent.VK_LEFT, false, new DirectionAction(Direction.LEFT, false));
        addKeyBinding("right.pressed", KeyEvent.VK_RIGHT, true, new DirectionAction(Direction.RIGHT, true));
        addKeyBinding("right.released", KeyEvent.VK_RIGHT, false, new DirectionAction(Direction.RIGHT, false));
        addKeyBinding("space.pressed", KeyEvent.VK_SPACE, true, new DirectionAction(Direction.SPACE, true));
        addKeyBinding("space.released", KeyEvent.VK_SPACE, false, new DirectionAction(Direction.SPACE, false));
    }

    protected void addKeyBinding(String name, int keyEvent, boolean pressed, DirectionAction action) {
        addKeyBinding(name, KeyStroke.getKeyStroke(keyEvent, 0, !pressed), action);
    }

    protected void addKeyBinding(String name, KeyStroke keyStroke, DirectionAction action) {
        InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
        ActionMap actionMap = getActionMap();

        inputMap.put(keyStroke, name);
        actionMap.put(name, action);
    }

    @Override
    public void setController(GameController controller) {
        this.controller = controller;
    }

    @Override
    public GameController getController() {
        return controller;
    }

    @Override
    public Rectangle getViewBounds() {
        return new Rectangle(new Point(0, 0), getSize());
    }

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

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        GameController controller = getController();
        for (Entity entity : controller.getEntities()) {
            // I don't trust you
            Graphics2D g2d = (Graphics2D) g.create();
            entity.paint(g2d);
            g2d.dispose();
        }
    }

    public class DirectionAction extends AbstractAction {

        private Direction direction;
        private boolean pressed;

        public DirectionAction(Direction direction, boolean pressed) {
            this.direction = direction;
            this.pressed = pressed;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            getController().setDirection(direction, pressed);
        }

    }

}

Okay, but that's all fine and good, but how do you use it? Something like this for example...

Play

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                GameModel model = new DefaultGameModel();
                DefaultGameView view = new DefaultGameView();
                GameController controller = new DefaultGameController(model, view);

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(view);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                controller.start();
            }
        });
    }

    public static enum Direction {
        LEFT,
        RIGHT,
        SPACE
    }

    public interface Entity {
        public void paint(Graphics2D g2d);
        public Point getLocation();
        public void setLocation(Point p);
        public Dimension getSize();
    }

    public interface GameModel {
        public Entity[] getEntities();
        public void update(Rectangle bounds, Set<Direction> keys);
    }

    public interface GameController {
        public Entity[] getEntities();
        public void setDirection(Direction direction, boolean pressed);
        public void start();
    }

    public interface GameView {
        public void setController(GameController controller);
        public GameController getController();
        public Rectangle getViewBounds();
        public void repaint();
    }

    public class DefaultGameModel implements GameModel {

        private final List<Entity> entities;
        private Player player;

        private Long lastShot;

        public DefaultGameModel() {
            entities = new ArrayList<>(25);
        }

        @Override
        public Entity[] getEntities() {
            return entities.toArray(new Entity[0]);
        }

        @Override
        public void update(Rectangle bounds, Set<Direction> keys) {
            if (player == null) {
                player = new Player(bounds);
                entities.add(player);
            }

            Point p = player.getLocation();
            int xDelta = 0;
            if (keys.contains(Direction.LEFT)) {
                xDelta = -4;
            } else if (keys.contains(Direction.RIGHT)) {
                xDelta = 4;
            }
            p.x += xDelta;
            if (p.x <= bounds.x) {
                p.x = bounds.x;
            } else if (p.x + player.getSize().width >= bounds.x + bounds.width) {
                p.x = bounds.width - player.getSize().width;
            }
            player.setLocation(p);

            Iterator<Entity> it = entities.iterator();
            while (it.hasNext()) {
                Entity entity = it.next();
                if (entity instanceof Bullet) {
                    Point location = entity.getLocation();
                    Dimension size = entity.getSize();
                    location.y -= size.height;
                    if (location.y + size.height < bounds.y) {
                        it.remove();
                    } else {
                        entity.setLocation(location);
                    }
                }
            }

            if (keys.contains(Direction.SPACE)) {
                if (lastShot == null || System.currentTimeMillis() - lastShot > 100) {
                    lastShot = System.currentTimeMillis();
                    Bullet bullet = new Bullet();
                    int x = p.x + ((player.getSize().width - bullet.getSize().width) / 2);
                    int y = p.y - bullet.getSize().height;
                    bullet.setLocation(new Point(x, y));

                    entities.add(bullet);
                }
            }
        }

    }

    public class DefaultGameController implements GameController {

        private GameModel model;
        private GameView view;

        private Timer timer;

        private Set<Direction> keys = new HashSet<>(25);

        public DefaultGameController(GameModel gameModel, GameView gameView) {
            gameView.setController(this);

            view = gameView;
            model = gameModel;
        }

        @Override
        public Entity[] getEntities() {
            return model.getEntities();
        }

        @Override
        public void setDirection(Direction direction, boolean pressed) {
            if (pressed) {
                keys.add(direction);
            } else {
                keys.remove(direction);
            }
        }

        @Override
        public void start() {
            if (timer != null && timer.isRunning()) {
                timer.stop();
            }
            timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    model.update(view.getViewBounds(), Collections.unmodifiableSet(keys));
                    view.repaint();
                }
            });
            timer.start();
        }

    }

    public abstract class AbstractEntity implements Entity {

        private final Point location = new Point(0, 0);

        @Override
        public Point getLocation() {
            return new Point(location);
        }

        @Override
        public void setLocation(Point p) {
            location.setLocation(p);
        }

    }

    public class Player extends AbstractEntity {

        public Player(Rectangle bounds) {
            int x = bounds.x + ((bounds.width - getSize().width) / 2);
            int y = bounds.y + (bounds.height - getSize().height);
            setLocation(new Point(x, y));
        }

        @Override
        public Dimension getSize() {
            return new Dimension(40, 17);
        }

        @Override
        public void paint(Graphics2D g2d) {
            Point p = getLocation();
            Dimension size = getSize();
            g2d.setColor(Color.BLUE);
            g2d.fillRect(p.x, p.y + 7, size.width, 10);
            g2d.fillRect(p.x + 18, p.y, 4, 7);
        }

    }

    public class Bullet extends AbstractEntity {

        @Override
        public void paint(Graphics2D g2d) {
            Rectangle bullet = new Rectangle(getLocation(), getSize());
            g2d.setColor(Color.RED);
            g2d.fill(bullet);
        }

        @Override
        public Dimension getSize() {
            return new Dimension(4, 8);
        }

    }

    public class DefaultGameView extends JPanel implements GameView {

        private GameController controller;

        public DefaultGameView() {
            addKeyBinding("left.pressed", KeyEvent.VK_LEFT, true, new DirectionAction(Direction.LEFT, true));
            addKeyBinding("left.released", KeyEvent.VK_LEFT, false, new DirectionAction(Direction.LEFT, false));
            addKeyBinding("right.pressed", KeyEvent.VK_RIGHT, true, new DirectionAction(Direction.RIGHT, true));
            addKeyBinding("right.released", KeyEvent.VK_RIGHT, false, new DirectionAction(Direction.RIGHT, false));
            addKeyBinding("space.pressed", KeyEvent.VK_SPACE, true, new DirectionAction(Direction.SPACE, true));
            addKeyBinding("space.released", KeyEvent.VK_SPACE, false, new DirectionAction(Direction.SPACE, false));
        }

        protected void addKeyBinding(String name, int keyEvent, boolean pressed, DirectionAction action) {
            addKeyBinding(name, KeyStroke.getKeyStroke(keyEvent, 0, !pressed), action);
        }

        protected void addKeyBinding(String name, KeyStroke keyStroke, DirectionAction action) {
            InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap actionMap = getActionMap();

            inputMap.put(keyStroke, name);
            actionMap.put(name, action);
        }

        @Override
        public void setController(GameController controller) {
            this.controller = controller;
        }

        @Override
        public GameController getController() {
            return controller;
        }

        @Override
        public Rectangle getViewBounds() {
            return new Rectangle(new Point(0, 0), getSize());
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            GameController controller = getController();
            for (Entity entity : controller.getEntities()) {
                // I don't trust you
                Graphics2D g2d = (Graphics2D) g.create();
                entity.paint(g2d);
                g2d.dispose();
            }
        }

        public class DirectionAction extends AbstractAction {

            private Direction direction;
            private boolean pressed;

            public DirectionAction(Direction direction, boolean pressed) {
                this.direction = direction;
                this.pressed = pressed;
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                getController().setDirection(direction, pressed);
            }

        }

    }

}

Again, you're going to need to go away and do some more research, but this is the general idea

Saturday, August 7, 2021
 
RahulG
answered 4 Months ago
79

for example

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

public class MyFrame extends JFrame {

    private static final long serialVersionUID = 1L;

    public MyFrame() {
        final JPanel parentPanel = new JPanel();
        parentPanel.setLayout(new BorderLayout(10, 10));

        final JPanel childPanel1 = new JPanel();
        childPanel1.setBackground(Color.red);
        childPanel1.setPreferredSize(new Dimension(300, 40));

        final JPanel childPanel2 = new JPanel();
        childPanel2.setBackground(Color.blue);
        childPanel2.setPreferredSize(new Dimension(800, 600));

        JButton myButton = new JButton("Add Component ");
        myButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                parentPanel.remove(childPanel1);
                parentPanel.add(childPanel2, BorderLayout.CENTER);
                parentPanel.revalidate();
                parentPanel.repaint();
                pack();
            }
        });
        setTitle("My Empty Frame");
        setLocation(10, 200);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        parentPanel.add(childPanel1, BorderLayout.CENTER);
        parentPanel.add(myButton, BorderLayout.SOUTH);
        add(parentPanel);
        pack();
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                MyFrame myFrame = new MyFrame();
            }
        });
    }
}
Tuesday, August 17, 2021
 
nkron
answered 4 Months ago
70
  1. Instead of implementing Runnable, establish an ActionListener that calls repaint(). Call it from a Swing Timer.
  2. There are 2 ways to do this.
    • Extend a JComponent or JPanel
    • Draw in a BufferedImage and add that to an ImageIcon in a JLabel.
  3. If extending a component, use JComponent if you do not need to add further children, or JPanel if you do. For either, override paintComponent(Graphics) instead of paint(Graphics).
  4. The BufferedImage might be a better choice for this use-case, since it seems to be animating a (supposedly intentionally persistant) series of lines.
  5. Swing GUIs should be started on the EDT.
  6. Don't call setBounds! Instead, set a preferred size to the custom component, use sensible values for the constructor of the text area, and combine them with layouts (and appropriate padding and borders), then call pack() on the frame after all components are added.
  7. There is an NPE if the JRE calls repaint() prior to the Thread starting.

..What was the question? Oh right, if it can be inferred that the question is "How to combine other components with a custom painted component?" - use a nested layout. see the Nested Layout example.

If using a BufferedImage as backing store, you might place it like the image in that example, except that you would leave out the JTable above that, as well as the JSplitPane.

Thursday, August 26, 2021
 
edorian
answered 4 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share