是否可以将JComponent及其所有子项绘制到另一个组件?

时间:2013-08-03 08:00:06

标签: java swing graphics jscrollpane jviewport

我有一个名为JPanel的扩展GridPanel类。它允许您从JList将图像拖放到其中。 GridPanel允许您使用鼠标拖动图像并根据需要重新排列它们。我感兴趣的是制作GridPanel组件的缩略图视图。

如果我理解正确,将JScrollPane的视图设为GridPanel会使GridPanel成为JViewPort的孩子,这将成为{{1}的孩子}}。目前JScrollPane已设置为GridPanel的视图,我很确定JScrollPane不能有两个父母。所以我不能让两个组件共享相同的视图,但我真的只需要缩略图视图来绘制GridPanel的缩放视觉副本。

这引出了我的问题。是否可以复制GridPanel涂料,但将其涂在完全独立的组件上?

这是我尝试过的一个例子,以防我不被理解。

GridPanel

我希望发生的是两个组件都显示同一组彩色import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; public class TestMain { public static void main(String[] a) { Color[] colors = new Color[]{Color.green, Color.red, Color.blue, Color.yellow}; final JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationByPlatform(true); JPanel content = new JPanel(); frame.setContentPane(content); content.setLayout(new FlowLayout()); //using variable names to try and help relate to my question final JPanel gridPanel = new JPanel(); gridPanel.setPreferredSize(new Dimension(200,200)); gridPanel.setLayout(new GridLayout(2, 2)); JLabel label; for (Color c: colors){ label = new JLabel(); label.setOpaque(true); label.setBackground(c); gridPanel.add(label); } JScrollPane gridScroll = new JScrollPane(gridPanel); final JScrollPane thumbnailScroll = new JScrollPane(); thumbnailScroll.setPreferredSize(new Dimension(200,200)); JButton tryThumbnailView = new JButton("Activate Thumbnail"); tryThumbnailView.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent arg0) { thumbnailScroll.setViewportView(gridPanel); frame.repaint(); } }); content.add(tryThumbnailView); content.add(gridScroll); content.add(thumbnailScroll); frame.pack(); frame.setVisible(true); } } ,而不重复那些JLabels

2 个答案:

答案 0 :(得分:1)

您所要做的就是“获取一个组件的渲染结果”并重复使用它。 这需要:

  1. 拦截渲染过程 - 覆盖绘制(Graphics)方法
  2. 创建自己的图像以渲染到
  3. 将您的图片渲染为原始图片
  4. 将图像渲染到其他组件 - 覆盖绘制(图形)方法
  5. 前三个步骤可以这样做:

    @Override
    public void paint(Graphics originalGraphics) {
      GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment();
      GraphicsConfiguration c = e.getDefaultScreenDevice().getDefaultConfiguration();
      //create own image to paint to
      BufferedImage image = c.createCompatibleImage(getWidth(), getHeight());
      Graphics2D reusableGraphics = image.createGraphics();
      //let it paint into our graphics
      super.paint(reusableGraphics);
      // draw image on this component
      originalGraphics.drawImage(image, 0, 0, null);
      // draw image on other component
      otherComponent.setMirrorImage(image);
    }
    

    在otherComponent中,您必须保存图像并在需要时绘制它:

    @Override
    public void paint(Graphics g) {
      if (mirroredImage == null) {
        super.paintAll(g);
      } else {
        g.drawImage(mirroredImage, 0, 0, getWidth() * 3 / 4, getHeight() * 3 / 4, null);
      }
    }
    public void setMirrorImage(BufferedImage mirroredImage) {
      this.mirroredImage = mirroredImage;
      repaint();
    }
    

    您可以查看here以获取完整示例

答案 1 :(得分:0)

您可以像这样覆盖paintComponent

protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;
    g2d.scale(scaleFactor, scaleFactor);
    gridPanel.paintComponenet(g);
}

这假设gridPanelpaintComponent覆盖为public,或者此类必须与GridPanel位于同一个包中。