Подтвердить что ты не робот

Создание прокрутки изображения в области содержимого JFrame

Я пытаюсь отобразить большое изображение внутри области содержимого JFrame. Я хотел бы сделать изображение или contentpane прокручиваемым, так как изображение велико. Я попытался сделать это с помощью Jscrollpane и добавить его в область содержимого, но это не сработало. Некоторые искали решение, но не смогли его найти. Может ли кто-нибудь меня вести? Мой код ниже

FinalEnvironment.java

package environment;

import java.awt.*;
import java.net.URL;

import javax.swing.*;

public class FinalEnvironment{

public FinalEnvironment(){

    Image Eastlake;
    URL EastlakeURL = null;

    EastlakeURL = FinalEnvironment.class.getResource("/image1/eastlake_night.png");
    Eastlake = Toolkit.getDefaultToolkit().getImage(EastlakeURL);

    JFrame frame = new JFrame("UniCat World");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(800, 600);
    frame.setResizable(false);
    frame.setLocationRelativeTo(null);

    JMenuBar yellowMenuBar = new JMenuBar();
    Map map = new Map(800, 550, Eastlake);
    yellowMenuBar.setOpaque(true);
    yellowMenuBar.setBackground(Color.YELLOW);
    yellowMenuBar.setPreferredSize(new Dimension(800, 50));
    frame.setJMenuBar(yellowMenuBar);
    JScrollPane scroller = new JScrollPane(map);
    scroller.setAutoscrolls(true);
    scroller.setPreferredSize(new Dimension(800, 550));
    frame.getContentPane().add(scroller, BorderLayout.CENTER);


    frame.setSize(800, 600);
    frame.setVisible(true);
}

public static void main(String[] args){
    FinalEnvironment fe = new FinalEnvironment();
}
}

Вот моя map.java

package environment;

import java.awt.*;

import javax.swing.*;


public class Map extends JPanel{

    private int width;
    private int height;
    private Image img;

    public Map(int width, int height, Image img){

        this.width = width;
        this.height = height;
        this.img = img;
    }

    protected void  paintComponent(Graphics g)
    {
        super.paintComponents(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(img,0,0,2624,1696,null);
    }

}

Наконец, я хотел бы разместить Jbuttons поверх этого изображения. Должен ли я вызвать Rectangle и поместить его поверх изображения в области содержимого, которое затем я использую Point для размещения моих кнопок, или я должен немедленно использовать изображение или сам компонент для этого? Мне нужна кнопка для синхронизации с изображением, когда она прокручивается, а не статична в области содержимого.

Спасибо

4b9b3361

Ответ 1

Что я буду делать здесь:

1. У вас есть панель (холст), которая несет ответственность только за рисование данного изображения независимо от реального размера изображения в переопределенном методе paintComponent()

    super.paintComponent(g);
    g.drawImage(image, 0, 0, null);

2.Убедитесь, что размер предпочтительного холста равен реальному размеру изображения.

3. У вас есть вторая панель, которая будет служить в качестве области содержимого кадра.

4. В нем вы установите JScrollPane в качестве своего центра.

5. В области просмотра прокрутки будет отображаться компонент с шага 1.

6.Добавьте свою кнопку на панель холста с шага 1. Она будет прокручиваться вместе с изображением.

7.Добавьте панель содержимого, панель с шага 3, в кадр и запустите приложение.

EDIT: Образец кода с кнопкой, добавленной на холст, который всегда остается на своем месте, независимо от положения прокрутки или размера рамки.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

public class ScrollImageTest extends JPanel {
    private static final long serialVersionUID = 1L;
    private BufferedImage image;
    private JPanel canvas;

    public ScrollImageTest() {
        try {
            this.image = ImageIO.read(new URL("http://interviewpenguin.com/wp-content/uploads/2011/06/java-programmers-brain.jpg"));
        }catch(IOException ex) {
            Logger.getLogger(ScrollImageTest.class.getName()).log(Level.SEVERE, null, ex);
        }

        this.canvas = new JPanel() {
            private static final long serialVersionUID = 1L;
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.drawImage(image, 0, 0, null);
            }
        };
        canvas.add(new JButton("Currently I do nothing"));
        canvas.setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
        JScrollPane sp = new JScrollPane(canvas);
        setLayout(new BorderLayout());
        add(sp, BorderLayout.CENTER);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JPanel p = new ScrollImageTest();
                JFrame f = new JFrame();
                f.setContentPane(p);
                f.setSize(400, 300);
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setVisible(true);
            }
        });
    }
}

Ответ 2

Что делать, если вы используете свои размеры для установки предпочтительного размера карты. Например, дайте Map этот метод:

// method in the Map class
@Override
public Dimension getPreferredSize() {
  return new Dimension(width, height);
}

Таким образом, Map JPanel займет необходимую комнату, чтобы показать все изображение. Кроме того, почему ваш метод drawImage в методе paintComponent имеет большие магические числа? Почему бы не использовать ширину и высоту там? Изменить 1: или даже не указать размер изображения, как предлагает Боро в своем ответе (1+ к нему).

Ответ 3

Почему все изобретают колесо??? Нет необходимости в создании пользовательской панели для рисования изображения.

Все, что вам нужно сделать, это создать JLabel и добавить ImageIcon на ярлык, и у вас не будет проблем. Метка будет:

  • покрасить изображение в (0, 0) с его первоначальным размером (это именно то, что делает пользовательский код).

  • определить предпочтительный размер изображения на основе размера изображения. Теперь прокрутка произойдет автоматически.

Также редко существует причина использовать метод setPreferredSize(), поскольку все компоненты имеют предпочтительный размер по умолчанию. Поэтому вы не должны устанавливать размер по умолчанию в строке меню. Единственный раз, когда я установил предпочтительный размер, будет на JScrollPane. Это позволит упаковать фреймы с разумным размером, а затем полосы прокрутки будут отображаться автоматически в зависимости от размера изображения на этикетке.

Ответ 4

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