java - 需要使用 IntelliJ 更改 GUI 上的背景,但背景隐藏了按钮
问题描述
package imgscoring;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import static java.lang.System.exit;
public class IMGSCORING
{
private JButton button1;
private JPanel main;
private JButton button2;
private JLabel lblLed;
private JButton button3;
private JLabel label;
private JLabel logo;
private static Image i;
public IMGSCORING() {
button1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
try {
runProgam();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
button2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
exit(1);
}
});
Image i = Toolkit.getDefaultToolkit().createImage("C:\\Users\\djuwo\\Desktop\\icon.jpg");
}
public static void paint(Graphics g)
{
g.drawImage(i, 0, 0, null);
}
public void runProgam() throws IOException, InterruptedException {
QrScanner run = new QrScanner();
run.runProgram();
}
public JPanel getMain() {
return main;
}
public void setMain(JPanel main) {
this.main = main;
}
public static void main(String[] args) {
JFrame frame = new JFrame(" IMG FORMING Label Generator");
frame.setContentPane(new IMGSCORING().main);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
ImageIcon img = new ImageIcon("C:\\Users\\djuwo\\Desktop\\icon.jpg");
frame.setIconImage(img.getImage());
}
private void createUIComponents() {
// TODO: place custom component creation code here
logo = new JLabel(new ImageIcon("icon.jpg"));
}
}
我对使用 Java 的 gui 非常陌生,并且基于环顾四周并看到其他代码,我可以肯定地告诉我的代码与它应该看起来的样子相去甚远.. 希望获得有关如何正确格式化我的代码以及如何添加的反馈一个背景。程序正常工作,按钮响应,图标更改等。但我无法更改背景。起初我尝试了以下方法,但这显然没有用。
frame.setContentPane(new JLabel(new ImageIcon(ImageIO.read(new File("C:\\Users\\djuwo\\Desktop\\icon.jpg")))));
解决方案
在以下解决方案中,您可以看到以下步骤:
- 覆盖
paintComponent
,JPanel
以便在其背景中绘制图像。 - 在子类中添加您想要的任何元素
JPanel
。 - 将子类添加
JPanel
到JFrame
. setOpaque(false)
在子类JPanel
中以显示背景(我们绘制图像的位置)。
在第一个解决方案中,我只绘制一次图像,而不关心在调整大小时填充框架:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Objects;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class RegularMain extends JPanel {
private final BufferedImage bimg;
public RegularMain(final BufferedImage bimg) {
//super(); //FlowLayout already.
this.bimg = Objects.requireNonNull(bimg);
//Add your components here:
for (int i = 1; i <= 3; ++i)
super.add(prepare(new JButton("Button " + i)));
//Allow pixels to show through (ie the backgroung image to be shown):
super.setOpaque(false);
//Preparing the preferred size:
final Dimension prefsz = super.getPreferredSize(); //Gets the preferred size, after adding the components to this panel.
super.setPreferredSize(new Dimension(Math.max(prefsz.width, bimg.getWidth()), Math.max(prefsz.height, bimg.getHeight())));
}
@Override
protected void paintComponent(final Graphics g) {
g.drawImage(bimg, 0, 0, this);
super.paintComponent(g);
}
public static JButton prepare(final JButton button) {
button.addActionListener(e -> JOptionPane.showMessageDialog(button, "You clicked \"" + button.getText() + "\"!"));
return button;
}
public static void main(final String[] args) throws IOException {
final JFrame frame = new JFrame("Main frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new RegularMain(ImageIO.read(new File("your_image.png"))));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
但是,另一种方法是调整图像的大小以对应面板的大小:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Objects;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class TransformMain extends JPanel {
private final BufferedImage bimg;
public TransformMain(final BufferedImage bimg) {
//super(); //FlowLayout already.
this.bimg = Objects.requireNonNull(bimg);
//Add your components here:
for (int i = 1; i <= 3; ++i)
super.add(prepare(new JButton("Button " + i)));
//Allow pixels to show through (ie the backgroung image to be shown):
super.setOpaque(false);
//Preparing the preferred size:
final Dimension prefsz = super.getPreferredSize(); //Gets the preferred size, after adding the components to this panel.
super.setPreferredSize(new Dimension(Math.max(prefsz.width, bimg.getWidth()), Math.max(prefsz.height, bimg.getHeight())));
}
@Override
protected void paintComponent(final Graphics g) {
final Graphics2D g2d = (Graphics2D) g.create();
g2d.scale(getWidth() / (double) bimg.getWidth(), getHeight() / (double) bimg.getHeight());
g2d.drawImage(bimg, 0, 0, this);
g2d.dispose();
super.paintComponent(g);
}
public static JButton prepare(final JButton button) {
button.addActionListener(e -> JOptionPane.showMessageDialog(button, "You clicked \"" + button.getText() + "\"!"));
return button;
}
public static void main(final String[] args) throws IOException {
final JFrame frame = new JFrame("Main frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new TransformMain(ImageIO.read(new File("your_image.png"))));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
最后另一种方法是制作图像 a TexturePaint
,如果你想重复图像:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.TexturePaint;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class TextureMain extends JPanel {
private final TexturePaint paint;
public TextureMain(final BufferedImage bimg) {
//super(); //FlowLayout already.
paint = new TexturePaint(bimg, new Rectangle2D.Double(0, 0, bimg.getWidth(), bimg.getHeight()));
//Add your components here:
for (int i = 1; i <= 3; ++i)
super.add(prepare(new JButton("Button " + i)));
//Allow pixels to show through (ie the backgroung image to be shown):
super.setOpaque(false);
//Preparing the preferred size:
final Dimension prefsz = super.getPreferredSize(); //Gets the preferred size, after adding the components to this panel.
super.setPreferredSize(new Dimension(Math.max(prefsz.width, bimg.getWidth()), Math.max(prefsz.height, bimg.getHeight())));
}
@Override
protected void paintComponent(final Graphics g) {
final Graphics2D g2d = (Graphics2D) g.create();
g2d.setPaint(paint);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();
super.paintComponent(g);
}
public static JButton prepare(final JButton button) {
button.addActionListener(e -> JOptionPane.showMessageDialog(button, "You clicked \"" + button.getText() + "\"!"));
return button;
}
public static void main(final String[] args) throws IOException {
final JFrame frame = new JFrame("Main frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new TextureMain(ImageIO.read(new File("your_image.png"))));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
调整框架/面板的大小时,可以看到上述解决方案的差异。在第一种情况下,不应该调整框架的大小,所以我们只绘制一次图像,而不改变它的大小。在第二种情况下,图像大小跟随面板的大小。在最后一种情况下,我们将图像垂直和水平重复到面板的大小(使用TexturePaint
)。
所有案例都有一个共同点,那就是我们先绘制图像,然后paintComponent
再绘制图像。setOpaque
false
推荐阅读
- typescript - Typescript 类型断言,可以是数组或普通类型
- javascript - 我可以从 HTML 页面上的 JS 模块导入一些东西吗?
- neo4j - Neo4j - 如何组合来自多个 CSV 的节点和关系
- mysql - 设置 auto_increment_increment = 1 对现有表的影响
- c# - 使用 WCF 时如何为 OperationContract 指定命名空间?
- sql - 将行嵌套到多个 json 对象中
- laravel - 如何更改刀片 laravel 中的前缀语言环境?
- r - R 中的 fitdistrplus 包 - 离散/连续概率分布
- https - 如何使用我的 Arduino 自动获取某个网站的 SHA-1 指纹
- lte - 了解错误消息:spdlog::spdlog_ex