簡體   English   中英

是否可以將JComponent及其所有子組件繪制到另一個組件?

[英]Is it possible to paint a JComponent and all its children to another component?

我有一個擴展的JPanel類,稱為GridPanel 它使您可以將圖像從JList拖放到其中。 GridPanel允許您用鼠標拖動圖像並根據需要重新排列圖像。 我感興趣的是制作GridPanel組件的縮略圖。

如果我理解正確,將JScrollPane的視圖設置為GridPanel會使GridPanel成為GridPanel的子JViewPort ,而JViewPort成為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 ,而不必重復這些JLabels

您要做的就是“獲取一個組件的渲染結果”並重新使用它。 這需要:

  1. 截取渲染過程-覆蓋paint(Graphics)方法
  2. 創建自己的圖像以渲染到
  3. 將圖像渲染為原始圖形
  4. 將圖像渲染到其他組件-覆蓋paint(Graphics)方法

前三個步驟可以這樣完成:

@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();
}

您可以在這里查看完整示例

您可以像這樣重寫paintComponent

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

假定gridPanel作為public重寫paintComponent ,或者此類必須與GridPanel同一包中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM