java - 将 ViewPort 添加到 JPanel

标签 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 cannot be cast to java.awt.image.BufferedImage

由于 getScaledInstance 方法生成的 Image 是 ToolkitImage 的一个实例,所以它不能转换为 BufferedImage。

如果您不想使用 Scalr 库,可以使用 this 中建议的代码发布以缩放 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

        }
    }
}

最佳答案

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

关于java - 将 ViewPort 添加到 JPanel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31355656/

相关文章:

java - 执行网络命令android

java - 我应该把工作线程放在哪里

java - JComponent 脱离效果

java - 更大的 TextField Java 中的更小的 TextField

c# - C# 和 java 中的 volatile 有什么区别?

java - 在 Java 中使用证书进行编程

java - 是否可以使用通配符创建路由?

java - 如何在Java Swing中制作按钮点击 block ?

java - 返回对象数组方法

java - Android 日志中 Activity 类名称后的美元 ($) 符号(非匿名内部类)