gpt4 book ai didi

java - Swing :带箭头的弹出框

转载 作者:搜寻专家 更新时间:2023-10-31 19:48:31 26 4
gpt4 key购买 nike

我想创建一个带有箭头、圆角的 Google Chrome Collection 夹样式的弹出窗口,如果我有时间,还可以添加阴影效果。在 Java Swing 中。什么是最好的方法? SplashScreen ?或者只是一个普通的 AWT Window ?其他想法?谢谢!

最佳答案

有几个选项,每个选项都有自己的优点和缺点...

  1. 创建一个自定义形状的窗口 - 通过这种方法,一些系统将能够在形状窗口后面创建额外的阴影,这也适用于大多数系统(甚至应该适用于 linux JDK's)。这种方法的缺点(实际上使它无法使用)是没有锯齿的形状边界线 - 如果您创建一些椭圆形窗口,它的侧面会显得粗糙。

  2. 创建一个具有绘制形状的非不透明未装饰窗口 - 这种方法将解决 (1) 方法的主要问题。您可以为在完全透明窗口上绘制的形状添加别名。这个的坏处是它只适用于 Win 和 Mac 系统。在(大部分)任何 Linux 系统上,您都会得到一个矩形结果窗口和大量关于不受支持的操作的错误。

  3. 在 java-window 中创建一个自定义形状的弹出窗口,并将其放置在分层窗口或玻璃 Pane 上。这将使您能够完全避免任何兼容性问题并获得 (2) 方法的好处。不过这种方法有一个缺点——您只能在窗口根 Pane 边界中显示此类弹出窗口。在大多数情况下,这仍然比其他两种方式要好得多,因为它使用的资源更少,不会创建额外的窗口,并且您可以控制弹出窗口的每个部分。

关于第三种方法 - 您可以查看我在自己的项目中创建的 TooltipManager WebLookAndFeel - 它使用窗口玻璃 Pane 显示自定义形状的半透明工具提示,具有阴影效果。同样很快我将添加窗口 PopupManager,它将允许快速创建“内部”窗口弹出窗口。

以下是一些方法示例:

在所有示例中都使用了 ahead 的一些代码

创建形状的方法:

private static Area createShape ()
{
Area shape = new Area ( new RoundRectangle2D.Double ( 0, 20, 500, 200, 20, 20 ) );

GeneralPath gp = new GeneralPath ( GeneralPath.WIND_EVEN_ODD );
gp.moveTo ( 230, 20 );
gp.lineTo ( 250, 0 );
gp.lineTo ( 270, 20 );
gp.closePath ();
shape.add ( new Area ( gp ) );

return shape;
}

允许通过拖动组件移动窗口的鼠标适配器:

public static class WindowMoveAdapter extends MouseAdapter
{
private boolean dragging = false;
private int prevX = -1;
private int prevY = -1;

public WindowMoveAdapter ()
{
super ();
}

public void mousePressed ( MouseEvent e )
{
if ( SwingUtilities.isLeftMouseButton ( e ) )
{
dragging = true;
}
prevX = e.getXOnScreen ();
prevY = e.getYOnScreen ();
}

public void mouseDragged ( MouseEvent e )
{
if ( prevX != -1 && prevY != -1 && dragging )
{
Window w = SwingUtilities.getWindowAncestor ( e.getComponent () );
if ( w != null && w.isShowing () )
{
Rectangle rect = w.getBounds ();
w.setBounds ( rect.x + ( e.getXOnScreen () - prevX ),
rect.y + ( e.getYOnScreen () - prevY ), rect.width, rect.height );
}
}
prevX = e.getXOnScreen ();
prevY = e.getYOnScreen ();
}

public void mouseReleased ( MouseEvent e )
{
dragging = false;
}
}

第一种方法示例:

public static void main ( String[] args )
{
JFrame frame = new JFrame ();
frame.setUndecorated ( true );

JPanel panel = new JPanel ();
panel.setBackground ( Color.BLACK );
WindowMoveAdapter wma = new WindowMoveAdapter ();
panel.addMouseListener ( wma );
panel.addMouseMotionListener ( wma );
frame.getContentPane ().add ( panel );

Area shape = createShape ();
AWTUtilities.setWindowShape ( frame, shape );
frame.setSize ( shape.getBounds ().getSize () );
frame.setLocationRelativeTo ( null );

frame.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
frame.setVisible ( true );
}

如你所见-圆角的形状很粗糙而且不好看

第二种方法:

public static void main ( String[] args )
{
JFrame frame = new JFrame ();
frame.setUndecorated ( true );

final Area shape = createShape ();
JPanel panel = new JPanel ()
{
protected void paintComponent ( Graphics g )
{
super.paintComponent ( g );

Graphics2D g2d = ( Graphics2D ) g;
g2d.setRenderingHint ( RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON );

g2d.setPaint ( Color.BLACK );
g2d.fill ( shape );
}
};
panel.setOpaque ( false );
WindowMoveAdapter wma = new WindowMoveAdapter ();
panel.addMouseListener ( wma );
panel.addMouseMotionListener ( wma );
frame.getContentPane ().add ( panel );

AWTUtilities.setWindowOpaque ( frame, false );
frame.setSize ( shape.getBounds ().getSize () );
frame.setLocationRelativeTo ( null );

frame.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
frame.setVisible ( true );
}

现在它看起来应该很完美——唯一的问题是它只能在 Windows 和 Mac 上正常工作(至少在 1.6.x JDK 中)。至少大约一个月前,我上次在各种操作系统上检查它时是这样。

第三种方法

public static void main ( String[] args )
{
JFrame frame = new JFrame ();

JPanel panel = new JPanel ( new BorderLayout () );
panel.setOpaque ( false );
WindowMoveAdapter wma = new WindowMoveAdapter ();
panel.addMouseListener ( wma );
panel.addMouseMotionListener ( wma );
frame.getContentPane ().add ( panel );

panel.add ( new JButton ( "Test" ) );

final Area shape = createShape ();

JPanel glassPane = new JPanel ( null )
{
public boolean contains ( int x, int y )
{
// This is to avoid cursor and mouse-events troubles
return shape.contains ( x, y );
}
};
glassPane.setOpaque ( false );
frame.setGlassPane ( glassPane );
glassPane.setVisible ( true );

JComponent popup = new JComponent ()
{
protected void paintComponent ( Graphics g )
{
super.paintComponent ( g );

Graphics2D g2d = ( Graphics2D ) g;
g2d.setRenderingHint ( RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON );

g2d.setPaint ( Color.BLACK );
g2d.fill ( shape );
}
};
popup.addMouseListener ( new MouseAdapter ()
{
// To block events on the popup
});
glassPane.add ( popup );
popup.setBounds ( shape.getBounds () );
popup.setVisible ( true );

frame.setSize ( 800, 500 );
frame.setLocationRelativeTo ( null );

frame.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
frame.setVisible ( true );
}

这是放置在玻璃 Pane 上的弹出窗口的简单示例。如您所见,它仅存在于 JFrame 内部,但具有别名的一面并且可以在任何类型的操作系统上正常工作。

关于java - Swing :带箭头的弹出框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10100815/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com