System Tray

3,005
192
595
Кто умеет юзать System Tray в java?
Можете плез помочь создать кастомный System Tray, где можно отправлять уведомления и он выключался при выключении майна?
 
https://stackoverflow.com/questions/13989265/task-tray-notification-balloon-events
Для выключения сделай callback где-нибудь
 
Я сделал так:
При определенных условиях - оно уведомление показывается, через 4 секунды убирается, но если выполнить условие при включенным уведомление - крашит условие из-за того, что уведомление уже включено.
 
Код:
	final TrayIcon trayIcon = new TrayIcon(Toolkit.getDefaultToolkit().createImage("icon.png"));
	final SystemTray tray = SystemTray.getSystemTray();

    @SubscribeEvent
    public void chatMSG(ClientChatReceivedEvent e) {
    	String msg = e.getMessage().getUnformattedText();
    	if (!msg.contains("<FTB_lag>") && (msg.contains("FTB_lag") || msg.contains("whispers to you"))) {
    		createAndASD(msg);
    	}
    }
	
	java.util.Timer timer;
    
    class SayHello extends TimerTask {
        public void run() {
        	try {
				Thread.sleep(4000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
        	tray.remove(trayIcon);
        	timer.cancel();
        }
    }
    
    private void createAndASD(String msg) {
    	if (!SystemTray.isSupported()) {
            System.out.println("SystemTray is not supported");
            return;
        }
        try {
            tray.add(trayIcon);
        } catch (AWTException e) {
            System.out.println("TrayIcon could not be added.");
            return;
        }
        
        trayIcon.displayMessage("Minecraft", msg, TrayIcon.MessageType.INFO);
		timer = new java.util.Timer();
		timer.schedule(new SayHello(), 0, 4000);
        //tray.remove(trayIcon);
    }
 
Тебе после каждого сообщения нужно убирать иконку? Или лишь по закрытии игры?
 
Мне лично все равно как.
Но на счет убрать когда майн будет закрыт - это я хз как сделать, ибо это эвентами не уловить (на сколько я знаю).
 
Где-нибудь в инициализации устанавливаешь иконку, в эвенте по ссылке на TrayIcon вызываешь метод для уведомления. Когда же майн закроется, иконка автоматически исчезнет(пруф из джавадоков): "All icons added by the application are automatically removed from the SystemTray upon application exit and also when the desktop system tray becomes unavailable.". Но на опыте знаю, что она будет там висеть до тех пор, пока на неё не наведёшь мышь; только тогда она исчезнет.
 
Вроде бы получилось.
Остался вопрос: как сделать так, что если более 2х раз вызова сообщения - соединить в одно?
Т.Е. Если 2 раза вызывать создание сообщения - сначала откроется 1, после 1-ое закроется, откроется 2-ое.
 
Я не знаю. Могу лишь такое предложить: поменять иконку на ту же, но с маленькой цифрой(1-9, а если больше, то 9+). Это можно сделать, если нарисовать готовые 10 иконок заранее(, или в рантайме с помощью графики, если извращенец). Так вот, когда игрок будет кликать на это чудо, то иконку ставим в нуль, словно все сообщения стали прочитанными; показываем PopupMenu с сообщениями. Добавить их туда просто: хранишь ссылку на это меню, вызываешь add(String). А displayMessage может показывать что-то вроде "New Message!". Костыль? Нет, иной путь решения. В итоге едем в CПб из Москвы не через Владивосток, а всего лишь через Йошкар-Олу.
 
Можешь написать это кодом?))
Просто сложно писать там, где мало чего понятно.
 
Я и кодить не умею, по сути. Заведи список сообщений(history). Сделай иконку всё там же, в клиентском эвенте(прокси, наверно, да? Главное, чтобы 1 раз). Затем нарисуй 11 иконок. 1 - нет сообщений, 9 других для циферок 1-9, 10 - "9+" или "...". По дефолту ставь 0-вую. Итак, ты получил сообщение, добавь его в коллекцию, измени иконку в зависимости от кол-ва сообщений, добавь в PopupMenu(https://docs.oracle.com/javase/tutorial/uiswing/misc/systemtray.html) label с помощью метода add, где lable - неотформатированное сообщение. Всё. Игрок кликает, срабатывает твой листенер(эвент же), и можешь там удалить "историю" и поменять иконку на нулевую. Понятно?(
 
Как сделать историю, обнуление и добавление?
 
Я ещё подумал. Давай попробуем так:
1. Делаешь список, инициализируешь иконки, всё как надо. Иконку делаешь с PopupMenu, где будет кнопка "очистить"
2. Пришло сообщение, добавляешь в PopupMenu. Можно сделать ограничения, чтоб при, допустим, 5 сообщениях старые удалялись, заменяясь новыми.
3. Допустим, игрок открыл, нажал на "очистить". Ты удаляешь все элементы этого PopupMenu кроме кнопки(сделай её первой, индекс нулевой, её потом не трогать)
4. Всё?
Вот это дюже на костыль похоже. Так что пошли меня уже и сделай по-нормальному, меня далеко унесло
********
Где-то в инициализации(ще Котлин, аларм):


Код:
val icon = TrayIcon(...)
val popup = PopupMenu()

fun init(){
...
val butt = MenuItem("Delete")
butt.addActionListener {
    for (i in 1 until popup.itemCount) popup.remove(i) //обычный цикл от 1 до popup.itemCount
}
popup.add(butt)
icon.popupMenu = popup
require(SystemTray.isSupported()) // Просто пихни условие, если поддерживается, то строки ниже
val tray = SystemTray.getSystemTray()
tray.add(icon)
}

Когда получил сообщение:
fun receive() {
...
popup.add(event.message) //Строку как-нибудь впихнёшь
icon.image = новую картинку, если хочешь, а можно...
icon.displayMessage(...)
}

Весь мой костыль
 
У меня почему-то цикл плохо работает.
for (int i = 2; i < popup.getItemCount(); i++)
popup.remove(i);
(2, т.к. У меня кнопка очищения и кнопка теста).
+ как туда прикрутить иконки так, что бы это работало в майне? Ибо икнока берется из папки eclipse.
 
Не знаю, почему цикл плохо работает. Я проверил - кнопки пропадают.(после закрытия popup, конечно же). Как добавить иконку из майна - не знаю, с год(а то и более) не кодил. Попробуй найти где-нибудь InputStream, всунь в ImageIO.read
 
Вышло в итоге:
Когда обнуляю - просто удаляю все, после добавляю кнопку.
На счет картинок - сделал через File.
Спасибо за помощь).
 
Назад
Сверху