Почему BufferedImage не обрезается по нарисованному в методе paintComponent прямоугольнику (его высота вычисляется неправильно)?

Я пишу приложение с возможностью для пользователя вырезать изображения. В настоящее время приведенный ниже код обрезает изображение немного выше нарисованного прямоугольника (его цель — показать, с какими координатами пользователь хочет разрезать изображение на самом деле).

public class ScreenCaptureRectangle extends JFrame implements MouseListener, MouseMotionListener {

int drag_status = 0, c1, c2, c3, c4;

public void cut() {
    ImagePanel im = new ImagePanel(PicChanges.getNewImage());
    JScrollPane scrollPane = new JScrollPane(im);
    add(scrollPane);
    setSize(500, 400);
    setVisible(true);
    im.addMouseListener(this);
    im.addMouseMotionListener(this);
}

public void draggedScreen() throws Exception {
    int w = c1 - c3;
    int h = c2 - c4;
    w = w * -1;
    h = h * -1;
    Robot robot = new Robot();
    BufferedImage img = robot.createScreenCapture(new Rectangle(c1, c2, w, h));
    File save_path = new File("screen1.jpg");
    ImageIO.write(img, "JPG", save_path);
    System.out.println("Cropped image saved successfully.");
}

@Override
public void mouseClicked(MouseEvent arg0) {
}

@Override
public void mouseEntered(MouseEvent arg0) {
}

@Override
public void mouseExited(MouseEvent arg0) {
}

@Override
public void mousePressed(MouseEvent arg0) {
    repaint();
    c1 = arg0.getX();
    c2 = arg0.getY();
}

@Override
public void mouseReleased(MouseEvent arg0) {
    repaint();
    if (drag_status == 1) {
        c3 = arg0.getX();
        c4 = arg0.getY();
        try {
            repaint();
            draggedScreen();
        } catch (Exception e) {
            e.printStackTrace();
        }
    } else {
        System.out.println("Issue is under construction");
    }
}

@Override
public void mouseDragged(MouseEvent arg0) {
    repaint();
    drag_status = 1;
    c3 = arg0.getX();
    c4 = arg0.getY();
}

@Override
public void mouseMoved(MouseEvent arg0) {
}

public void paint(Graphics g) {
    super.paint(g);
    int w = c1 - c3;
    int h = c2 - c4;
    w = w * -1;
    h = h * -1;
    if (w < 0)
        w = w * -1;
    g.setColor(Color.RED);
    g.drawRect(c1, c2, w, h);
}

public class ImagePanel extends JPanel {

private BufferedImage imageToCut;


public ImagePanel(BufferedImage img) {
    this.imageToCut = img;
    Dimension size = new Dimension(imageToCut.getWidth(null), imageToCut.getHeight(null));
    setPreferredSize(size);
    setMaximumSize(size);
    setMinimumSize(size);
    setSize(size);
}

@Override
protected void paintComponent(Graphics g) {
    g.drawImage(imageToCut, 0, 0, null);
}
}

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

Почему BufferedImage не обрезается по нарисованному в методе paintComponent прямоугольнику (его высота вычисляется неправильно)?

Он получает это:

Почему BufferedImage не обрезается по нарисованному в методе paintComponent прямоугольнику (его высота вычисляется неправильно)?

Моя цель - получить следующий результат:

Почему BufferedImage не обрезается по нарисованному в методе paintComponent прямоугольнику (его высота вычисляется неправильно)?

Я использую прослушиватели мыши, чтобы получить координаты нарисованного прямоугольника, а затем, используя эти координаты, вырезать изображение. Теперь изображение обрезается с неправильной высотой (как я это вижу). Я был бы признателен, если бы кто-нибудь мог сказать мне, что может быть не так в коде? Спасибо!

1) Чтобы быстрее получить помощь, редактировать добавить минимальный воспроизводимый пример или Короткий, автономный, правильный пример. НАПРИМЕР. как в этот ответ (что, кажется, является основой для этого вопроса!). 2) См. Обнаружение/исправление висящей закрывающей скобки блока кода для проблемы, которую я больше не мог решить. Пожалуйста, редактировать вопрос, чтобы добавить 4 символа пробела перед закрытием } в конце кода.

