在 JScrollPane 中按比例绘制图像

Posted

技术标签:

【中文标题】在 JScrollPane 中按比例绘制图像【英文标题】:Drawing an image in JScrollPane within scale 【发布时间】:2013-12-13 18:39:06 【问题描述】:

我有一个滚动窗格来加载图像。我不会用她的自然尺寸这张图片,如果这张图片太大,我不会激活滚动条,但是这条指令

 g.drawImage(immagine, 0, 0, getWidth(), getHeight(), this); 

用于放置在滚动窗格中的缩放图像。我能做什么?

类桂:

导入 java.awt.*; 导入 java.awt.event.*; 导入java.io.File; 导入 javax.swing.*; 公共类 Gui 实现 ActionListener 私有 JFrame frmEditor; 私有 Mappa 内容; 私人 JMenuItem mntmSfondo; 私有 JScrollPane 可滚动; /** *启动应用程序。 */ 公共静态无效主要(字符串[]参数) EventQueue.invokeLater(new Runnable() 公共无效运行() 尝试 Gui 窗口 = new Gui(); window.frmEditor.setVisible(true); 捕捉(异常 e) e.printStackTrace(); ); /** * 创建应用程序。 */ 公共桂() 初始化(); /** * 初始化框架的内容。 */ 私人无效初始化() frmEditor = new JFrame(); frmEditor.setFont(UIManager.getFont("TextArea.font")); frmEditor.setBounds(50, 50, 1024, 768); frmEditor.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frmEditor.getContentPane().setLayout(new BorderLayout(0, 0)); JPanel panelTile = new JPanel(); panelTile.setLayout(new BorderLayout(0, 0)); 内容 = 新 Mappa(null); content.setMinimumSize(新维度(150, 150)); 可滚动 = 新 JScrollPane(内容); frmEditor.getContentPane().add(scrollabile, BorderLayout.CENTER); inizializzaMenu(); /** * 初始化菜单。 */ 私人无效 inizializzaMenu() JMenuBar menuBar = new JMenuBar(); frmEditor.setJMenuBar(menuBar); JMenu mnAltro = new JMenu("修改"); menuBar.add(mnAltro); mntmSfondo = new JMenuItem("加载背景"); mntmSfondo.addActionListener(this); mnAltro.add(mntmSfondo); 公共无效actionPerformed(ActionEvent e) 对象源 = e.getSource(); 如果(来源 == mntmSfondo) JFileChooser fc = new JFileChooser("tuttiSfondi"); int 结果 = fc.showOpenDialog(null); 如果(结果 == JFileChooser.APPROVE_OPTION) 文件文件 = fc.getSelectedFile(); 尝试 内容.setImage(文件); //content = new Mappa(file); //scrollabile.setViewportView(content); 捕捉(异常前) 如果(结果 == JFileChooser.CANCEL_OPTION)

类映射:

导入 java.awt.*; 导入 java.awt.image.BufferedImage; 导入java.io.*; 导入 javax.imageio.ImageIO; 导入 javax.swing.*; 公共类 Mappa 扩展 JPanel BufferedImage 想象; 公共Mappa(文件fileImmagine) if (fileImmagine != null ) 缓冲图像 img = null; 尝试 img = ImageIO.read(new File(fileImmagine.getPath())); 捕捉(IOException e) e.printStackTrace(); this.immagine = img; 重绘(); 公共无效 setImage(文件文件)抛出 IOException this.immagine = ImageIO.read(file); 字符串名称 = file.getPath(); System.out.println(name); 重绘(); 公共无效paintComponent(图形g) super.paintComponent(g); g.clearRect(0, 0, 4000, 4000); g.drawImage(this.immagine, 0, 0, getWidth(), getHeight(), this); System.out.println("在 Mappa 上调用 Repaint()");

【问题讨论】:

【参考方案1】:

JScrollPane,或更确切地说,JViewport 将使用组件(或在本例中为“视图”)的首选大小作为确定视图应该有多大的基础。

当视图扩展超出滚动窗格的大小时,它将显示滚动条。

所以基本上,你需要覆盖public class Mappa extends JPanel 面板的getPreferredSize,例如

public class Mappa extends JPanel 
    //...
    public Dimension getPreferredSize() 
        return immagine == null ? new Dimension(200, 200) : new Dimension(immagine.getWidth(), immagine.getHeight());
    
    //...

这将鼓励JViewport 始终与图像大小相同。

还有两件事……

首先,你不应该依赖幻数,例如

g.clearRect(0, 0, 4000, 4000);

应该更像...

g.clearRect(0, 0, getWidth(), getHeight());

其次,

super.paintComponent(g);

无论如何都会这样做,所以调用clearRect 是毫无意义的......

你可能还想看看Scrollable,但这是一个相当高级的话题

【讨论】:

我错过了一点,如果我需要JScrollPane 对图像的视图做出反应,为什么还要使用JPanel 并覆盖paintComponent 函数! JLabel 已经在为我做这件事了。不是一点不必要的开销。 :( @Sage 我只是根据 OP 所做的事情来回答,希望我们可以教他们一些有关事情在此过程中如何运作的知识。是的,除非您正在进行某种处理和/或动态调整大小,否则JLabel 通常是更好的方法。但多年后,我倾向于不使用JLabel 这么多......因为我想做图像的动态重新缩放:P 你的回答从一开始对我来说就更清楚了,偏离了方向。只是想说,然后说:) 添加覆盖的方法 getPreferedSize() 我解决了滚动条的问题。谢谢。但是我需要加载一个具有她真实尺寸的图像,这个问题仍然没有解决。例如:我有图像 1920*1080,我的 JFrame 在这里初始化:frmEditor.setBounds(50, 50, 1024, 768);所以我的图像被缩放了...... @MadProgrammer 是的,我知道在这种情况下指令 g.clearRect(...) 是愚蠢的。它是糟糕编程的残余。我非常非常初学者。 :-) 感谢您的耐心等待。【参考方案2】:

我不会用她的自然尺寸这张图片,如果这张图片太 大,我不会激活滚动条,

使用JLabel 包含图像并将其包装在JScrollPane 中应该可以轻松实现您想要的。从以下示例中获取提示:

class AFrame extends JFrame

   public AFrame()
  

     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     setTitle("Image view Demo with JScrollPane");

     ImageIcon image = new ImageIcon("myImage.png"); // pass the file location of an image
     JLabel label = new JLabel(image);
     JScrollPane scrollPane = new JScrollPane(label);
     scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
     scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
     add(scrollPane, BorderLayout.CENTER);
     pack();
  

 public static void main(String[] args)
 
    SwingUtilities.invokeLater(new Runnable() 

       @Override
       public void run() 
          new AFrame().setVisible(true);
       
    );

  

【讨论】:

我想我不能使用这个方法,因为我需要在这个图像上绘制。我用它作为背景。

以上是关于在 JScrollPane 中按比例绘制图像的主要内容,如果未能解决你的问题,请参考以下文章

用比例绘制 UIImage 并平移

爪哇。无法在 JScrollPane 中添加 JPanel

python(matplotlib)三维图像绘制,旋转坐标轴视角,坐标轴拉伸,缩放比例

setVisible() 和正在绘制的组件之间会发生啥?

如何在ggplot中按指定顺序绘制值向量?

如何在android中按名称访问可绘制资源