如何绘制在屏幕上半透明的矩形? 这不能是JFrame
,因为JFrame在右上角具有通常的关闭,最小化和最大化选项。
如果它确实是一个挥杆能力,它是如何在稀薄的空气中绘制的?没有插入JFrame
什么? 请告诉我它是什么以及如何实现它...
回答
想到的直接想法是使用java.awt.Robot
捕获屏幕截图,将其绘制到无框窗口。从那里,你可以简单地画一个矩形,它
与例如
更新...花了一些时间......
public class SelectionRectangle {
public static void main(String[] args) {
new SelectionRectangle();
}
public SelectionRectangle() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setUndecorated(true);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new BackgroundPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class BackgroundPane extends JPanel {
private BufferedImage background;
private Point mouseAnchor;
private Point dragPoint;
private SelectionPane selectionPane;
public BackgroundPane() {
selectionPane = new SelectionPane();
try {
Robot bot = new Robot();
background = bot.createScreenCapture(getScreenViewableBounds());
} catch (AWTException ex) {
Logger.getLogger(SelectionRectangle.class.getName()).log(Level.SEVERE, null, ex);
}
selectionPane = new SelectionPane();
setLayout(null);
add(selectionPane);
MouseAdapter adapter = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
mouseAnchor = e.getPoint();
dragPoint = null;
selectionPane.setLocation(mouseAnchor);
selectionPane.setSize(0, 0);
}
@Override
public void mouseDragged(MouseEvent e) {
dragPoint = e.getPoint();
int width = dragPoint.x - mouseAnchor.x;
int height = dragPoint.y - mouseAnchor.y;
int x = mouseAnchor.x;
int y = mouseAnchor.y;
if (width < 0) {
x = dragPoint.x;
width *= -1;
}
if (height < 0) {
y = dragPoint.y;
height *= -1;
}
selectionPane.setBounds(x, y, width, height);
selectionPane.revalidate();
repaint();
}
};
addMouseListener(adapter);
addMouseMotionListener(adapter);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(background, 0, 0, this);
g2d.dispose();
}
}
public class SelectionPane extends JPanel {
private JButton button;
private JLabel label;
public SelectionPane() {
button = new JButton("Close");
setOpaque(false);
label = new JLabel("Rectangle");
label.setOpaque(true);
label.setBorder(new EmptyBorder(4, 4, 4, 4));
label.setBackground(Color.GRAY);
label.setForeground(Color.WHITE);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
add(label, gbc);
gbc.gridy++;
add(button, gbc);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.getWindowAncestor(SelectionPane.this).dispose();
}
});
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
label.setText("Rectangle " + getX() + "x" + getY() + "x" + getWidth() + "x" + getHeight());
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(new Color(128, 128, 128, 64));
g2d.fillRect(0, 0, getWidth(), getHeight());
float dash1[] = {10.0f};
BasicStroke dashed =
new BasicStroke(3.0f,
BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER,
10.0f, dash1, 0.0f);
g2d.setColor(Color.BLACK);
g2d.setStroke(dashed);
g2d.drawRect(0, 0, getWidth() - 3, getHeight() - 3);
g2d.dispose();
}
}
public static Rectangle getScreenViewableBounds() {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
return getScreenViewableBounds(gd);
}
public static Rectangle getScreenViewableBounds(GraphicsDevice gd) {
Rectangle bounds = new Rectangle(0, 0, 0, 0);
if (gd != null) {
GraphicsConfiguration gc = gd.getDefaultConfiguration();
bounds = gc.getBounds();
Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc);
bounds.x += insets.left;
bounds.y += insets.top;
bounds.width -= (insets.left + insets.right);
bounds.height -= (insets.top + insets.bottom);
}
return bounds;
}
}
更新与SnipIt例
有人建议usi在屏幕顶部放置一个透明窗口,这实际上是行不通的,因为透明窗口实际上不会响应鼠标点击,除非它们有东西要涂在它们上面,这样鼠标事件才能被捕获。
也有人建议你使用Window作为选择机制,这是一个有效的答案,然而,我会(亲自)发现这是一个不合适的解决方案,因为你希望用户只需点击并拖动选择矩形(恕我直言)。
另一种方法是使用类似SnipIt的东西。
public class SnipIt {
public static void main(String[] args) {
new SnipIt();
}
public SnipIt() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setUndecorated(true);
// This works differently under Java 6
frame.setBackground(new Color(0, 0, 0, 0));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new SnipItPane());
frame.setBounds(getVirtualBounds());
frame.setVisible(true);
}
});
}
public class SnipItPane extends JPanel {
private Point mouseAnchor;
private Point dragPoint;
private SelectionPane selectionPane;
public SnipItPane() {
setOpaque(false);
setLayout(null);
selectionPane = new SelectionPane();
add(selectionPane);
MouseAdapter adapter = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
mouseAnchor = e.getPoint();
dragPoint = null;
selectionPane.setLocation(mouseAnchor);
selectionPane.setSize(0, 0);
}
@Override
public void mouseDragged(MouseEvent e) {
dragPoint = e.getPoint();
int width = dragPoint.x - mouseAnchor.x;
int height = dragPoint.y - mouseAnchor.y;
int x = mouseAnchor.x;
int y = mouseAnchor.y;
if (width < 0) {
x = dragPoint.x;
width *= -1;
}
if (height < 0) {
y = dragPoint.y;
height *= -1;
}
selectionPane.setBounds(x, y, width, height);
selectionPane.revalidate();
repaint();
}
};
addMouseListener(adapter);
addMouseMotionListener(adapter);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Rectangle bounds = new Rectangle(0, 0, getWidth(), getHeight());
Area area = new Area(bounds);
area.subtract(new Area(selectionPane.getBounds()));
g2d.setColor(new Color(192, 192, 192, 64));
g2d.fill(area);
}
}
public class SelectionPane extends JPanel {
private JButton button;
private JLabel label;
public SelectionPane() {
button = new JButton("Close");
setOpaque(false);
label = new JLabel("Rectangle");
label.setOpaque(true);
label.setBorder(new EmptyBorder(4, 4, 4, 4));
label.setBackground(Color.GRAY);
label.setForeground(Color.WHITE);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
add(label, gbc);
gbc.gridy++;
add(button, gbc);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.getWindowAncestor(SelectionPane.this).dispose();
}
});
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
label.setText("Rectangle " + getX() + "x" + getY() + "x" + getWidth() + "x" + getHeight());
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
// I've chosen NOT to fill this selection rectangle, so that
// it now appears as if you're "cutting" away the selection
// g2d.setColor(new Color(128, 128, 128, 64));
// g2d.fillRect(0, 0, getWidth(), getHeight());
float dash1[] = {10.0f};
BasicStroke dashed =
new BasicStroke(3.0f,
BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER,
10.0f, dash1, 0.0f);
g2d.setColor(Color.BLACK);
g2d.setStroke(dashed);
g2d.drawRect(0, 0, getWidth() - 3, getHeight() - 3);
g2d.dispose();
}
}
public static Rectangle getVirtualBounds() {
Rectangle bounds = new Rectangle(0, 0, 0, 0);
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice lstGDs[] = ge.getScreenDevices();
for (GraphicsDevice gd : lstGDs) {
bounds.add(gd.getDefaultConfiguration().getBounds());
}
return bounds;
}
}
是的,'robot'可以用来** **屏幕。然后'ImageIO'可以用来将它写到磁盘上,但是这个问题;那个神秘的矩形是什么? –
使用标准Graphics2D简单地将图像涂在图像上 – MadProgrammer
我相信问题是指屏幕本身的“捕获区域边界”,而不是所得到的捕获图像(或者'Robot'实际上是否被用于超出JVM窗口绘制?) – Vulcan
你可以以创建一个基本的边框使用透明,无修饰框架。
public class ScreenRectangle extends JFrame {
public ScreenRectangle() {
this.setUndecorated(true);
this.setBackground(new Color(0, 0, 0, 0.25F));
// opacity ranges 0.0-1.0 and is the fourth paramater
this.add(new DrawPanel());
}
private class DrawPanel extends JPanel {
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(0, 0, this.getWidth(), this.getHeight());
// any other drawing
}
}
}
框架还可能需要setOpaque
,或面板尺寸,可能需要处理,但是这是它的总体思路。
请致电'super.paintComponent';) – MadProgrammer
@MadProgrammer哎呀!修正了这一点,谢谢。 (虽然在这种情况下实际上很重要,因为在JPanel上没有其他东西可以绘制,也许我会在稍后测试。) – Vulcan
@Vulcan并且没有额外的代码需要创建可更改的大小吗? 'JFrame'会自己处理它? –
更新对@MadProgrammer的示例应答的多监视器支持。
没有ExtendedState(JFrame.MAXIMIZED_BOTH)
和pack()
public SelectionRectangle() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setUndecorated(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new BackgroundPane());
frame.setResizable(false);
frame.setBounds(getScreenViewableBounds());
frame.setVisible(true);
}
});
}
public static Rectangle getScreenViewableBounds() {
GraphicsDevice[] devices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
int minx = Integer.MAX_VALUE;
int miny = Integer.MAX_VALUE;
int maxx = Integer.MIN_VALUE;
int maxy = Integer.MIN_VALUE;
for(GraphicsDevice device : devices) {
for(GraphicsConfiguration config : device.getConfigurations()) {
Rectangle bounds = config.getBounds();
minx = Math.min(minx, bounds.x);
miny = Math.min(miny, bounds.y);
maxx = Math.max(maxx, bounds.x + bounds.width);
maxy = Math.max(maxy, bounds.y + bounds.height);
}
}
return new Rectangle(new Point(minx, miny), new Dimension(maxx - minx, maxy - miny));
}
这是一个有趣的方法。我会在getScreenViewableBounds中使用一个Area,基本上将每个设备边界/矩形添加到一起,这只是我虽然 – MadProgrammer
- 1. 为什么由pyplot绘制的边框区域是黑色的?
- 2. ggplot2绘制区域边距?
- 3. 手绘选择,复制手绘选定区域在c#
- 4. 复选框选择区域
- 5. 绘制多边形点击区域
- 6. 如何在使用delphi的区域绘制边框?
- 7. 如何在Google图表的图表区域绘制边框?
- 8. 边框绘制
- 9. 为什么controlpaint绘制方法在客户端绘画区域之外绘制?
- 10. 选择区域
- 11. 绘制UIImage的选定区域
- 12. VBA绘制边框
- 13. 绘制3D边框
- 14. 绘制后无法选择多边形
- 15. 让用户绘制矩形来选择区域
- 16. 用Pixi.js绘制鼠标选择区域(橡皮筋)/ html Canvas
- 17. Xcode记住用户选择的区域
- 18. Highmaps:将边框区域
- 19. 使用复选框缩小重复区域中的记录
- 20. 选择区域OpenCV
- 21. MySQL选择区域
- 22. DirectX限制绘图区域
- 23. 如何创建只能绘制到圆形区域边界的标记?
- 24. 可能会覆盖fabricjs中的边框选择区域 - 控件选项
- 25. 设置Highcharts绘图区域边距
- 26. 当我们在复选框模型中选择所选记录时,限制取消选择剩余记录
- 27. 用阴影区域绘制直方图并在R中没有公共边框
- 28. 在绘图区域上绘制图像
- 29. GTK +如何绘制绘图区域
- 30. 绘制边框形状javafx
本教程可能会帮助你,[如何使半透明窗口(http://docs.oracle.com/ javase/tutorial/uiswing/misc/trans_shaped_windows.html) –