Java 为什么添加透明度时透明按钮会显示帧的图像?
我正在为Java应用程序开发GUI,我想要一个背景图像。问题是,我有一种“抽屉”类型,里面装满了按钮,当按钮被选中时,按钮会以红色高位显示 Im使用buttonName.setBackground方法(新颜色(255、102、102、200));同时设置高位按钮和透明度。问题是,尽管该方法可以工作并使按钮透明,但透明显示的是按钮后面框架的随机部分,包括标题、另一个按钮、按钮所在的JScrollPane滚动条等。按钮的文本仍然显示,按钮也可以工作,但是背景显示了来自其他按钮或框架部分的文本 此外,我意识到,如果我点击一个按钮并将鼠标在所选按钮上多次移动,透明度开始累积,直到变成纯色Java 为什么添加透明度时透明按钮会显示帧的图像?,java,swing,jbutton,transparency,Java,Swing,Jbutton,Transparency,我正在为Java应用程序开发GUI,我想要一个背景图像。问题是,我有一种“抽屉”类型,里面装满了按钮,当按钮被选中时,按钮会以红色高位显示 Im使用buttonName.setBackground方法(新颜色(255、102、102、200));同时设置高位按钮和透明度。问题是,尽管该方法可以工作并使按钮透明,但透明显示的是按钮后面框架的随机部分,包括标题、另一个按钮、按钮所在的JScrollPane滚动条等。按钮的文本仍然显示,按钮也可以工作,但是背景显示了来自其他按钮或框架部分的文本 此外,
package buttonsbug;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
/**
*
* @author F&H
*/
public class ButtonsBug extends JFrame implements ActionListener {
private ArrayList<JButton> botones;
private JLabel panelPrin, panelNav, panelUser, panelImgUser, nombre, puesto;
private JButton logout, planDis, consuEmpleados, funConsultarPiezas, btnCalidad, compraMat, soySuper, histProy, crearProyecto, clientes, adminConsProye;
private JPanel buttonScroll;
private JScrollPane navScroll;
private BufferedImage img;
private Dimension screenSize;
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
try {
new ButtonsBug().setVisible(true);
} catch (Exception e) {
System.out.println(e.getMessage());
System.exit(0);
}
}
});
}
public ButtonsBug() {
botones = new ArrayList<>();
screenSize = Toolkit.getDefaultToolkit().getScreenSize();
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setSize(ajustarDimensiones(1400), ajustarDimensiones(800));
setContentPane(panelPrin = new JLabel());
panelPrin.setSize(ajustarDimensiones(1400), ajustarDimensiones(800));
try {
img = ImageIO.read(new File("src/tw3.png"));
Image dimg1 = img.getScaledInstance(panelPrin.getWidth(), panelPrin.getHeight(), Image.SCALE_SMOOTH);
ImageIcon imageIcon = new ImageIcon(dimg1);
panelPrin.setIcon(imageIcon);
} catch (IOException z) {
System.out.println(z.getMessage());
JOptionPane.showMessageDialog(this, "¡Error en la lectura de imagen!", "Error", JOptionPane.ERROR_MESSAGE);
}
panelPrin.setBackground(java.awt.Color.white);
panelPrin.add(panelNav = new JLabel());
// panelPrin.setOpaque(true);
// panelNav.setOpaque(true);
panelNav.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
// panelNav.setBackground(new Color(0, 0, 0, 150));
panelNav.setBounds(0, 0, ajustarDimensiones(305), ajustarDimensiones(771));
panelNav.add(panelUser = new JLabel());
panelNav.add(logout = new JButton());
logout.setContentAreaFilled(false);
// logout.setOpaque(true);
// panelUser.setOpaque(true);
panelUser.setBounds(ajustarDimensiones(1), ajustarDimensiones(1), ajustarDimensiones(303), ajustarDimensiones(88));
panelUser.add(panelImgUser = new JLabel());
panelUser.add(nombre = new JLabel());
panelUser.add(puesto = new JLabel());
nombre.setText("Wil Fonseca");
puesto.setText("Production manager");
nombre.setBounds(ajustarDimensiones(55), ajustarDimensiones(25), ajustarDimensiones(245), ajustarDimensiones(20));
puesto.setBounds(ajustarDimensiones(55), ajustarDimensiones(45), ajustarDimensiones(245), ajustarDimensiones(20));
nombre.setFont(new java.awt.Font("Arial", 1, ajustarDimensiones(14)));
puesto.setFont(new java.awt.Font("Arial", 1, ajustarDimensiones(12)));
nombre.setForeground(Color.white);
puesto.setForeground(Color.white);
logout.setText("Logout");
logout.setFont(new java.awt.Font("Arial", 1, ajustarDimensiones(34)));
logout.setBounds(ajustarDimensiones(1), ajustarDimensiones(691), ajustarDimensiones(303), ajustarDimensiones(88));
logout.setBackground(Color.white);
logout.setForeground(Color.red);
logout.addActionListener(this);
logout.setBorder(null);
logout.setBorderPainted(false);
logout.setFocusPainted(false);
panelImgUser.setBounds(ajustarDimensiones(3), ajustarDimensiones(24), ajustarDimensiones(40), ajustarDimensiones(40));
try {
img = ImageIO.read(new File("src/Usuario.png"));
Image dimg1 = img.getScaledInstance(panelImgUser.getWidth(), panelImgUser.getHeight(), Image.SCALE_SMOOTH);
ImageIcon imageIcon = new ImageIcon(dimg1);
panelImgUser.setIcon(imageIcon);
} catch (IOException z) {
System.out.println(z.getMessage());
}
setTitle("ButtonsBug");
setLocationRelativeTo(null);
setResizable(false);
setVisible(true);
buttonGenerator();
}
public int ajustarDimensiones(int coo) {
int newC = 0;
double res = (screenSize.getHeight());
float newRes;
if (res < 1080) {
if (coo == 1400) {
return 1208;
} else if (coo == 800) {
return 680;
}
}
if (coo == 0) {
return newC;
} else {
if (res < 1080) {
newRes = (918f / 1080f);
if (coo == 305) {
newC = (int) (newRes * coo) - 1;
} else if (coo == 90) {
newC = (int) (newRes * coo) - 1;
} else if (coo == 224) {
newC = (int) (newRes * coo) - 1;
} else if (coo == 601) {
newC = (int) (newRes * coo) + 3;
} else if (coo == 1066) {
newC = (int) (newRes * coo) - 1;
} else if (coo == 1474 || coo == 1576) {
newC = (int) (newRes * coo) + 1;
} else if (coo == 1059) {
newC = (int) (newRes * coo) - 10;
} else if (coo == 1095) {
newC = (int) (newRes * coo) + 14;
} else {
newC = (int) (newRes * coo);
}
} else {
newRes = (float) (res / 1080f);
newC = (int) (newRes * coo);
}
if (newC < 0) {
newC = 1;
}
}
return newC;
}
public void buttonGenerator() {
int y = 0;
panelNav.add(navScroll = new JScrollPane(buttonScroll = new JPanel(), JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER));
navScroll.setBorder(BorderFactory.createEmptyBorder());
navScroll.setBounds(ajustarDimensiones(1), ajustarDimensiones(90), ajustarDimensiones(303), ajustarDimensiones(600));
// navScroll.setBackground(Color.white);
navScroll.setOpaque(false);
navScroll.getVerticalScrollBar().setUnitIncrement(30);
navScroll.setPreferredSize(new Dimension(ajustarDimensiones(305), ajustarDimensiones(601)));
// buttonScroll.setBackground(Color.white);
buttonScroll.setPreferredSize(new Dimension(ajustarDimensiones(305), ajustarDimensiones(601)));
buttonScroll.setLayout(null);
navScroll.setViewportView(buttonScroll);
buttonScroll.setOpaque(false);
navScroll.getViewport().setOpaque(false);
buttonScroll.add(funConsultarPiezas = new JButton());
funConsultarPiezas.setContentAreaFilled(false);
// funConsultarPiezas.setOpaque(true);
funConsultarPiezas.setText("Consultar pieza");
funConsultarPiezas.setFont(new java.awt.Font("Arial", 1, ajustarDimensiones(30)));
funConsultarPiezas.setBounds(ajustarDimensiones(1), ajustarDimensiones(0), ajustarDimensiones(301), ajustarDimensiones(80));
// funConsultarPiezas.setBackground(java.awt.Color.white);
funConsultarPiezas.setForeground(Color.white);
funConsultarPiezas.addActionListener(this);
funConsultarPiezas.setBorder(null);
funConsultarPiezas.setBorderPainted(false);
funConsultarPiezas.setFocusPainted(false);
botones.add(funConsultarPiezas);
y += 81;
buttonScroll.add(btnCalidad = new JButton());
btnCalidad.setContentAreaFilled(false);
// btnCalidad.setOpaque(true);
btnCalidad.setText("Quality Check");
btnCalidad.setBounds(ajustarDimensiones(1), ajustarDimensiones(y), ajustarDimensiones(301), ajustarDimensiones(80));
btnCalidad.setFont(new java.awt.Font("Arial", 1, ajustarDimensiones(30)));
// btnCalidad.setBackground(Color.white);
btnCalidad.setForeground(Color.white);
btnCalidad.addActionListener(this);
btnCalidad.setBorder(null);
btnCalidad.setBorderPainted(false);
btnCalidad.setFocusPainted(false);
botones.add(btnCalidad);
y += 81;
buttonScroll.add(planDis = new JButton());
planDis.setContentAreaFilled(false);
// planDis.setOpaque(true);
planDis.setText("Diseño y planear");
planDis.setBounds(ajustarDimensiones(1), ajustarDimensiones(y), ajustarDimensiones(301), ajustarDimensiones(80));
planDis.setFont(new java.awt.Font("Arial", 1, ajustarDimensiones(30)));
// planDis.setBackground(Color.white);
planDis.setForeground(Color.white);
planDis.addActionListener(this);
planDis.setBorder(null);
planDis.setBorderPainted(false);
planDis.setFocusPainted(false);
botones.add(planDis);
y += 81;
buttonScroll.add(compraMat = new JButton());
compraMat.setContentAreaFilled(false);
// compraMat.setOpaque(true);
compraMat.setText("Compra Material");
compraMat.setBounds(ajustarDimensiones(1), ajustarDimensiones(y), ajustarDimensiones(301), ajustarDimensiones(80));
compraMat.setFont(new java.awt.Font("Arial", 1, ajustarDimensiones(30)));
//compraMat.setBackground(Color.white);
compraMat.setForeground(Color.white);
compraMat.addActionListener(this);
compraMat.setBorder(null);
compraMat.setBorderPainted(false);
compraMat.setFocusPainted(false);
botones.add(compraMat);
y += 81;
buttonScroll.add(soySuper = new JButton());
soySuper.setContentAreaFilled(false);
// soySuper.setOpaque(true);
soySuper.setText("Liberar piezas");
soySuper.setBounds(ajustarDimensiones(1), ajustarDimensiones(y), ajustarDimensiones(301), ajustarDimensiones(80));
soySuper.setFont(new java.awt.Font("Arial", 1, ajustarDimensiones(30)));
//soySuper.setBackground(Color.white);
soySuper.setForeground(Color.white);
soySuper.addActionListener(this);
soySuper.setBorder(null);
soySuper.setBorderPainted(false);
soySuper.setFocusPainted(false);
botones.add(soySuper);
y += 81;
buttonScroll.add(crearProyecto = new JButton());
crearProyecto.setContentAreaFilled(false);
// crearProyecto.setOpaque(true);
crearProyecto.setText("Crear proyecto");
crearProyecto.setBounds(ajustarDimensiones(1), ajustarDimensiones(y), ajustarDimensiones(301), ajustarDimensiones(80));
crearProyecto.setFont(new java.awt.Font("Arial", 1, ajustarDimensiones(30)));
//crearProyecto.setBackground(Color.white);
crearProyecto.setForeground(Color.white);
crearProyecto.addActionListener(this);
crearProyecto.setBorder(null);
crearProyecto.setBorderPainted(false);
crearProyecto.setFocusPainted(false);
botones.add(crearProyecto);
y += 81;
buttonScroll.add(clientes = new JButton());
clientes.setContentAreaFilled(false);
// clientes.setOpaque(true);
clientes.setText("Clientes");
clientes.setBounds(ajustarDimensiones(1), ajustarDimensiones(y), ajustarDimensiones(301), ajustarDimensiones(80));
clientes.setFont(new java.awt.Font("Arial", 1, ajustarDimensiones(30)));
//clientes.setBackground(Color.white);
clientes.setForeground(Color.white);
clientes.addActionListener(this);
clientes.setBorder(null);
clientes.setBorderPainted(false);
clientes.setFocusPainted(false);
botones.add(clientes);
y += 81;
buttonScroll.add(adminConsProye = new JButton());
adminConsProye.setContentAreaFilled(false);
// adminConsProye.setOpaque(true);
adminConsProye.setText("Consultar proyectos");
adminConsProye.setBounds(ajustarDimensiones(1), ajustarDimensiones(y), ajustarDimensiones(301), ajustarDimensiones(80));
adminConsProye.setFont(new java.awt.Font("Arial", 1, ajustarDimensiones(26)));
//adminConsProye.setBackground(Color.white);
adminConsProye.setForeground(Color.white);
adminConsProye.addActionListener(this);
adminConsProye.setBorder(null);
adminConsProye.setBorderPainted(false);
adminConsProye.setFocusPainted(false);
botones.add(adminConsProye);
y += 81;
buttonScroll.add(histProy = new JButton());
histProy.setText("Historial");
histProy.setContentAreaFilled(false);
// histProy.setOpaque(true);
histProy.setBounds(ajustarDimensiones(1), ajustarDimensiones(y), ajustarDimensiones(301), ajustarDimensiones(80));
histProy.setFont(new java.awt.Font("Arial", 1, ajustarDimensiones(30)));
//histProy.setBackground(Color.white);
histProy.setForeground(Color.white);
histProy.addActionListener(this);
histProy.setBorder(null);
histProy.setBorderPainted(false);
histProy.setFocusPainted(false);
botones.add(histProy);
y += 81;
buttonScroll.add(consuEmpleados = new JButton());
consuEmpleados.setText("Trabajadores");
consuEmpleados.setContentAreaFilled(false);
// consuEmpleados.setOpaque(true);
consuEmpleados.setBounds(ajustarDimensiones(1), ajustarDimensiones(y), ajustarDimensiones(301), ajustarDimensiones(80));
consuEmpleados.setFont(new java.awt.Font("Arial", 1, ajustarDimensiones(30)));
//consuEmpleados.setBackground(Color.white);
consuEmpleados.setForeground(Color.white);
consuEmpleados.addActionListener(this);
consuEmpleados.setBorder(null);
consuEmpleados.setBorderPainted(false);
consuEmpleados.setFocusPainted(false);
botones.add(consuEmpleados);
y += 81;
buttonScroll.setPreferredSize(new Dimension(ajustarDimensiones(305), ajustarDimensiones(y)));
}
public void botonSeleccionado(JButton but) {
for (JButton b : botones) {
if (b.getText().equalsIgnoreCase(but.getText())) {
b.setOpaque(true);
b.setBackground(new Color(255, 102, 102, 200));
b.setForeground(Color.white);
} else {
b.setOpaque(false);
//b.setBackground(Color.white);
b.setForeground(Color.white);
}
b.revalidate();
b.repaint();
}
}
@Override
public void actionPerformed(ActionEvent ae) {
JButton obj = (JButton) ae.getSource();
if (obj != logout) {
botonSeleccionado(obj);
}
}
}
在另一个例子中,我将透明度应用于整个导航面板,它是一个JLabel。在第一幅图像中,显示的是框架显示时出现的内容,甚至框架的某些部分显示在导航面板下方。在第二个示例中,显示了当我使用滚动条一次时发生的情况
编辑2:
我将所有用作JPanel的JLabel替换为实际的JPanel。不幸的是,这只虫子一直存在。我在主JPanel中添加了一个额外的按钮,之所以这样做是因为我认为错误源于向JScrollPane添加按钮。但问题似乎直接出在我如何实现方法buttonName.setBackground()上
以下是代码的新版本:
在99%的情况下,您在示例应用程序中看到的任何问题都是由于不透明和/或非不透明组件的不正确混合造成的 正如我从代码中看到的,您正在使用
setOpaque(…)
来更改各种组件的不透明度,但是它非常混乱。简而言之,opaque
属性的作用是什么?每当需要对特定UI元素(面板/标签/按钮等)进行可视化更新时,它会影响Swing重新绘制该元素的方式
例如,当你用鼠标悬停一个按钮时,如果它有一个不同的悬停状态,可能需要重新绘制,无论它是一个图标还是一个稍微/完全不同的样式。这就是不透明度发挥作用的地方-opaque=true
组件永远不会将重绘调用“在”自身下传递给它们的父组件(用其他/适当的术语)。这意味着,如果面板上有一个不透明按钮,当它变为“悬停”状态时,必须重新绘制该按钮-该按钮将是唯一重新绘制的组件,因为它是不透明的,因此没有理由重新绘制其下方的任何内容,您实际上应该无法看穿它,因此,图形应该用不透明的颜色填充按钮边界内的所有像素
理论上。在实践中,如果您将按钮设置为不透明状态,但使其图形内容保持透明或半透明(这显然是一个错误,但Swing永远不会告诉您这一点),您将看到各种视觉构件,就像您在应用程序中看到的一样。这是由于Graphics2D
实现经常在(0,0)坐标处执行不同的绘制操作以优化其速度而导致的-了解这一点并不重要,但这也是为什么在组件边界透明时可能会看到其他组件“部分”混合在组件边界中的部分原因。这比这要复杂一点,但这并不重要,因为它只是一个内部的Swing优化
在同一布局上混合opaque=true
和opaque=false
组件也可能导致类似的视觉问题。很可能你的问题也是如此。我确实很快尝试将演示中的所有内容设置为opaque=false
,它确实解决了问题,但这并不是解决问题的正确方法,尤其是如果您希望保持某些组件的不透明性。这就意味着问题在于在一个容器中混合不同不透明类型的组件
我个人的建议-如果不透明和非不透明组件有轻微重叠的可能(意味着它们的边界将在布局中相交),则不要在一个布局中混合使用不透明和非不透明组件。或者更好——在单个容器中,不要重叠组件。使用多个嵌套容器和适当的非空布局,这也将在将来帮助您轻松修改UI
我可以给你一个简单的例子来说明为什么它不好:
/**
*@作者米克尔·加林
*/
公共类不透明结石
{
公共静态void main(字符串[]args)
{
SwingUtilities.invokeLater(()->{
最终JFrame=新JFrame(“不透明度故障样本”);
//默认为不透明
最终JPanel面板=新JPanel(空);
//默认情况下为不透明,但可能随L&F的不同而不同
最终JButton button1=新JButton(“1111111”);
panel.add(按钮1);
//非不透明,以演示问题
最终JButton按钮2=新JButton(“2222222”);
panel.add(按钮2);
//交叉按钮
按钮1.立根(100、100、150、30);
按钮2.立根(130、115、150、30);
frame.getContentPane().add(面板);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
框架尺寸(500500);
frame.setLocationRelativeTo(空);
frame.setVisible(true);
} );
}
}
从理论上讲,您应该得到的是按钮1
始终位于顶部(因为它被较早地添加,并且在容器上最后一次绘制),但位于顶部
panelNav.setBackground(new Color(0, 0, 0, 200));
panelNav.setOpaque(true);
button2.setOpaque ( false );