我目前正在开发应用程序,需要选择屏幕区域的功能。我想出了一个透明的,未修饰的全屏JFrame,并在其中添加了半透明的,不透明的JPanel,其中半透明的黑色背景以及选择被绘制。
虽然这个想法(和代码)在Windows上运行良好,但它在linux上的故事并不相同,在调用repaint()时,JPanel的背景似乎没有被清除(尽管我告诉它通过各种方法) - 每个重绘方法,背景和组件变得更暗更暗等
这是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(由朋友测试)中进行了测试
编辑:也在OSX(Yosemite& El capitan)下进行了测试,两者都运行良好。
答案 0 :(得分:3)
this.setBackground(new Color(255, 255, 255, 0));
如果您希望组件完全透明,请使用:
component.setOpaque( false );
这告诉Swing寻找父组件并先绘制它,这样你就不会得到绘画工件。
private static Color bg = new Color(0,0,0,0.5f);
如果你想要半透明背景,那么需要自定义编码,因为Swing不支持这个。
查看Backgrounds With Transparency以获取有关此主题和一些解决方案的更多信息。
一种是使用以下代码进行自己的自定义绘画:
JPanel panel = new JPanel()
{
protected void paintComponent(Graphics g)
{
g.setColor( getBackground() );
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
};
另一个解决方案是可重用的类,可以与任何组件一起使用,因此您不需要自定义每个组件。 panel.setOpaque(假); //将首先绘制父级的背景 panel.setBackground(new Color(255,0,0,20)); frame.add(面板);
答案 1 :(得分:2)
如果无法复制问题,很难知道问题的确切原因。代码中有许多值得关注的领域...
super.paintComponent
setDoubleBuffered(false)
this.setBackground(bg);
上使用JPanel
并将基于alpha的颜色传递给它AlphaComposite
并谨慎使用以尝试清除Graphics
背景基本行动方针是简化绘画流程,直到您能够确定导致问题的行动或行动组合为止。
或采取另一种方法。您可以考虑仅使用AlphaComposite
并减去要从中公开的区域,而不是使用不同Area
设置的组合....
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.geom.Area;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
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);
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.setOpaque(false);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
Area area = new Area(new Rectangle(0, 0, getWidth(), getHeight()));
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);
area.subtract(new Area(new Rectangle(asx - 1, asy - 1, w + 2, h + 2)));
}
g2.setComposite(AlphaComposite.Src.derive(.25f));
g2.setPaint(bg);
g2.fill(area);
g2.setComposite(AlphaComposite.Src.derive(1f));
g2.setPaint(Color.WHITE);
g2.drawString("Press Escape to exit", 10, 20);
g2.dispose();
}
}
}
答案 2 :(得分:0)
如果要清除背景,请务必致电super.paintComponent()
。
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g.create();