我想为我的swing项目
实现以下目标我能够通过扩展JPanel和使用JLayer来实现这一点。
我尝试使用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方法。
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 :(得分:2)
如AlphaComposite
所示,不要直接使用here,而是尝试使用RescaleOp
来改变图像的颜色/ alpha波段,如example所示。这将允许您根据需要静音整个图像的色调。使用getSubimage()
复制原始图像的一部分以恢复突出显示。