将ViewPort添加到JPanel

时间:2015-07-11 09:33:56

标签: java swing

我想为我的swing项目enter image description here

实现以下目标

我能够通过扩展JPanel和使用JLayer来实现这一点。 enter image description here

我尝试使用AlphaComposite,但它没有用。

Edit1:我认为JTable或JViewport可以帮助我获得我想要的东西,但我不知道如何使用它们。

Edit2:更新了SSCCE,非常感谢trashgod的建议。 我已经使用了Scalr库,因为在使用Image类的getScaledInstance方法之后,如果我尝试使用BufferedImage的getSubImage方法,则抛出以下异常:

  

java.lang.ClassCastException:sun.awt.image.ToolkitImage不能   强制转换为java.awt.image.BufferedImage

由于getScaledInstance方法生成的Image是ToolkitImage的一个实例,因此无法将其强制转换为BufferedImage。

如果您不想使用Scalr库,可以使用this post中建议的代码来缩放BufferedImage,而不是使用getSubImage方法。

enter image description here

SCSE.java

import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.util.Random;
import javax.swing.*;
import javax.swing.plaf.LayerUI;
import org.imgscalr.Scalr;

public class SCSE {

    private JFrame mainFrame;
    private JPanel mainPanel;
    private GridView gridView;
    private JButton imgBtn, shuffleBtn;
    private int gridX = -1, gridY = -1, gridWidth = -1, gridHeight = -1;
    private boolean isGridEmpty = false;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            SCSE sc = new SCSE();

