java - JLabel 无法从其他类中使用

标签 java swing jlabel image-resizing

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

将我的界面想象为只有两个分开的面板,一个是空的(顶部),一个带有 slider (机器人):

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;
}
}

第三个类给我带来了麻烦,它监听 slider 并根据它设置 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,为什么我不能使用它?

最佳答案

您的 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() {
  ..
  this.envContainer = new JLabel(imageIcon);
  ...
}

关于java - JLabel 无法从其他类中使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17375104/

相关文章:

java - 使用 Selenium 处理 InnerFrame

java - JFrame 在打开时陷入了一些奇怪的内部死锁

Java Canvas 无法正确调整大小

Java - 更新JLabel的图标时,新图标放在旧图标后面

Java:如何将控件而不是其数据拖放到新位置?

java - 使用 Java 从另一台机器搜索文件

java - 如何以正确的方式更新生产中的 Hibernate 应用程序?

java - 计算器控制台应用程序无法运行

java - 使用 ImageIO.read 时出现问题

java - 在 BoxLayout 中对齐 JLabel