2011-09-04 2 views
12

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

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 для размещения моих кнопок, или я должен немедленно использовать изображение или сам компонент для этого? Мне нужна кнопка для синхронизации с изображением, когда она прокручивается, а не статична в контентной панели.

Благодаря

+2

Это домашнее задание? – Boro

+0

Нет, это одна из многих вещей, которые я пытаюсь создать в моем проекте. – Noble

+0

Попробуйте то, что я предлагаю для себя. Тогда, если у вас все еще есть проблемы, я могу опубликовать образец кода. – Boro

ответ

14

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

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

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

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

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

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

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

6.Add ваша кнопка на холст панели с шага 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); 
      } 
     }); 
    } 
} 
+0

Я могу сделать изображение прокручиваемым сейчас. Благодаря! Тем не менее, работая над кнопкой. Опубликуйте комментарий здесь или в этом разделе, если я столкнусь с проблемой. Благодаря! – Noble

+0

@Noble рады помочь. Попробуйте просто добавить кнопку на холст, в вашем случае 'map', например. 'map.add (новый JButton (« ОК »)); и он должен работать так, как вы хотите, если я правильно понимаю синхронизацию с изображением. Я думаю, что двигаюсь, двигаясь, верно? – Boro

+2

@Noble: если вы сталкиваетесь с новой проблемой с вашей программой и нуждаетесь в нашей помощи, тогда ваш лучший выбор - задать новый вопрос на SO. Вы можете ссылаться на этот вопрос, если хотите, но создание нового вопроса для новой проблемы увеличит ваши шансы получить своевременную помощь. –

5

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

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

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

+0

Привет @Hovercraft Full Of Eels Я думаю, что вы предлагаете это делать. Или в конструкторе он мог бы использовать 'setPreferredSize (...)' вместо того, чтобы переопределять его. В любом случае, перечитав код, еще раз, реальной проблемой OP было то, что метод 'setPreferredSize()' не был применен к панели, которая входит в 'ScrollPane'. Вместо этого я вижу, что он установлен для 'ScrollPane', который в этом случае не нужен, поскольку он устанавливается как центр макета границы, и он игнорирует как ширину, так и высоту компонента. – Boro

+0

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

3

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

+0

+1 Интересно. Сначала я думал, что это что-то, что имитирует прокрутку смартфона (т. Е. Перетаскивание). Кстати вы знаете о таком API, который имитирует поведение телефона? – Boro

+0

@Boro: Извините, нет. – trashgod

5

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

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

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

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

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

+1

Хорошие очки. В пользовательском компоненте есть ли причина предпочесть переопределять 'getPreferredSize()' против вызова 'getPreferredSize()'? – trashgod

+1

В пользовательском компоненте вы всегда должны переопределять getPreferredSize(), потому что размер может динамически изменяться по мере изменения свойств компонента. – camickr

+0

ImageIcon, похоже, имеет довольно низкое ограничение размеров, похоже, даже зависит от платформы. В Win 10 я могу показать 32768x400 RGB-изображений, как ImageIcon, встроенный в JLabel, в то время как максимальная ширина Ubuntu 16.10 составляет от 16384 до 32768. Прохладный материал заключается в том, что это не вызывает ошибки, и вы начинаете поиск ..... – user1050755

Смежные вопросы