Создание изображения с возможностью прокрутки в области содержимого JFrame - PullRequest
12 голосов
/ 04 сентября 2011

Я пытаюсь отобразить большое изображение в области содержимого JFrame. Я хотел бы сделать изображение или область содержимого прокручиваемым, так как изображение большое. Я попытался сделать это с помощью 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();
}
}

Вот моя карта. 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);
    }

}

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

Спасибо

Ответы [ 4 ]

14 голосов
/ 04 сентября 2011

Что бы я тут делал:

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);
            }
        });
    }
}
5 голосов
/ 04 сентября 2011

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

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

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

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

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

5 голосов
/ 04 сентября 2011

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

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

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

3 голосов
/ 04 сентября 2011

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

...