Перемещение объекта в пределах указанного c пространства сетки в java JFrame возможно с использованием GridBagLayout? - PullRequest
0 голосов
/ 29 января 2020

Я хочу переместить прямоугольник вверх и вниз по вертикальной сетке 1x10 в окне JFrame.

Сетка должна быть пронумерована, и я должен знать, на каком уровне сетки находится прямоугольник.

У меня нет большого опыта работы с java, но на данный момент мой базовый c код, который я понимаю из учебника, который я наблюдал, позволяет мне перемещать прямоугольник вверх и вниз по экран, но прямоугольник исчезает с экрана, и он не находится в сетке.

package JavaWork;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Lift extends JPanel implements ActionListener, KeyListener {
    Timer tm = new Timer(5, this);
    int x = 0, y = 0, velX = 0, velY = 0;
    /**
     * 
     */
    public Lift() {
        // TODO Auto-generated constructor stub
        tm.start();
        addKeyListener(this);
        setFocusable(true);
        setFocusTraversalKeysEnabled(false);
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.RED);
        g.fillRect(x, y, 50, 30);

    }

    public void actionPerformed(ActionEvent e) {
        x = x + velX;
        y = y + velY;
        repaint();
    }

    public void keyPressed(KeyEvent e) {
        int c = e.getKeyCode();

        if (c == KeyEvent.VK_UP) {
            velX = 0;
            velY = -1;

        }
        if (c == KeyEvent.VK_DOWN) {
            velX = 0;
            velY = 1;

        }
    }

    public void keyTyped(KeyEvent e) {}
    public void keyReleased(KeyEvent e) {}


    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO code application logic here
        Lift t = new Lift();
        JFrame jf = new JFrame();

        jf.setTitle("Lift");
        jf.setSize(600, 400);
        jf.setVisible(true);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.add(t);
    }
}

Любой совет, кусок кода, веб-сайт или видео ссылка на учебник будет принята с благодарностью :)

Ответы [ 2 ]

1 голос
/ 30 января 2020

Вы можете сделать sh эквивалент сетки самостоятельно, только рисуя с y-координатой, кратной 40. Я предлагаю 40, так как вы устанавливаете высоту своего окна на 400, и вы хотите иметь 10 “ полы »в вашей сетке и 400 ÷ 10 = 40.

Таким образом, последняя строка в вашем методе paintComponent должна выглядеть следующим образом:

g.fillRect(x, y * 40, 50, 30);

Технически область рисования окна будет немного меньше 400, так как размер JFrame включает строку заголовка и границы окна. Это можно исправить, заменив это:

jf.setSize(600, 400);

на это:

jf.add(t);
jf.pack();

и удалив другую строку jf.add(t);. Вам также необходимо добавить переопределение getPreferredSize в вашем классе:

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

(Вам также понадобится строка import java.awt.Dimension; в верхней части вашей программы.)

pack() метод говорит окну делать все возможное, чтобы соответствовать предпочтительному размеру каждого компонента, который он содержит. Вот почему необходимо, чтобы ваша панель сообщала о своем предпочтительном размере, и поэтому необходимо добавить панель до того, как JFrame будет упакован и станет видимым.

Относительно того, почему прямоугольник так быстро удаляется с экрана, это происходит из-за числа, которое вы передаете своему таймеру:

Timer tm = new Timer(5, this);

То, что 5 означает, что метод actionPerformed вызывается Swing каждые 5 миллисекунд - это 200 раз в секунду! Возможно, вам нужно более разумное значение, например, два раза в секунду:

Timer tm = new Timer(500, this);

Наконец, вам нужно убедиться, что ваш прямоугольник никогда не покидает экран, проверив минимальное и максимальное значения y в ваш actionPerformed метод:

y = y + velY;
y = Math.max(0, y);     // don’t let y go off the top
y = Math.min(9, y);     // don’t let y go off the bottom
0 голосов
/ 02 февраля 2020

Вы можете сделать это, используя GridLayout. Имейте прозрачный лифт на каждом этаже и непрозрачный (красный в этом примере) на одном этаже. Перемещение вверх или вниз достигается простым изменением правого подъема (обозначенного JLabel на следующем mre) с прозрачного на непрозрачный:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Lift extends JPanel implements ActionListener, KeyListener {

    private static final int NUMBER_OF_FLOORS = 5, LIFT_W =100, LIFT_H =100, PAUSE = 2000;
    private final JLabel[] lifts = new JLabel[NUMBER_OF_FLOORS];
    private int liftPosition = 0;
    private boolean isMovingUp = true;
    private final Timer tm = new Timer(PAUSE, this);

    public Lift() {
        setLayout(new GridLayout(0, 1));
        for(int floor = NUMBER_OF_FLOORS -1; floor >=0 ; floor--){
            JLabel lift = getLift(floor);
            lifts[floor] = lift;
            add(lift);
        }

        addKeyListener(this);
        tm.start();
    }

    private JLabel getLift(int floor) {
        JLabel lift = new JLabel();
        lift.setPreferredSize(new Dimension(LIFT_W, LIFT_H));
        lift.setBackground(Color.RED);
        if(liftPosition == floor) {
            lift.setOpaque(true);
        }
        return lift;
    }

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

    private void autoMove(){
        if(liftPosition == 0) {
            isMovingUp = true;
        } else if(liftPosition >= NUMBER_OF_FLOORS -1) {
            isMovingUp = false;
        }
        if(isMovingUp) {
            moveUp();
        } else {
            moveDown();
        }
    }

    private void moveUp(){
        if(liftPosition >= NUMBER_OF_FLOORS -1) return;
        lifts[liftPosition].setOpaque(false);
        liftPosition++;
        lifts[liftPosition].setOpaque(true);
        repaint();
    }

    private void moveDown(){
        if(liftPosition <= 0) return;
        lifts[liftPosition].setOpaque(false);
        liftPosition--;
        lifts[liftPosition].setOpaque(true);
        repaint();
    }

    @Override
    public void keyPressed(KeyEvent e) {
        int c = e.getKeyCode();
        if (c == KeyEvent.VK_UP) {
            moveUp();
        }
        if (c == KeyEvent.VK_DOWN) {
            moveDown();
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {}
    @Override
    public void keyReleased(KeyEvent e) {}

    public static void main(String[] args) {
        // TODO code application logic here
        Lift t = new Lift();
        JFrame jf = new JFrame();
        jf.setTitle("Lift");
        jf.setSize(300, 400);
        jf.setVisible(true);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.add(t, BorderLayout.WEST);
    }
}

enter image description here

...