            sc.createGUI();

        });
    }

    private void createGUI() {

        mainFrame = new JFrame();
        mainFrame.setSize(500, 500);
        mainFrame.setResizable(false);
        mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        mainPanel = new JPanel(new BorderLayout());

        gridView = new GridView();

        imgBtn = new JButton("Get-Image");
        shuffleBtn = new JButton("Shuffle-ViewPort");
        imgBtn.addActionListener((ActionEvent evt) -> {
            try {
                gridView.setImage(ImageIO.read(new URL("http://www.keenthemes.com/preview/metronic/theme/assets/global/plugins/jcrop/demos/demo_files/image1.jpg")));
            } catch (IOException ex) {
                System.out.println(ex);
            }
        });

        shuffleBtn.addActionListener((ActionEvent evt) -> {
            gridView.startShuffle();
        });

        mainPanel.add(gridView.getComponent(), BorderLayout.CENTER);
        mainPanel.add(imgBtn, BorderLayout.NORTH);
        mainPanel.add(shuffleBtn, BorderLayout.SOUTH);
        mainFrame.add(mainPanel);
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setVisible(true);
    }

    class GridView {

        private Random shuffleRandom;
        private RegisterUI layerUi = null;
        private JLayer<JPanel> gridLayer = null;
        private ImagePanel mainPanel = null;
        private int gridNos = 21;   //number of grids
        int digit[];
        private int viewportDimensions = 4; //no of rows and columns in viewport
        private JLabel gridLabel[][] = new JLabel[gridNos][gridNos];
        private int gridX = -1, gridY = -1, gridWidth = -1, gridHeight = -1;
        private boolean isGridInitialized = false;

        public GridView() {
            initPersuasive();
            initPanel();
            initGrids();
        }

        private void initPanel() {
            mainPanel = new ImagePanel();
            mainPanel.setLayout(new GridLayout(gridNos, gridNos, 0, 0));                 //creates layout to place labels in grid form
            layerUi = new RegisterUI();
            gridLayer = new JLayer<>(mainPanel, layerUi);
        }

        private void initGrids() {
            for (int i = 0; i < gridNos; i++) {
                for (int j = 0; j < gridNos; j++) {
                    gridLabel[i][j] = new JLabel();
                    gridLabel[i][j].setOpaque(false);
                    gridLabel[i][j].setName("" + (i + 1));         // Since for loop index is 0 to 80, we add 1 to the name to make it 1 to 81
                    mainPanel.add(gridLabel[i][j]);              //add it to mainPanel
                }
            }
        }

        private void initPersuasive() {
            shuffleRandom = new Random();
            digit = new int[2];

        }

        private void random() {

            digit[0] = shuffleRandom.nextInt(gridNos - viewportDimensions);
            digit[1] = shuffleRandom.nextInt(gridNos - viewportDimensions);
        }

        public void startShuffle() {
            random();
            int x = gridLabel[digit[0]][digit[1]].getX();
            int y = gridLabel[digit[0]][digit[1]].getY();
            layerUi.placeViewport(x, y);
        }

        public void stopShuffle() {
            layerUi.removeViewPort();
        }

        public void setupGridView() {

            gridX = gridLabel[0][0].getX();
            gridY = gridLabel[0][0].getY();
            gridWidth = gridLabel[0][0].getWidth();
            gridHeight = gridLabel[0][0].getHeight();
            mainPanel.setValues(gridX, gridY);
            layerUi.setViewSize(gridWidth * viewportDimensions, gridHeight * viewportDimensions);

        }

        public void setImage(BufferedImage img) {
            if (!isGridInitialized) {
                setupGridView();
                isGridInitialized = true;
            }
            BufferedImage sendImg = Scalr.resize(img, Scalr.Mode.FIT_EXACT, gridWidth * gridNos, gridHeight * gridNos, Scalr.OP_ANTIALIAS);
            layerUi.setupViewport(img);
            mainPanel.paintImage(img);
        }

        public JLayer<JPanel> getComponent() {
            return gridLayer;
        }

    }

    class RegisterUI extends LayerUI<JPanel> {

        private int viewX, viewY, viewWidth, viewHeight;
        private boolean shuffleIsRunning = false;
        private BufferedImage viewportImage = null;

        private void drawPCCP(Graphics g, int w, int h) {
            Graphics2D g2 = ((Graphics2D) g);
            Color c = new Color(1.0f, 1.0f, 1.0f, 0.7f);
            g2.setPaint(c);
            g2.fillRect(0, 0, w, h);
            BufferedImage highlightGrid = Scalr.pad(Scalr.crop(viewportImage, viewX, viewY, viewWidth, viewHeight), 2, Color.BLACK, Scalr.OP_ANTIALIAS);
            g2.drawImage(highlightGrid, viewX, viewY, null);
            g2.dispose();
        }

        public void paint(Graphics g, JComponent c) {
            super.paint(g, c);
            int w = c.getWidth();
            int h = c.getHeight();
            if (shuffleIsRunning) {
                drawPCCP(g, w, h);
            }
        }

        public void setupViewport(BufferedImage bi) {
            viewportImage = bi;
        }

        public void setViewSize(int w, int h) {
            viewWidth = w;
            viewHeight = h;
        }

        public void placeViewport(int x, int y) {
            viewX = x;
            viewY = y;
            if (!shuffleIsRunning) {
                shuffleIsRunning = true;
            }
            firePropertyChange("shuffleui", 0, 1);

        }

        public void removeViewPort() {
            if (!shuffleIsRunning) {
                return;
            }
            viewX = 0;
            viewY = 0;
            viewWidth = 0;
            viewHeight = 0;
            shuffleIsRunning = false;
            firePropertyChange("shuffleui", 0, 1);
        }

        @Override
        public void applyPropertyChange(PropertyChangeEvent evt, JLayer<? extends JPanel> l) {
            if ("disableui".equals(evt.getPropertyName()) || "shuffleui".equals(evt.getPropertyName())) {
                l.repaint();
            }
        }

    }

    class ImagePanel extends JPanel {

        private BufferedImage displayImage = null;
        private int x, y;

        public void setValues(int x, int y) {
            this.x = x;
            this.y = y;

        }

        public void paintImage(BufferedImage bi) {
            System.out.print(bi);
            displayImage = bi;
            repaint(); // repaint calls paintComponent method internally
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(displayImage, x, y, this);   // To Paint the image on the panel

        }
    }
}

1 个答案:

答案 0 :(得分:2)

AlphaComposite所示,不要直接使用here,而是尝试使用RescaleOp来改变图像的颜色/ alpha波段,如example所示。这将允许您根据需要静音整个图像的色调。使用getSubimage()复制原始图像的一部分以恢复突出显示。