swing - java jlabel在Windows中工作,但在Linux中不工作,在屏幕上显示旧格式,openjdk?

标签 swing ubuntu jlabel java

所以我编写了一个Java应用程序,它在屏幕顶部提供透明的平视显示器,它在Windows上完美运行,但在我的kubuntu 16.04机器上,当您更改标签文本时,它不会清除旧标签,你最终会得到大量重叠的困惑。

因为一图抵一千字,上图是在windows下的样子,下图是在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();
    }
}

最佳答案

所以,有很多问题

  • 您违反了 Swing 的单线程规则,本质上是从 EDT 上下文之外更新 UI,如果系统在您尝试更新某些内容时尝试绘制某些内容,则可能会导致问题
  • getContentPane().setBackground(new Color(1.0f,1.0f,1.0f,0.0f)); - Swing 不知道如何处理基于 alpha 的不透明组件颜色,它往往不会更新其下面的任何组件。

透明 window ……很有趣……它们往往会带来超出我们通常预期的问题。

在我的 Mac 系统上,我能够重现该问题,但不一致。这尤其明显,因为 Mac 操作系统不断在文本周围渲染阴影。

我摆脱的第一件事是 setType(javax.swing.JFrame.Type.UTILITY);,我还添加了标签父容器的 repaint 请求这似乎已经解决了问题的症状,但同样,我有时也能够执行代码。

如果您想定期更新 UI,您应该使用 Swing Timer,请参阅 How to use Swing Timers更多细节。如果您需要在后台执行某些操作然后更新 UI,您应该使用 SwingWorker,看看 Worker Threads and SwingWorker了解更多详情

Translucent example

(哇是我,它不喜欢我的动画 gif :()

该示例特意使用了半透明背景,其目的是显示框架。将 pane.setAlpha(0.5f); 更改为 pane.setAlpha(0.0f); 以使其完全透明(我也测试过)。

如果您遇到问题,请取消注释 Timer 中的 label.getParent().repaint(); 行,看看是否有帮助

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();
        }

    }

}

nb我没有使用 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);
    }

}

关于swing - java jlabel在Windows中工作,但在Linux中不工作,在屏幕上显示旧格式,openjdk?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41824508/

相关文章:

java - JFrame getHeight() 和 getWidth() 返回 0

java - 编译器不识别 Action 监听器类中的参数

java - 创建具有多个图像的 JPanel

java - 从 JButton 更改 JLabel 的图像

java - 使用触摸屏运行 java swing

java - 基本 FFmpeg 转换错误?

c - 为什么我不能写超过 2GB?

php - 拉维尔 5 : Installing ide helper for Netbeans

java - Java GUI 中的图片更改

java - 使用哪个 Swing 组件?