Andrew Thompson 22.04.2019 10:14

Если вы собираетесь использовать Robot, вам нужно изменить координаты, сообщаемые MouseEvent, на экранные координаты, в настоящее время они сообщаются как координаты компонента относительно компонента, на который зарегистрирован MouseListener.

MadProgrammer 22.04.2019 10:52

Кроме того, поскольку компоненты относятся к ImagePanel, прямоугольник, который вы рисуете на рамке, будет искажен.

MadProgrammer 22.04.2019 10:57

Вы захотите взглянуть на MouseEvent#getLocationOnScreen

MadProgrammer 22.04.2019 10:59

Робот режет относительно экрана - координаты точки мыши относятся к окну программы - поэтому вам нужно поиграть с этим - начните с начала окна вашей программы и добавьте это к началу вашего компьютера экран - тогда, если у вас есть JPanel внутри фрейма, который также изменит относительные координаты - так что вам нужно поиграть - поставьте прямоугольники в каждом случае, чтобы увидеть, где находятся точки

gpasch 22.04.2019 17:29

Спасибо, @MadProgrammer, вы были правы насчет координат, сообщенных MouseEvent - я их изменил. Так же, @gpasch спасибо за ваши рекомендации, в итоге у меня не открывается отдельное окно для вырезания фото, я добавляю MouseListeners в JFrame и теперь вырез работает как положено, даже лучше!)

Ilona 24.04.2019 09:23
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
6
74
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Благодаря полученным рекомендациям, теперь я не открываю отдельный кадр для вырезания фото после того, как пользователь нажмет на кнопку «Вырезать», а просто добавляю MouseListeners в JFrame, что более удобно и дружелюбно к пользователю. Фото обрезано правильно, по координатам из MouseListeners:

public class ImageScreenShot extends JFrame implements MouseListener, MouseMotionListener {

int drag_status = 0, c1, c2, c3, c4;

public int getC1() {
    return c1;
}

public int getC2() {
    return c2;
}

public int getC3() {
    return c3;
}

public int getC4() {
    return c4;
}

public void cut() {
    GraphicalUserInterface.getFrame().addMouseMotionListener(this);
    GraphicalUserInterface.getFrame().addMouseListener(this);
}

public void draggedScreen() throws Exception {
    int w = c1 - c3;
    int h = c2 - c4;
    w = w * -1;
    h = h * -1;
    Robot robot = new Robot();
    BufferedImage img = robot.createScreenCapture(new Rectangle(c1, c2, w, h));
    File save_path = new File("screen1.jpg");
    ImageIO.write(img, "JPG", save_path);
    GraphicalUserInterface.getLabelIcon().setIcon(new ImageIcon(new ImageIcon(img).getImage().getScaledInstance(img.getWidth(), img.getHeight(), Image.SCALE_SMOOTH)));
    JOptionPane.showConfirmDialog(null, "Would you like to save your cropped Pic?");
    if (JOptionPane.YES_OPTION == 0) {
    /**Need to implement some code*/
    } else {
    /**Need to implement some code*/

    }
    System.out.println("Cropped image saved successfully.");
}

@Override
public void mouseClicked(MouseEvent arg0) {
}

@Override
public void mouseEntered(MouseEvent arg0) {
}

@Override
public void mouseExited(MouseEvent arg0) {
}

@Override
public void mousePressed(MouseEvent arg0) {
    c1 = arg0.getXOnScreen();
    c2 = arg0.getYOnScreen();
}

@Override
public void mouseReleased(MouseEvent arg0) {
    if (drag_status == 1) {
        c3 = arg0.getXOnScreen();
        c4 = arg0.getYOnScreen();
        try {
            draggedScreen();
        } catch (Exception e) {
            e.printStackTrace();
        }
    } else {
        System.out.println("Issue is under construction");
    }
}

@Override
public void mouseDragged(MouseEvent arg0) {
    drag_status = 1;
    c3 = arg0.getXOnScreen();
    c4 = arg0.getYOnScreen();
}

@Override
public void mouseMoved(MouseEvent arg0) {
}

Другие вопросы по теме