macos 在半透明框架/面板/组件上重新上漆。
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2163544/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Re-paint on translucent frame/panel/component.
提问by OscarRyz
I'm trying to create a translucent window with Java on OSX and add a JLabel
to it.
我正在尝试在 OSX 上使用 Java 创建一个半透明窗口并向其中添加一个JLabel
。
This JLabel
changes its text every second....
这JLabel
每秒都会更改其文本....
However the component is not repainting well.
然而,该组件不能很好地重新绘制。
How can I solve this problem?
我怎么解决这个问题?
I've found the thesearticles, but I can't figure out how to solve it.
If possible, please paste the fixing source code, here's mine:
如果可能,请粘贴修复源代码,这是我的:
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.Color;
import java.awt.Font;
import java.util.Timer;
import java.util.TimerTask;
public class Translucent {
public static void main( String [] args ) {
JFrame frame = new JFrame();
frame.setBackground( new Color( 0.0f,0.0f,0.0f,0.3f));
final JLabel label = new JLabel("Hola");
label.setFont( new Font( label.getFont().getFamily(), Font.PLAIN, 46 ) );
label.setForeground( Color.white );
frame.add( label );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
Timer timer = new Timer();
timer.schedule( new TimerTask(){
int i = 0;
public void run() {
label.setText("Hola "+ i++ );
}
}, 0, 1000 );
}
}
采纳答案by trashgod
I've had some luck extending JLabel
and implementing Icon
to get a translucent component working the way I want. You can see the result of various rule combinations in this AlphaCompositeDemo. The example below is 100% white atop 50% black.
我有一些运气扩展JLabel
和实施,Icon
以使半透明组件按我想要的方式工作。您可以在这个AlphaCompositeDemo 中看到各种规则组合的结果。下面的示例是 100% 白色和 50% 黑色。
Addendum: Note how this example composites opaque text on a clear offscreen background over the translucent frame background.
附录:请注意此示例如何在半透明框架背景上的清晰屏幕外背景上合成不透明文本。
Addendum: Here's a way to make the whole frame translucent. Unfortunately, it dims the content, too.
附录:这是一种使整个框架半透明的方法。不幸的是,它也会使内容变暗。
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Translucent extends JPanel implements ActionListener {
private static final int W = 300;
private static final int H = 100;
private static final Font font =
new Font("Serif", Font.PLAIN, 48);
private static final SimpleDateFormat df =
new SimpleDateFormat("HH:mm:ss");
private final Date now = new Date();
private final Timer timer = new Timer(1000, this);
private BufferedImage time;
private Graphics2D timeG;
public Translucent() {
super(true);
this.setPreferredSize(new Dimension(W, H));
timer.start();
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int w = this.getWidth();
int h = this.getHeight();
g2d.setComposite(AlphaComposite.Clear);
g2d.fillRect(0, 0, w, h);
g2d.setComposite(AlphaComposite.Src);
g2d.setPaint(g2d.getBackground());
g2d.fillRect(0, 0, w, h);
renderTime(g2d);
int w2 = time.getWidth() / 2;
int h2 = time.getHeight() / 2;
g2d.setComposite(AlphaComposite.SrcOver);
g2d.drawImage(time, w / 2 - w2, h / 2 - h2, null);
}
private void renderTime(Graphics2D g2d) {
g2d.setFont(font);
String s = df.format(now);
FontMetrics fm = g2d.getFontMetrics();
int w = fm.stringWidth(s);
int h = fm.getHeight();
if (time == null && timeG == null) {
time = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
timeG = time.createGraphics();
timeG.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
timeG.setFont(font);
}
timeG.setComposite(AlphaComposite.Clear);
timeG.fillRect(0, 0, w, h);
timeG.setComposite(AlphaComposite.Src);
timeG.setPaint(Color.green);
timeG.drawString(s, 0, fm.getAscent());
}
private static void create() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setBackground(new Color(0f, 0f, 0f, 0.3f));
f.setUndecorated(true);
f.add(new Translucent());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
now.setTime(System.currentTimeMillis());
this.repaint();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
create();
}
});
}
}
回答by Laird Nelson
The problem may also have to do with the fact that you're setting the JLabel
's text from a thread that is not the Event Dispatch Thread.
问题也可能与您JLabel
从不是事件调度线程的线程设置的文本这一事实有关。
There are two ways to solve this. Without testing your problem, I'd solve it by using the javax.swing.Timer
class, instead of the java.util.Timer
class. javax.swing.Timer
will ensure that events are fired on the dispatch thread.
有两种方法可以解决这个问题。如果不测试您的问题,我会通过使用javax.swing.Timer
类而不是类来解决它java.util.Timer
。 javax.swing.Timer
将确保在调度线程上触发事件。
So (untested code):
所以(未经测试的代码):
final ActionListener labelUpdater = new ActionListener() {
private int i;
@Override
public final void actionPerformed(final ActionEvent event) {
label.setText("Hola " + this.i++);
}
};
final javax.swing.Timer timer = new javax.swing.Timer(1000L, labelUpdater);
The other way to solve it is to continue to use java.util.Timer
but to make sure that you use EventQueue.invokeLater(Runnable)
to ensure that updates to the label take place on the EDT.
解决此问题的另一种方法是继续使用,java.util.Timer
但要确保使用EventQueue.invokeLater(Runnable)
以确保在 EDT 上对标签进行更新。
回答by Icy
I don't know if the problem is solved, but I solved it in my application with a "Frame.repaint();"
我不知道问题是否已解决,但我在我的应用程序中使用“Frame.repaint();”解决了它
So every second my Frame will be repainted and my JLabel will be updatet with the actual time.
所以每一秒我的框架都会被重新绘制,我的 JLabel 将被更新为实际时间。
回答by user6930434
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mreg;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
/**
*
* @author Manoj
*/
public class TranscluentWindow {
public static void main(String[] args) {
new TranscluentWindow();
}
public TranscluentWindow() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JWindow frame = new JWindow();
frame.setAlwaysOnTop(true);
frame.addMouseListener(new MouseAdapter() {
});
frame.setBackground(new Color(0,0,0,0));
frame.setContentPane(new TranslucentPane());
frame.add(new JLabel(new ImageIcon(ImageIO.read(getClass().getResource("/124742-high-school-collection/png/image_4.png")))));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(2500);
} catch (InterruptedException ex) {
}
frame.dispose();
new loging().setVisible(true);
}
}).start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public class TranslucentPane extends JPanel {
public TranslucentPane() {
setOpaque(false);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.SrcOver.derive(0.0f));
g2d.setColor(getBackground());
g2d.fillRect(0, 0, getWidth(), getHeight());
}
}
}