2017-01-24 1 views
0

Итак, я написал приложение Java, которое обеспечивает прозрачный дисплей Heads up в верхней части экрана, он отлично работает на окнах, но на моем компьютере kubuntu 16.04 он не очищает старую метку при изменении текста меток, вы получаете тонну перекрытия беспорядка.java jlabel, работающий в Windows, но не в Linux, показывающий старые, форматы на экране, openjdk?

, потому что картинка стоит тысячи слов, верх, как она выглядит в окнах, в нижней части, как это выглядит под Kubuntu:

https://s23.postimg.org/yra0vvlvf/rawr.png

вот код:

import java.util.*; 
import java.awt.*; 
import java.awt.event.*; 
import java.net.*; 
import java.net.URL; 
import javax.swing.*; 
import java.io.*; 

public class spob extends JFrame implements WindowFocusListener 
{ 
    public spob() 
    { 
     if (!SystemTray.isSupported()) { 
      System.out.println("SystemTray is not supported"); 
      return; 
     } 
     final TrayIcon trayIcon = new TrayIcon((new ImageIcon("icon.png", "trayicon")).getImage()); 
     final SystemTray tray = SystemTray.getSystemTray(); 
     trayIcon.setImageAutoSize(true); 
     trayIcon.setToolTip("spO2 pr monitor");   
     try { 
      tray.add(trayIcon); 
     } catch (AWTException e) { 
      System.out.println("TrayIcon could not be added."); 
      return; 
     } 
     setType(javax.swing.JFrame.Type.UTILITY); 
     setUndecorated(true); 
     getContentPane().setBackground(new Color(1.0f,1.0f,1.0f,0.0f)); 
     setBackground(new Color(1.0f,1.0f,1.0f,0.0f)); 
     setSize(400, 35); 
     JLabel label = new JLabel("Loading..."); 
     label.setFont(new Font("Tahoma", Font.BOLD, 28)); 
     label.setForeground(Color.GREEN); 
     add(label); 
     setLocation(800, 0); 
     addWindowFocusListener(this); 
     setAlwaysOnTop(true); 
     this.setFocusable(true); 
     setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     setVisible(true); 
     URL url = null; 
     BufferedReader in = null; 
     String[] anArray = new String[10]; 
     anArray[0] = "<html><font color=green>- spO2:91 pr:65</font></html>"; 
     anArray[1] = "<html><font color=red>+ spO2:85 pr:77</font></html>"; 
     anArray[2] = "<html><font color=green>- spO2:90 pr:68</font></html>"; 
     anArray[3] = "<html><font color=orange>+ spO2:89 pr:76</font></html>"; 
     anArray[4] = "<html><font color=orange>- spO2:89 pr:72</font></html>"; 
     anArray[5] = "<html><font color=orange>+ spO2:88 pr:73</font></html>"; 
     anArray[6] = "<html><font color=red>- spO2:87 pr:78</font></html>"; 
     anArray[7] = "<html><font color=red>+ spO2:86 pr:73</font></html>"; 
     anArray[8] = "<html><font color=green>- spO2:92 pr:74</font></html>"; 
     anArray[9] = "<html><font color=green>+ spO2:90 pr:71</font></html>"; 
     while (true){ 
      try { 
       Thread.sleep(200); 
       //url = new URL("http://192.168.1.153/stat.php"); 
       //in = new BufferedReader(new InputStreamReader(url.openStream())); 
       //label.setText(in.readLine().toString()); 
       Random randomno = new Random(); 
       label.setText(anArray[randomno.nextInt(9 - 1) + 1]); 
      } catch (Exception ex) { 
      } finally { 
       //try { 
       // in.close(); 
       //} catch (IOException e) { 
       //} 
      } 
     } 
    } 

    public void windowGainedFocus(WindowEvent e){} 
    public void windowLostFocus(WindowEvent e) 
    { 
     if(e.getNewState()!=e.WINDOW_CLOSED){ 
      setAlwaysOnTop(false); 
      setAlwaysOnTop(true); 
     } 

    } 

    public static void main(String[] args) 
    { 
    new spob(); 
    } 
} 
+0

getContentPane(). setBackground (новый цвет (1.0f, 1.0f, 1.0f, 0.0f)) является вашей проблемой, Swing не знает, как бороться с непрозрачным компонентом с цветом на основе алоха (JFrame - это особый случай). В вашем случае просто создайте новый экземпляр JPanel, установите его непрозрачное состояние в false и примените его как панель содержимого к кадру (и при необходимости обновите диспетчер компоновки) – MadProgrammer

+0

Swing также не является потокобезопасным, ваш цикл while собирается блокировать ETD или нарушать правила singe thread, если Swing, в любом случае, вы должны использовать Swing Timer – MadProgrammer

+0

, вы имеете в виду вместо обновления метки label.setText, вместо этого я бы обновлял весь jpanel? (to заставьте его работать на kubuntu) ... интересный, большая часть кода была составлена ​​с использованием примеров и документации, доступных в Интернете. что происходит, когда ETD заблокирован? до сих пор он надежно работал последние пару недель на окнах, я буду смотреть на качели таймеров. – xekon

ответ

1

Таким образом, целый ряд вопросов

  • Вы нарушив однопоточные правила уплотнительные f Swing, по сути, обновляет пользовательский интерфейс вне контекста EDT, это может вызвать проблемы, если система пытается что-то нарисовать, пока вы пытаетесь ее обновить.
  • getContentPane().setBackground(new Color(1.0f,1.0f,1.0f,0.0f)); - Swing не знает, как справиться с непрозрачные компоненты, которые имеют цвет на основе альфа, он, как правило, не обновляет ни один из компонентов под ним.

