在 JButton 中添加装饰
Add decorations in JButton
我目前在 JavaSwing
进行 GUI 开发。
我正在尝试使用 JButton
创建一个类似于 HTML
代码的 button
,它已添加到 getContentPane()
,但我不知道该怎么做并且我不知所措。
当前代码:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setTitle("TITLE");
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1000, 800);
frame.getContentPane().setLayout(new FlowLayout());
JButton button = new JButton("Click Here");
frame.getContentPane().add(button);
button.setBackground(Color.RED);
button.setForeground(Color.WHITE);
button.setOpaque(true);
button.setPreferredSize(new Dimension(150, 50));
}
}
我试图创建的实体有点难以口头解释,所以我尝试使用 HTML 重现我试图创建的内容。如下:
HTML 代码:
<div class="btn">Click Here</div>
<style>
.btn {
background-color: red;
display: inline-block;
height: 70px;
width: 150px;
text-align: center;
color: white;
padding-top: 35px;
font-size: 25px;
border-radius: 50px;
box-shadow: 0px 5px #b70d0b;
opacity: 0.7;
cursor: pointer;
}
.btn:hover {
opacity: 1;
}
.btn:active{
position: relative;
top: 5px;
box-shadow: none;
}
</style>
这是执行时的样子:下图是我在JavaSwing
中的理想。
这次的问题是:
在 JavaSwing
中将 opacity
设置为 JButton
将border-radius
设置为button
仅当鼠标hovers
在button
和MouseEvent
上检测到时才将opacity
设置为1。
设置box-shadow
为5px
,用ActionListener
检测active的间隔,让它看起来像一个button
按下。
当鼠标悬停在 button
上时重现 cursor:pointer
代码。
我不确定这样问是不是太多了。我很清楚问题太多了,所以如果你能只回答我能回答的问题,我将不胜感激。
同时,我自己Google研究了这个问题,但none符合我的理想,所以我在这里问。
至于我做了什么,我是这样做的:
我看了here,但是当我输入小数点时,比如setOpacity(0.5)
,我得到一个错误setOpacity(double) is undefined
。
我提到了边界半径 here,但是当我 运行 它时没有任何反应。可能是我的文风或版本有问题。我觉得是我写的方式有问题,或者版本有问题,但是没找到原因。
我尝试复制 MouseEvent
用于悬停 here,但版本可能不同,或者出现错误。
那么,我应该编写什么代码来实现我的要求?
如果你能帮助我,我将不胜感激。
谢谢。
没有“简单”的方法可以做到这一点,您要么必须创建自己的自定义按钮(从 JButton
扩展),要么必须创建自己的 UI 委托 class(这可能是首选方向,但它很复杂)
Why not use a Border
因为 Border
无法填充...如果填充,它将覆盖按钮的文本
您应该先查看 Painting in AWT and Swing, Performing Custom Painting and 2D Graphics 以更好地了解解决方案的工作原理。
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
FancyButton btn = new FancyButton();
btn.setText("Click me");
add(btn);
}
}
public class FancyButton extends JButton {
private int cornerRadius = 32;
private BufferedImage backgroundImage;
private float alpha = 0.25f;
public FancyButton() {
setBackground(Color.RED);
setForeground(Color.WHITE);
// This is important
setBorderPainted(false);
// This is important
setContentAreaFilled(false);
// This is important
int padding = cornerRadius / 2;
setBorder(new EmptyBorder(padding, padding, padding, padding));
addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
alpha = 1;
repaint();
}
@Override
public void mouseExited(MouseEvent e) {
alpha = 0.25f;
repaint();
}
});
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
backgroundImage = null;
}
});
}
@Override
public boolean isOpaque() {
return false;
}
@Override
public Insets getInsets() {
Insets insets = super.getInsets();
insets.bottom += 5;
return insets;
}
@Override
public Insets getInsets(Insets insets) {
super.getInsets(insets);
insets.bottom += 5;
return insets;
}
@Override
protected void paintComponent(Graphics g) {
if (backgroundImage == null) {
backgroundImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = backgroundImage.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(getBackground().darker());
g2d.fillRoundRect(0, 5, getWidth(), getHeight() - 5, cornerRadius, cornerRadius);
g2d.setColor(getBackground());
g2d.fillRoundRect(0, 0, getWidth(), getHeight() - 5, cornerRadius, cornerRadius);
g2d.dispose();
}
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.SrcOver.derive(alpha));
g2d.drawImage(backgroundImage, 0, 0, this);
super.paintComponent(g2d);
g2d.dispose();
}
}
}
我目前在 JavaSwing
进行 GUI 开发。
我正在尝试使用 JButton
创建一个类似于 HTML
代码的 button
,它已添加到 getContentPane()
,但我不知道该怎么做并且我不知所措。
当前代码:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setTitle("TITLE");
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1000, 800);
frame.getContentPane().setLayout(new FlowLayout());
JButton button = new JButton("Click Here");
frame.getContentPane().add(button);
button.setBackground(Color.RED);
button.setForeground(Color.WHITE);
button.setOpaque(true);
button.setPreferredSize(new Dimension(150, 50));
}
}
我试图创建的实体有点难以口头解释,所以我尝试使用 HTML 重现我试图创建的内容。如下:
HTML 代码:
<div class="btn">Click Here</div>
<style>
.btn {
background-color: red;
display: inline-block;
height: 70px;
width: 150px;
text-align: center;
color: white;
padding-top: 35px;
font-size: 25px;
border-radius: 50px;
box-shadow: 0px 5px #b70d0b;
opacity: 0.7;
cursor: pointer;
}
.btn:hover {
opacity: 1;
}
.btn:active{
position: relative;
top: 5px;
box-shadow: none;
}
</style>
这是执行时的样子:下图是我在JavaSwing
中的理想。
这次的问题是:
在
中将JavaSwing
opacity
设置为JButton
将
border-radius
设置为button
仅当鼠标
hovers
在button
和MouseEvent
上检测到时才将opacity
设置为1。设置
box-shadow
为5px
,用ActionListener
检测active的间隔,让它看起来像一个button
按下。当鼠标悬停在
button
上时重现cursor:pointer
代码。
我不确定这样问是不是太多了。我很清楚问题太多了,所以如果你能只回答我能回答的问题,我将不胜感激。
同时,我自己Google研究了这个问题,但none符合我的理想,所以我在这里问。
至于我做了什么,我是这样做的:
我看了here,但是当我输入小数点时,比如setOpacity(0.5)
,我得到一个错误setOpacity(double) is undefined
。
我提到了边界半径 here,但是当我 运行 它时没有任何反应。可能是我的文风或版本有问题。我觉得是我写的方式有问题,或者版本有问题,但是没找到原因。
我尝试复制 MouseEvent
用于悬停 here,但版本可能不同,或者出现错误。
那么,我应该编写什么代码来实现我的要求? 如果你能帮助我,我将不胜感激。
谢谢。
没有“简单”的方法可以做到这一点,您要么必须创建自己的自定义按钮(从 JButton
扩展),要么必须创建自己的 UI 委托 class(这可能是首选方向,但它很复杂)
Why not use a
Border
因为 Border
无法填充...如果填充,它将覆盖按钮的文本
您应该先查看 Painting in AWT and Swing, Performing Custom Painting and 2D Graphics 以更好地了解解决方案的工作原理。
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
FancyButton btn = new FancyButton();
btn.setText("Click me");
add(btn);
}
}
public class FancyButton extends JButton {
private int cornerRadius = 32;
private BufferedImage backgroundImage;
private float alpha = 0.25f;
public FancyButton() {
setBackground(Color.RED);
setForeground(Color.WHITE);
// This is important
setBorderPainted(false);
// This is important
setContentAreaFilled(false);
// This is important
int padding = cornerRadius / 2;
setBorder(new EmptyBorder(padding, padding, padding, padding));
addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
alpha = 1;
repaint();
}
@Override
public void mouseExited(MouseEvent e) {
alpha = 0.25f;
repaint();
}
});
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
backgroundImage = null;
}
});
}
@Override
public boolean isOpaque() {
return false;
}
@Override
public Insets getInsets() {
Insets insets = super.getInsets();
insets.bottom += 5;
return insets;
}
@Override
public Insets getInsets(Insets insets) {
super.getInsets(insets);
insets.bottom += 5;
return insets;
}
@Override
protected void paintComponent(Graphics g) {
if (backgroundImage == null) {
backgroundImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = backgroundImage.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(getBackground().darker());
g2d.fillRoundRect(0, 5, getWidth(), getHeight() - 5, cornerRadius, cornerRadius);
g2d.setColor(getBackground());
g2d.fillRoundRect(0, 0, getWidth(), getHeight() - 5, cornerRadius, cornerRadius);
g2d.dispose();
}
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.SrcOver.derive(alpha));
g2d.drawImage(backgroundImage, 0, 0, this);
super.paintComponent(g2d);
g2d.dispose();
}
}
}