所以我编写了一个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了解更多详情
(哇是我,它不喜欢我的动画 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/