Прозрачные окна - это ... забава ... они, как правило, представляют свои проблемы помимо того, чего мы обычно ожидаем.

В моей системе Mac я смог воспроизвести проблему, но непоследовательно. Это было особенно очевидно, потому что Mac OS продолжает визуализировать тень вокруг текста.

Первое, что я получил от setType(javax.swing.JFrame.Type.UTILITY);, я также добавил repaint запрос родительского контейнера ярлыка, который, кажется, решил симптомы проблемы, но я снова смог выполнить код.

Если вы хотите периодически обновлять пользовательский интерфейс, вы должны использовать Swing Timer, см. How to use Swing Timers для получения более подробной информации. Если вам нужно сделать что-то в фоновом режиме, а затем обновить пользовательский интерфейс, вы должны использовать SwingWorker, посмотрите Worker Threads and SwingWorker для получения более подробной информации

Translucent example

(ничего себе меня, он не любит мой анимированный GIF :()

пример намеренно использует полупрозрачный фон, он предназначен, чтобы показать рамку. Изменение pane.setAlpha(0.5f); к pane.setAlpha(0.0f);, чтобы сделать его полностью прозрачным (я проверил, что хорошо).

Если у вас есть вопросы, раскомментируйте строку label.getParent().repaint(); в Timer и посмотреть, если это помогает

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    private JLabel label; 
    private String[] anArray = { 
     "<html><font color=green>- spO2:91 pr:65</font></html>", 
     "<html><font color=red>+ spO2:85 pr:77</font></html>", 
     "<html><font color=green>- spO2:90 pr:68</font></html>", 
     "<html><font color=orange>+ spO2:89 pr:76</font></html>", 
     "<html><font color=orange>- spO2:89 pr:72</font></html>", 
     "<html><font color=orange>+ spO2:88 pr:73</font></html>", 
     "<html><font color=red>- spO2:87 pr:78</font></html>", 
     "<html><font color=red>+ spO2:86 pr:73</font></html>", 
     "<html><font color=green>- spO2:92 pr:74</font></html>", 
     "<html><font color=green>+ spO2:90 pr:71</font></html>" 
    }; 
    private Random randomno = new Random(); 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setUndecorated(true); 
       frame.setAlwaysOnTop(true); 
       // Transparent window... 
       frame.setBackground(new Color(255, 255, 255, 0)); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

       BackgroundPane pane = new BackgroundPane(); 
       // Set this to 0.0f to make it fully transparent 
       pane.setAlpha(0.5f); 
       pane.setLayout(new BorderLayout()); 

       pane.setBorder(new EmptyBorder(10, 10, 10, 10)); 

       frame.setContentPane(pane); 

       label = new JLabel("Loading..."); 
       label.setFont(new Font("Tahoma", Font.BOLD, 28)); 
       label.setForeground(Color.GREEN); 
       frame.add(label); 

       frame.pack(); 
       Dimension size = frame.getSize(); 
       size.width = 400; 
       frame.setSize(size); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 

       Timer timer = new Timer(200, new ActionListener() { 
        @Override 
        public void actionPerformed(ActionEvent e) { 
         label.setText(anArray[randomno.nextInt(9 - 1) + 1]); 
//      label.getParent().repaint(); 
        } 
       }); 
       timer.start(); 
      } 
     }); 
    } 

    public class BackgroundPane extends JPanel { 

     private float alpha; 

     public BackgroundPane() { 
      setOpaque(false); 
     } 

     public void setAlpha(float alpha) { 
      this.alpha = alpha; 
      repaint(); 
     } 

     public float getAlpha() { 
      return alpha; 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      g2d.setColor(getBackground()); 
      g2d.setComposite(AlphaComposite.SrcOver.derive(getAlpha())); 
      g2d.fillRect(0, 0, getWidth(), getHeight()); 
      g2d.dispose(); 
     } 

    } 

} 

пи Я не использую OpenJDK, я использую Java 8, что может сделать разницу

Тестирование возможностей

import java.awt.GraphicsDevice; 
import java.awt.GraphicsEnvironment; 

public class Test { 

    public static void main(String[] args) { 
     GraphicsEnvironment ge 
       = GraphicsEnvironment.getLocalGraphicsEnvironment(); 
     GraphicsDevice gd = ge.getDefaultScreenDevice(); 

     boolean isUniformTranslucencySupported 
       = gd.isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.TRANSLUCENT); 
     boolean isPerPixelTranslucencySupported 
       = gd.isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT); 
     boolean isShapedWindowSupported 
       = gd.isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSPARENT); 

     System.out.println("isUniformTranslucencySupported = " + isUniformTranslucencySupported); 
     System.out.println("isPerPixelTranslucencySupported = " + isPerPixelTranslucencySupported); 
     System.out.println("isShapedWindowSupported = " + isShapedWindowSupported); 
    } 

} 
+0

offtop: как твоя дочь? теперь она может быть почти 5 лет, верно? :) – SeniorJD

+0

только что был на http://stackoverflow.com/questions/11696833, где вы упомянули ее :) – SeniorJD

+0

@SeniorJD 4.5 и тестирование каждой границы: P – MadProgrammer

Смежные вопросы