我想實現我的揮杆項目下面,添加視口的JPanel
我能夠通過擴展JPanel並使用JLayer得到這個。
我嘗試使用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方法。
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
}
}
}
我可以做到這一點,但我的應用程序還需要一個按鈕來隨機更改視口位置,並通過ImagePanel類設置圖像,這將迫使我每次更改圖像時發送一個圖像實例到LayerUI類圖片。 –
@JaymitDesai:ImagePanel將需要訪問兩個圖像,靜音和原始。 – trashgod
@trashgod感謝您的幫助,我使用您提供的第一個解決方案。我很快會更新我的SSCCE。我想將您的答案標記爲正確的答案,但由於您評論過我無法這樣做。 –