提问人:Georodin 提问时间:5/4/2021 更新时间:5/5/2021 访问量:32
如何将 Eventhandler 调用统一到两个堆叠的 JComponents 上
How to unify a Eventhandler call onto two stacked JComponents
问:
问题:我有一个带有 Icon 和 RolloverIcon(Hover effect) 的 JButon,为此我添加了一个 via add() 一个 JFXPanel,其中包含写入该 JButton 的字符串。如何正确地将展期转发到 JFXPanel?因为目前我在 JFXPanel 中调用 setOnMouseEntered 来更改 JButton 的背景,但从 Rollover JButton 事件到内部 JFXPanel setOnMouseEntered 的过渡并不是无缝的。
更精确的解释:当我将鼠标从包装器 JButton 悬停到内部 JFXPanel 上时,JButton 的翻转会尝试将按钮上的图标恢复为非翻转版本。但与此同时,新调用的 setOnMouseEntered 尝试将 JButton Icon 设置为 Rollover 版本。导致视觉 Race条件或只是口吃。
我将资源和 src 文件打包到这个 Zip 文件中
我心目中的决议:
- 有没有办法让 JFXPanel 完全点击,所以我只需要父按钮的翻转
- 也许在 JButton 类中将 JFXPanel 渲染成图标或图像,这样我就可以纯粹依赖翻转效果
主类:
package main.testbench;
import java.awt.Color;
import java.awt.Dimension;
import java.net.URL;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
public class MainStarter implements UrlGetter{
static final double MULTI = 2.0;
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension((int) (400*MULTI),(int) (400*MULTI)));
frame.setMinimumSize(new Dimension((int) (400*MULTI),(int) (400*MULTI)));
frame.setVisible(true);
JPanel pnl = new JPanel();
pnl.setBackground(new Color(0, 255, 0));
pnl.add(new ButtonIconHover("Reisen", "test", new Dimension((int) (110*MULTI),(int) (40*MULTI))));
frame.add(pnl);
}
});
}
}
JButton级:
public class ButtonIconHover extends JButton implements UrlGetter {
public ButtonIconHover(String display, String action, Dimension dimension) {
super();
super.setOpaque(false);
super.setContentAreaFilled(false);
super.setBorderPainted(false);
super.setPreferredSize(dimension);
super.setMinimumSize(dimension);
ImageIcon imageIcon = new ImageIcon(getURL("resources/Button.jpg"));
ImageIcon imageIconHover = new ImageIcon(getURL("resources/Button_h.jpg"));
Image image = imageIcon.getImage();
Image newimg = image.getScaledInstance(dimension.width, dimension.height, java.awt.Image.SCALE_SMOOTH);
imageIcon = new ImageIcon(newimg);
Image imageHover = imageIconHover.getImage();
Image newimgHover = imageHover.getScaledInstance(dimension.width, dimension.height, java.awt.Image.SCALE_SMOOTH);
imageIconHover = new ImageIcon(newimgHover);
super.setIcon(imageIcon);
super.setRolloverIcon(imageIconHover);
super.setPressedIcon(imageIconHover);
super.setActionCommand(action);
add(new FXButtonFont(display, dimension, this));
}
}
JFXPanel类:
package main.testbench;
import java.awt.Dimension;
import javax.swing.Icon;
import javafx.embed.swing.JFXPanel;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.Light;
import javafx.scene.effect.Lighting;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
public class FXButtonFont extends JFXPanel implements UrlGetter{
public FXButtonFont(String display, Dimension dimension, ButtonIconHover buttonIconHover) {
super();
Light.Distant light = new Light.Distant();
light.setAzimuth(-45.0);
Lighting lighting = new Lighting();
lighting.setLight(light);
lighting.setSurfaceScale(1.5*MainStarter.MULTI);
lighting.setSpecularConstant(2.0);
lighting.setSpecularExponent(10.0);
Text text = new Text(0 ,0, display);
// text.setText(display);
text.setFill(Color.WHITE);
Font font = Font.loadFont(getURL("resources/fonts/Arson-Regular.ttf").toString(), 20*MainStarter.MULTI);
text.setFont(font);
DropShadow shadow = new DropShadow();
shadow.setSpread(0);
shadow.setColor(Color.web("0x000000", 0.7));
shadow.setOffsetX(-2);
shadow.setOffsetY(2);
shadow.setWidth(4);
shadow.setRadius(4);
shadow.setInput(lighting);
text.setEffect(shadow);
Icon imageIcon = buttonIconHover.getIcon();
Icon imageIconHover = buttonIconHover.getRolloverIcon();
text.setOnMouseEntered((event) -> {
buttonIconHover.setIcon(imageIconHover);
});
text.setOnMouseExited((event) -> {
buttonIconHover.setIcon(imageIcon);
});
//Setting the stage
StackPane root = new StackPane();
StackPane.setAlignment(text, Pos.CENTER);
StackPane.setMargin(text, new Insets(0, 0, 0, 0));
root.getChildren().add(text);
Scene scene = new Scene(root, dimension.getWidth(),dimension.getHeight(), Color.TRANSPARENT);
setPreferredSize(dimension);
setMinimumSize(dimension);
this.setScene(scene);
}
}
UrlGetter 接口:
package main.testbench;
import java.net.URL;
public interface UrlGetter {
public default URL getURL(String resource) {
return getClass().getClassLoader().getResource(resource);
}
}
答:
0赞
Georodin
5/5/2021
#1
为了将 Swing JButton 上的图标与 JavaFX 文本无缝结合,我做了以下操作:
- 将 Icon 和 RolloverIcon 加载到上,以便图像已加载
JButton
- 因为 AWT 是异步的,需要加载才能更改
Image
- 在 (extends JButton) 构造函数中创建一个 (extends FXJPanel) 对象
FXButtonFont
ButtonIconHover
- 所有后续调用都是在嵌套中进行的,因为我们需要 JavaFX 线程
Platform.runLater
- 调用 JFXPanel 和现场
getScene
snapshot(WritableImage)
- 用于将 转换为
SwingFXUtils.fromFXImage(WritableImage, null)
WritableImage
BufferedImage
- 然后调用自写的 wich 将两者合二为一
mergeImages
BufferedImages
- 现在将返回的设置为
BufferedImage
setIcon
JButton
这里修改了 ButtonIconHover:
public ButtonIconHover(String display, String action, Dimension dimension) {
super();
super.setOpaque(false);
super.setContentAreaFilled(false);
super.setBorderPainted(false);
super.setPreferredSize(dimension);
super.setMinimumSize(dimension);
ImageIcon imageIcon = new ImageIcon(getURL("resources/Button.jpg"));
ImageIcon imageIconHover = new ImageIcon(getURL("resources/Button_h.jpg"));
Image image = imageIcon.getImage();
Image newimg = image.getScaledInstance(dimension.width, dimension.height, java.awt.Image.SCALE_SMOOTH);
Image imageHover = imageIconHover.getImage();
Image newimgHover = imageHover.getScaledInstance(dimension.width, dimension.height, java.awt.Image.SCALE_SMOOTH);
super.setIcon(new ImageIcon(newimg));
super.setRolloverIcon(new ImageIcon(newimgHover));
FXButtonFont FXBtnString = new FXButtonFont(display, dimension, false);
FXButtonFont FXBtnStringHover = new FXButtonFont(display, dimension, true);
ButtonIconHover thisbtn = this;
Platform.runLater(new Runnable() {
@Override
public void run() {
WritableImage img = new WritableImage((int)dimension.getWidth(), (int)dimension.getHeight()) ;
WritableImage imgHover = new WritableImage((int)dimension.getWidth(), (int)dimension.getHeight()) ;
FXBtnString.getScene().snapshot(img);
FXBtnStringHover.getScene().snapshot(imgHover);
BufferedImage FXBtnStringConverted = SwingFXUtils.fromFXImage(img, null);
BufferedImage FXBtnStringConvertedHover = SwingFXUtils.fromFXImage(imgHover, null);
BufferedImage combined = ImageUtil.mergeImages(ImageUtil.convertToBufferedImage(newimg), FXBtnStringConverted);
BufferedImage combinedRollPress = ImageUtil.mergeImages(ImageUtil.convertToBufferedImage(newimgHover), FXBtnStringConvertedHover);
ImageIcon nonConverted = new ImageIcon(combined);
ImageIcon rollPress = new ImageIcon(combinedRollPress);
thisbtn.setIcon(nonConverted);
thisbtn.setRolloverIcon(rollPress);
thisbtn.setPressedIcon(rollPress);
}
});
}
评论