我正在设置一个Spring Boot应用程序,希望主机能够访问系统托盘图标并访问一些bean信息。
我目前正在尝试为我的SystemTrayIcon创建一个带有@Autowired细节的Bean。然而,当我尝试添加SystemTrayIcon时,我得到了以下异常:
Caused by: java.awt.HeadlessException
at java.awt.TrayIcon.(Unknown Source)
at java.awt.TrayIcon.(Unknown Source)
at java.awt.TrayIcon.(Unknown Source)
at hermes.subsrciber.systemTray.HermesTrayIcon.(HermesTrayIcon.java:36)
at hermes.subscriber.boot.AppStarter.trayIcon(AppStarter.java:83)
at hermes.subscriber.boot.AppStarter$$EnhancerBySpringCGLIB$$c4f80849.CGLIB$trayIcon$3()
at hermes.subscriber.boot.AppStarter$$EnhancerBySpringCGLIB$$c4f80849$$FastClassBySpringCGLIB$$d62ab0bd.invoke()
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:312)
at hermes.subscriber.boot.AppStarter$$EnhancerBySpringCGLIB$$c4f80849.trayIcon()
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:166)
... 17 more有没有办法让SpringBoot应用程序可以访问系统托盘图标?
我相信我可以简单地在Main方法(连同SpringApplication.run)中定义它,但是我不能自动绑定我的属性。
这种设置可能吗?
发布于 2014-10-25 23:46:25
解决方案是,而不是使用SpringApplication.run(MyConfig.class,args),请使用以下设置:
SpringApplicationBuilder builder = new SpringApplicationBuilder(MyConfig.class);
builder.headless(false);
ConfigurableApplicationContext context = builder.run(args);为了实际添加系统图标,我添加了一个如下类型的bean:
public class MyTrayIcon extends TrayIcon {
private static final String IMAGE_PATH = "/path/icon_16x16.png";
private static final String TOOLTIP = "Text";
private PopupMenu popup;
private SystemTray tray;
public MyTrayIcon(){
super(createImage(IMAGE_PATH,TOOLTIP),TOOLTIP);
popup = new PopupMenu();
tray = SystemTray.getSystemTray();
}
@PostConstruct
private void setup() throws AWTException{
// popup.add(itemAbout);
// here add the items to your popup menu. These extend MenuItem
// popup.addSeparator();
setPopupMenu(popup);
tray.add(this);
}
protected static Image createImage(String path, String description){
URL imageURL = MyTrayIcon.class.getResource(path);
if(imageURL == null){
System.err.println("Failed Creating Image. Resource not found: "+path);
return null;
}else {
return new ImageIcon(imageURL,description).getImage();
}
}
}发布于 2017-06-09 15:52:02
如果有人想要完整的代码..。
import java.awt.AWTException;
import java.awt.CheckboxMenuItem;
import java.awt.Image;
import java.awt.Menu;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
import javax.annotation.PostConstruct;
import javax.swing.ImageIcon;
import org.springframework.boot.ExitCodeGenerator;
import org.springframework.boot.SpringApplication;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
public class MyTrayIcon extends TrayIcon {
private static final String IMAGE_PATH = "/PATH.png";
private static final String TOOLTIP = "Running";
private PopupMenu popup;
final SystemTray tray;
public MyTrayIcon(){
super(createImage(IMAGE_PATH,TOOLTIP),TOOLTIP);
popup = new PopupMenu();
tray = SystemTray.getSystemTray();
try {
setup();
} catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@PostConstruct
private void setup() throws AWTException{
// Create a pop-up menu components
MenuItem exitItem = new MenuItem("Exit");
popup.add(exitItem);
exitItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
final int exitCode = 0;
ExitCodeGenerator exitCodeGenerator = new ExitCodeGenerator() {
@Override
public int getExitCode() {
return exitCode;
}
};
tray.remove(MyTrayIcon.this);
SpringApplication.exit(Application.context, exitCodeGenerator);
}
});
// popup.addSeparator();
setPopupMenu(popup);
tray.add(this);
}
protected static Image createImage(String path, String description){
URL imageURL = MyTrayIcon.class.getResource(path);
if(imageURL == null){
System.err.println("Failed Creating Image. Resource not found: "+path);
return null;
}else {
return new ImageIcon(imageURL,description).getImage();
}
}
}在你的Application.java中:
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableConfigurationProperties(StorageProperties.class)
public class Application {
public static ConfigurableApplicationContext context;
public static void main(String[] args) {
//SpringApplication.run(Application.class, args);
SpringApplicationBuilder builder = new SpringApplicationBuilder(Application.class);
builder.headless(false);
context = builder.run(args);
MyTrayIcon m = new MyTrayIcon();
}
}发布于 2021-02-22 08:49:59
使用中的代码逻辑
/**
* @author lotuso
* @version 1.0 2021/2/21 14:55
**/
@Slf4j
public class TrayIcon extends Application {
private final AtomicInteger runCount = new AtomicInteger(0);
private final RegistryTrayConfiguration configuration = new RegistryTrayConfiguration();
@Override
public void start(final Stage stage) throws Exception {
//构建系统托盘图标
if(configuration.isEnabled()) {
var stream = TrayIcon.class.getClassLoader().getResource(configuration.getIcon());
assert stream != null;
var image = ImageIO.read(stream);
var trayIcon = new java.awt.TrayIcon(image, configuration.getTip());
trayIcon.setImageAutoSize(true);
//添加托盘事件
{
trayIcon.addMouseListener(new MouseAdapter() {
//鼠标点击事件
@Override
public void mouseClicked(final MouseEvent event) {
//双击左键
if(event.getButton() == MouseEvent.BUTTON1 && event.getClickCount() == 2) {
log.info("托盘双击事件");
Platform.runLater(() -> {
//TODO 如果需要显示一个窗口,哪么在这里进行,暂不实现
});
}
else if(event.getButton() == MouseEvent.BUTTON3) {
log.info("托盘右击事件");
//TODO 可以做些其它的事
}
}
});
}
//获取系统托盘
var trayPanel = SystemTray.getSystemTray();
trayPanel.add(trayIcon);
}
}
public synchronized void run(String... args) {
if(runCount.get() <= 0){
runCount.set(runCount.get()+1);
launch(args);
}
}
public static class RegistryTrayConfiguration {
public boolean isEnabled() {
return !Objects.isNull(getIcon());
}
public String getIcon() {
var icon = getYML("spring.application.tray.icon");
return String.valueOf(icon);
}
public String getTip() {
var tip = getYML("spring.application.tray.tip");
return String.valueOf(tip);
}
public static Object getYML(Object key) {
return getYML(key, "application.yml");
}
public static Object getYML(Object key, String yml) {
var resource = new ClassPathResource(yml);
Properties properties;
try {
var factory = new YamlPropertiesFactoryBean();
factory.setResources(resource);
properties = factory.getObject();
}
catch(Exception ex) {
log.warn(ex.getLocalizedMessage());
return null;
}
assert properties != null;
return properties.get(key);
}
}
}使用@Configuration标记在类中定义以下代码:
@Bean
public Application trayIcon() {
var trayIcon = new TrayIcon();
//TODO 此处将托盘与SpringBoot线程分开
new Thread(trayIcon::run).start();
return trayIcon;
}添加如下结构的资源文件。将图像目录添加到项目的资源目录并放置图标。PNG文件在那里
|_ src
|_ main
|_ java
|_ resources
|_ images
|_ icon.png
|_ application.ymlApplication.yml需要以下设置
spring:
application:
tray:
tip: Used to indicate the prompt when the mouse is moved over the icon
icon: Directory path relative to resources, such as images/icon.png通过这种方式,TrayIcon被移交给Spring的容器来管理。如果这对你有帮助,请让我知道如果你有更好的建议
https://stackoverflow.com/questions/26564077
复制相似问题