0

我遇到了两个问题类的问题。一种用于绘制事物,另一种用于在先前绘制的对象上实现平移和缩放。

想象一下我的界面只有两个吐出的面板,一个是空的(顶部),一个是带有滑块(bot)的:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import java.awt.BorderLayout;
import javax.swing.JSplitPane;
import javax.swing.JPanel;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JSlider;
import java.awt.FlowLayout;

public class Interface {
private JFrame mainFrame;
public static void main(String[] args) {
  EventQueue.invokeLater(new Runnable() {
   public void run() {
    try {Interface window = new Interface();window.mainFrame.setVisible(true);
            } catch (Exception e) { e.printStackTrace();}
   }
  });
}
public Interface() {initialize();}
private void initialize() {
  mainFrame = new JFrame();
  mainFrame.setTitle("LXView");
  mainFrame.setMinimumSize(new Dimension(800, 600));
  mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  mainFrame.setExtendedState(mainFrame.getExtendedState()| JFrame.MAXIMIZED_BOTH);
  mainFrame.getContentPane().setBackground(Color.WHITE);
  mainFrame.getContentPane().setLayout(new BorderLayout(0, 0));
  JSplitPane splitPane = new JSplitPane();
  splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
  splitPane.setOneTouchExpandable(true);
  splitPane.setBackground(Color.WHITE);
  mainFrame.getContentPane().add(splitPane, BorderLayout.CENTER);
  splitPane.setResizeWeight(0.99);
  JScrollPane scrollPane = new JScrollPane();
  scrollPane.setEnabled(false);
  splitPane.setLeftComponent(scrollPane);
  Render topPane = new Render();
  scrollPane.setViewportView(topPane);
  topPane.setLayout(new BoxLayout(topPane, BoxLayout.X_AXIS));
  JPanel botPane = new JPanel();
  splitPane.setRightComponent(botPane);
  botPane.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
  JLabel zoomLevel = new JLabel("Zoom level:");
  botPane.add(zoomLevel);
  JSlider slider = new JSlider(JSlider.HORIZONTAL, 25, 100, 100);
  slider.setMajorTickSpacing(15);
  slider.setMinorTickSpacing(5);
  slider.setPaintTicks(true);
  slider.setPaintLabels(true);
  slider.setPreferredSize(new Dimension(600,40));
  botPane.add(slider);
  PanAndZoom zoomer=new PanAndZoom(topPane.getLabel());
  slider.addChangeListener(zoomer);
}

顶部面板使用用于绘制图形的渲染类。简化:

import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Render extends JPanel {
JLabel envContainer;
Render() {
  super();
  ImageIcon imageIcon = new ImageIcon("/path/to/img1");
  JLabel envContainer = new JLabel(imageIcon);
  super.add(envContainer);
}
@Override
public void paint(Graphics g) {
  super.paint(g);
  /*Render stuff*/
}
public JLabel getLabel() {
  return envContainer;
}
}

给我带来麻烦的第三个班级在滑块上收听并根据它设置 JLabel 图标:

import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class PanAndZoom implements ChangeListener {
private JLabel label;
private BufferedImage image;


public PanAndZoom(JLabel lab){
  this.label=lab;
  try {
   image = ImageIO.read(new File("/path/to/img1"));
  } catch (IOException e) {
   e.printStackTrace();
  }
  label.setIcon(new ImageIcon("/path/to/img2"));//To test another img. It gives runtime errors.
}
public void stateChanged(ChangeEvent e) {
  int value = ((JSlider) e.getSource()).getValue();
  double scale = value / 100.0;
  BufferedImage scaled = getScaledImage(scale); // It also gives runtime errors.
  System.out.println("Scale:"+scale+" Value:"+value);
  label.setIcon(new ImageIcon(scaled));
  label.revalidate();

}
private BufferedImage getScaledImage(double scale) {
  int w = (int) (scale * image.getWidth());
  int h = (int) (scale * image.getHeight());
  BufferedImage bi = new BufferedImage(w, h, image.getType());
  Graphics2D g2 = bi.createGraphics();
  g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC);
  AffineTransform at = AffineTransform.getScaleInstance(scale, scale);
  g2.drawRenderedImage(image, at);
  g2.dispose();
  return bi;
}
}

如果 getLabel 方法成功返回了 JLabel,为什么我不能使用它?

4

1 回答 1

2

您是类 Render 的构造函数中的本地版本 envContainer 正在覆盖类实例 envContainer。

public class Render extends JPanel {
JLabel envContainer; //<---- class instance
Render() {
  super();
  ImageIcon imageIcon = new ImageIcon("/path/to/img1");
  JLabel envContainer = new JLabel(imageIcon); //<---- overriden by local instance, hence class instance remains null
  super.add(envContainer);
}

我的猜测是您并不是要使其成为本地版本,因为您没有在构造函数中使用它来做任何事情。对您的 Render 构造函数进行以下更改。

Render() {
  ..
  this.envContainer = new JLabel(imageIcon);
  ...
}
于 2013-06-29T00:58:13.680 回答