我目前正在开发一个应用程序,它需要选择屏幕区域的功能。我想到了创建一个透明的、无装饰的、全屏的JFrame,并在其中添加一个半透明的、非不透明的Jpanel,在其中画上半透明的深色背景以及选择。
虽然这个想法(和代码)在Windows上运行良好,但在Linux上就不一样了,Jpanel的背景似乎不会在调用repaint()时被清除(即使我通过各种方法告诉它)--在每个repaint方法中,背景和组件都变得越来越暗,等等。
Here's the MVCE:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ExampleFrame extends JFrame{
private ExamplePanel selectionPane;
public ExampleFrame(){
this.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
@Override
public void keyPressed(KeyEvent e) {
@Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
ExampleFrame.this.dispatchEvent(new WindowEvent(ExampleFrame.this, WindowEvent.WINDOW_CLOSING));
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
this.setSize(screenSize);
this.setUndecorated(true);
this.setBackground(new Color(255, 255, 255, 0));
populate();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setType(Window.Type.UTILITY);
this.setVisible(true);
private void populate(){
this.selectionPane = new ExamplePanel();
this.setContentPane(selectionPane);
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new ExampleFrame();
public static class ExamplePanel extends JPanel{
private static Color bg = new Color(0,0,0,0.5f);
private int sx = -1, sy = -1, ex = -1, ey = -1;
public ExamplePanel(){
MouseAdapter mouseAdapter = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
sx = sy = ex = ey = -1;
sx = e.getX();
sy = e.getY();
repaint();
@Override
public void mouseReleased(MouseEvent e) {
ex = e.getX();
ey = e.getY();
repaint();
@Override
public void mouseDragged(MouseEvent e) {
ex = e.getX();
ey = e.getY();
repaint();
this.addMouseListener(mouseAdapter);
this.addMouseMotionListener(mouseAdapter);
this.setDoubleBuffered(false);
this.setOpaque(false);
this.setBackground(bg);
@Override
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D)g.create();
g2.setComposite(AlphaComposite.Clear);
g2.setBackground(new Color(255, 255, 255, 0));
g2.fillRect(0, 0, getWidth(), getHeight());
//g2.clearRect(0, 0, getWidth(), getHeight()); //neither of them work
g2.setComposite(AlphaComposite.Src.derive(.5f));
g2.setPaint(getBackground());
g2.fillRect(0, 0, getWidth(), getHeight());
g2.setComposite(AlphaComposite.Src.derive(1f));
g2.setPaint(Color.WHITE);
g2.drawString("Press Escape to exit", 10, 20);
if(!(sx == -1 || sy == -1 || ex == -1 || ey == -1)){
int asx = Math.min(sx, ex);
int asy = Math.min(sy, ey);
int w = Math.abs(ex - sx);
int h = Math.abs(ey - sy);
g2.setComposite(AlphaComposite.Src);
g2.setPaint(new Color(255, 255, 255, 0));
g2.fillRect(asx, asy, w, h);
g2.setPaint(new Color(0, 0, 0, 1));
g2.fillRect(asx, asy, w, h);
g2.setComposite(AlphaComposite.SrcOver);
g2.setStroke(new BasicStroke(2));
g2.setPaint(new Color(1, 1, 1, 0.15f));
g2.drawRect(asx-1,asy-1, w+2, h+2);
有什么想法可能导致这种情况吗?或者这可能是Linux上Java的一个错误?我曾在Windows 10、Ubuntu 14.04 LTS以及运行KDE gui的未知版本的Arch Linux下测试过这个问题(由一个朋友测试)。
EDIT: also tested under OSX (Yosemite & El capitan), both worked fine.