Java: 用透明 JButton 覆盖图像
Java: Overlay an Image with Transparent JButton
所以我正在创建一个代表自动售货机的 GUI。我只是 运行 遇到了一些问题,试图让布局按照我想要的方式工作。我的想法是将图像插入 JLabel,然后在特定位置用透明 JButton 覆盖该图像,这样当您在特定位置单击图像时,它会触发 JButton。我还没有达到透明度,因为我目前一直在研究如何将 JButton 精确地放置在它们需要的位置。
我试过 setLocation 和 setBounds,但没有成功。任何关于如何将 jbuttons 准确定位在可能的自动售货机选择上的帮助都会很棒。
import javax.swing.*;
import javax.imageio.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
public class vendMachine extends JFrame
{
//Frame Dimensions
private static final int FRAME_HEIGHT = 800;
private static final int FRAME_WIDTH = 800;
private JPanel totalGUI, imagePanel, coinPanel;
public vendMachine()
{
createComponents();
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setTitle("Vending Machine");
}
private void createComponents()
{
try
{
BufferedImage machineImg = ImageIO.read(new File("images/pepsivend.jpg"));
JLabel machineImgLabel = new JLabel(new ImageIcon(machineImg));
machineImgLabel.setLayout(new FlowLayout());
JButton test = new JButton("TEST BUTTON");
machineImgLabel.add(test);
//test.setBounds(0,0,0,0);
ImageIcon pennyIcon = new ImageIcon("images/coins/penny.jpg");
JButton pennyButton = new JButton(pennyIcon);
ImageIcon nickelIcon = new ImageIcon("images/coins/nickel.jpg");
JButton nickelButton = new JButton(nickelIcon);
ImageIcon dimeIcon = new ImageIcon("images/coins/dime.jpg");
JButton dimeButton = new JButton(dimeIcon);
ImageIcon quarterIcon = new ImageIcon("images/coins/quarter.jpg");
JButton quarterButton = new JButton(quarterIcon);
coinPanel = new JPanel();
coinPanel.setLayout(new GridLayout(4,1));
coinPanel.add(pennyButton);
coinPanel.add(nickelButton);
coinPanel.add(dimeButton);
coinPanel.add(quarterButton);
totalGUI = new JPanel();
totalGUI.setLayout(new BorderLayout());
totalGUI.add(machineImgLabel, BorderLayout.CENTER);
totalGUI.add(coinPanel, BorderLayout.EAST);
}
catch (IOException e)
{
e.printStackTrace();
}
add(totalGUI);
}
}
在上图中,我希望获得有关如何获取测试按钮的帮助,以覆盖在百事可乐选择之上。从那里我可以着手使它透明并删除边框和文本。
编辑添加:none 个按钮可以执行任何操作。在添加任何其他内容之前简单地尝试让布局继续
不清楚您的实际问题是什么,但是,我将从布局开始...
没有任何一种布局可以满足您的所有需求,有时,您需要使用多种布局并将它们组合在一起。此示例使用 BorderLayout
和 GridBagLayout
来设置基本布局...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new VendingMachinePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class VendingMachinePane extends JPanel {
public VendingMachinePane() {
setLayout(new BorderLayout());
JLabel label = new JLabel("Cover");
// Demonstration purpose only
label.setPreferredSize(new Dimension(200, 400));
label.setOpaque(true);
label.setBackground(Color.BLUE);
add(label);
JPanel optionsPane = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.anchor = GridBagConstraints.NORTH;
optionsPane.setBackground(Color.DARK_GRAY);
optionsPane.add(new JLabel("Coin Slot"), gbc);
optionsPane.add(makeButton("Pepsi"), gbc);
optionsPane.add(makeButton("Diet Pepsi"), gbc);
optionsPane.add(makeButton("Slice"), gbc);
optionsPane.add(makeButton("Dr Pepper"), gbc);
optionsPane.add(makeButton("Lipton"), gbc);
optionsPane.add(makeButton("Mountain Dew"), gbc);
optionsPane.add(makeButton("Schweppes"), gbc);
gbc.weighty = 1;
optionsPane.add(makeButton("Pepsi"), gbc);
add(optionsPane, BorderLayout.LINE_END);
}
protected JButton makeButton(String text) {
JButton btn = new JButton(text);
btn.setBorderPainted(false);
btn.setContentAreaFilled(false);
btn.setMargin(new Insets(4, 4, 4, 4));
btn.setOpaque(false);
return btn;
}
}
}
至于你的 "overlay buttons" 问题,对我来说,这没有意义,因为 JButton
有 icon
属性,为什么不直接使用JButton
从什么开始?
只需更改按钮的 borderPainted
contentAreaFilled
和 opaque
属性即可使按钮透明
// You can pass a `Icon` instead of a `String` to the constructor
JButton btn = new JButton(text);
btn.setBorderPainted(false);
btn.setContentAreaFilled(false);
btn.setMargin(new Insets(4, 4, 4, 4));
btn.setOpaque(false);
不要忘记设置 ActionListener
;)
已更新,基于更新后的要求...
你可以...
将图像分解成多个部分,使每个元素成为自己的图像,然后简单地将它们应用到按钮上,使用与上述类似的方法
你可以...
在图像上绘制热点,并在 mouseClicked
事件发生的地方使用 MouseListener
监视器 - 虽然您确实失去了键盘输入的优势
你可以...
绘制图像的热点并使用 GridBagLayout
或自定义布局管理器,将按钮映射到图像上。
所以我正在创建一个代表自动售货机的 GUI。我只是 运行 遇到了一些问题,试图让布局按照我想要的方式工作。我的想法是将图像插入 JLabel,然后在特定位置用透明 JButton 覆盖该图像,这样当您在特定位置单击图像时,它会触发 JButton。我还没有达到透明度,因为我目前一直在研究如何将 JButton 精确地放置在它们需要的位置。
我试过 setLocation 和 setBounds,但没有成功。任何关于如何将 jbuttons 准确定位在可能的自动售货机选择上的帮助都会很棒。
import javax.swing.*;
import javax.imageio.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
public class vendMachine extends JFrame
{
//Frame Dimensions
private static final int FRAME_HEIGHT = 800;
private static final int FRAME_WIDTH = 800;
private JPanel totalGUI, imagePanel, coinPanel;
public vendMachine()
{
createComponents();
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setTitle("Vending Machine");
}
private void createComponents()
{
try
{
BufferedImage machineImg = ImageIO.read(new File("images/pepsivend.jpg"));
JLabel machineImgLabel = new JLabel(new ImageIcon(machineImg));
machineImgLabel.setLayout(new FlowLayout());
JButton test = new JButton("TEST BUTTON");
machineImgLabel.add(test);
//test.setBounds(0,0,0,0);
ImageIcon pennyIcon = new ImageIcon("images/coins/penny.jpg");
JButton pennyButton = new JButton(pennyIcon);
ImageIcon nickelIcon = new ImageIcon("images/coins/nickel.jpg");
JButton nickelButton = new JButton(nickelIcon);
ImageIcon dimeIcon = new ImageIcon("images/coins/dime.jpg");
JButton dimeButton = new JButton(dimeIcon);
ImageIcon quarterIcon = new ImageIcon("images/coins/quarter.jpg");
JButton quarterButton = new JButton(quarterIcon);
coinPanel = new JPanel();
coinPanel.setLayout(new GridLayout(4,1));
coinPanel.add(pennyButton);
coinPanel.add(nickelButton);
coinPanel.add(dimeButton);
coinPanel.add(quarterButton);
totalGUI = new JPanel();
totalGUI.setLayout(new BorderLayout());
totalGUI.add(machineImgLabel, BorderLayout.CENTER);
totalGUI.add(coinPanel, BorderLayout.EAST);
}
catch (IOException e)
{
e.printStackTrace();
}
add(totalGUI);
}
}
在上图中,我希望获得有关如何获取测试按钮的帮助,以覆盖在百事可乐选择之上。从那里我可以着手使它透明并删除边框和文本。
编辑添加:none 个按钮可以执行任何操作。在添加任何其他内容之前简单地尝试让布局继续
不清楚您的实际问题是什么,但是,我将从布局开始...
没有任何一种布局可以满足您的所有需求,有时,您需要使用多种布局并将它们组合在一起。此示例使用 BorderLayout
和 GridBagLayout
来设置基本布局...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new VendingMachinePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class VendingMachinePane extends JPanel {
public VendingMachinePane() {
setLayout(new BorderLayout());
JLabel label = new JLabel("Cover");
// Demonstration purpose only
label.setPreferredSize(new Dimension(200, 400));
label.setOpaque(true);
label.setBackground(Color.BLUE);
add(label);
JPanel optionsPane = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.anchor = GridBagConstraints.NORTH;
optionsPane.setBackground(Color.DARK_GRAY);
optionsPane.add(new JLabel("Coin Slot"), gbc);
optionsPane.add(makeButton("Pepsi"), gbc);
optionsPane.add(makeButton("Diet Pepsi"), gbc);
optionsPane.add(makeButton("Slice"), gbc);
optionsPane.add(makeButton("Dr Pepper"), gbc);
optionsPane.add(makeButton("Lipton"), gbc);
optionsPane.add(makeButton("Mountain Dew"), gbc);
optionsPane.add(makeButton("Schweppes"), gbc);
gbc.weighty = 1;
optionsPane.add(makeButton("Pepsi"), gbc);
add(optionsPane, BorderLayout.LINE_END);
}
protected JButton makeButton(String text) {
JButton btn = new JButton(text);
btn.setBorderPainted(false);
btn.setContentAreaFilled(false);
btn.setMargin(new Insets(4, 4, 4, 4));
btn.setOpaque(false);
return btn;
}
}
}
至于你的 "overlay buttons" 问题,对我来说,这没有意义,因为 JButton
有 icon
属性,为什么不直接使用JButton
从什么开始?
只需更改按钮的 borderPainted
contentAreaFilled
和 opaque
属性即可使按钮透明
// You can pass a `Icon` instead of a `String` to the constructor
JButton btn = new JButton(text);
btn.setBorderPainted(false);
btn.setContentAreaFilled(false);
btn.setMargin(new Insets(4, 4, 4, 4));
btn.setOpaque(false);
不要忘记设置 ActionListener
;)
已更新,基于更新后的要求...
你可以...
将图像分解成多个部分,使每个元素成为自己的图像,然后简单地将它们应用到按钮上,使用与上述类似的方法
你可以...
在图像上绘制热点,并在 mouseClicked
事件发生的地方使用 MouseListener
监视器 - 虽然您确实失去了键盘输入的优势
你可以...
绘制图像的热点并使用 GridBagLayout
或自定义布局管理器,将按钮映射到图像上。