2015-07-11 58 views
3

我想實現我的揮杆項目下面,enter image description here添加視口的JPanel

我能夠通過擴展JPanel並使用JLayer得到這個。 enter image description here

我嘗試使用AlphaComposite事件,但它沒有奏效。編輯1:我覺得JTable或JViewport可能會幫助我得到我想要的,但我不知道如何使用它們。

編輯2:更新了SSCCE,謝謝你的建議trashgod。 我已經因爲使用Image類的getScaledInstance方法,如果我試圖用BufferedImage的getSubImage方法,下面的異常被拋出之後,利用了Scalr庫:

java.lang.ClassCastException:sun.awt .image.ToolkitImage不能 澆鑄到java.awt.image.BufferedImage中

由於通過getScaledInstance方法生成的圖像是這樣的,它不能被鑄造成一個BufferedImage ToolkitImage的實例。

如果你不想使用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 

     } 
    } 
} 
+0

我可以做到這一點,但我的應用程序還需要一個按鈕來隨機更改視口位置,並通過ImagePanel類設置圖像,這將迫使我每次更改圖像時發送一個圖像實例到LayerUI類圖片。 –

+0

@JaymitDesai:ImagePanel將需要訪問兩個圖像,靜音和原始。 – trashgod

+0

@trashgod感謝您的幫助,我使用您提供的第一個解決方案。我很快會更新我的SSCCE。我想將您的答案標記爲正確的答案,但由於您評論過我無法這樣做。 –

回答

2

代替使用直接AlphaComposite,如圖here,嘗試RescaleOp以改變圖像的顏色/ alpha頻帶,如圖此example的。這將允許您根據需要靜音整個圖像的色調。使用getSubimage()複製原始圖像的一部分以恢復高光。