该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2010-07-13
yedaya 写道 “对窗体上的组件安装这一listener,就可以对窗口中任意元素进行拖拽,直接拖动窗体四处晃悠了。” 具体怎么装?能不能就那个红色的方框演示一下。 比较愚钝,请明示!!谢谢。 请参考FreeLoginUI.java中的132行: logoLabel.addMouseListener(moveWindowListener); logoLabel.addMouseMotionListener(moveWindowListener); |
|
返回顶楼 | |
发表时间:2010-07-13
xiaozhonghua 写道 yedaya 写道 “对窗体上的组件安装这一listener,就可以对窗口中任意元素进行拖拽,直接拖动窗体四处晃悠了。”
具体怎么装?能不能就那个红色的方框演示一下。 比较愚钝,请明示!!谢谢。 请参考FreeLoginUI.java中的132行: logoLabel.addMouseListener(moveWindowListener); logoLabel.addMouseMotionListener(moveWindowListener); 哦,明白了,我没有添加第二个事件,出来了,谢谢。 |
|
返回顶楼 | |
发表时间:2010-07-16
雪花报错:
[Exception in thread "main" java.lang.IllegalArgumentException: Width (0) and height (0) cannot be <= 0/code] 加上frame.setBounds(0, 0, 1, 1);后就好了。 期望第四刀。源码什么时候出出来呀。 以前做的是web,看了你的贴后感觉不错,想看看你代码的规划,风格。 |
|
返回顶楼 | |
发表时间:2010-08-30
最后修改:2010-08-30
根据官方导引http://java.sun.com/developer/technicalArticles/GUI/translucent_shaped_windows/和http://www.docjar.com/docs/api/com/sun/awt/AWTUtilities.html,类AWTUtilities对于窗体透明性的支持有3个枚举常量,并且"The constants PERPIXEL_TRANSPARENT, TRANSLUCENT, PERPIXEL_TRANSLUCENT represent shaping, simple translucency, and per-pixel translucency respectively."。
其实,类AWTUtilities只是想知道窗体Bounds范围所有点的alpha值。它提供了3种不同的设置方法:1是利用Shape设置点全透明(0.0f,如果在Shape边缘或Shape内)或全不透明(1.0f,在Shape外);2是设置点为同一个透明度(例如可以设置为0.8f);3是自己手动设置每一个点的alpha值(譬如官方导引中示例的是GradiantPaint)。如下所示。方法1演示了一个字母'T'的Shape。 这3种方法不分好坏,取决于自己的使用目的。方法1比较适用于Shape比较整齐(因为没有anti-alias),譬如实现一个“品”字形的窗体,也比较适用于Shape很容易获得的情况,譬如一个字符串在特定Font下的显示。方法2适用于窗体透明性很统一的时候。方法3适用于自定义,例如使用一张png图片指出各个点的alpha值。但是应当注意,只要AWTUtilities.setWindowOpaque(frame, false),无论你设置任何子组件的Opaque与否,系统都会以Opaque==false处理,这样就会导致JComponent的背景不会被绘制。 所以lz登录界面采用第3种方法是最好的。不过题外话说一句,即使使用方法1,如下办法也可以正确绘制图片的Shape。即逐行扫描每个点的alpha值,连在一起的不为0.0f的点可以画一个Rectangle,然后将所有的Rectangle合并成一个Area。避免了lz提到的算法的“边缘必须是连续的,甚至必须是‘外凸’的”的缺陷。另外,方法3中使用的图片,我在Photoshop做处理的时候,一个点的不透明度&填充<5%则在我的Java实验中被当成完全透明(alpha=0.0f),反之就有alpha>0.0f。下面一个例子使用了这样一个“回”字型的png,里面空白的不透明度是0%,外圈空白的不透明度是5%,虽然他们视觉上几乎辨别不出来区别,但是用鼠标点一点就知道了, (不过贴到论坛上 怎么看不出来是透明了 ) 配套使用的Java代码: import java.awt.Color; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.SwingUtilities; import com.sun.awt.AWTUtilities; public class TranslucentFrameDemo extends JFrame { private static final long serialVersionUID = 3878450094604602368L; TranslucentFrameDemo() { setUndecorated(true); setSize(400, 400); AWTUtilities.setWindowOpaque(this, false); final JLabel label = new JLabel(new ImageIcon("d:\\clip.png")); label.setBackground(Color.BLACK); // actually won't work add(label); } public static void main(final String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new TranslucentFrameDemo().setVisible(true); } }); } } 另外应当注意的是,不是所有的OS——例如linux的CentOS发行版——都支持AWTUtilities带来的窗体透明。应该在使用窗体透明的方面前加入检测代码,如官方示例中做的那样。 关于实现原理,由于在不规则的窗体中使用"Alt+Space"快捷键依然有效,依然可以设置AlwaysOnTop(true)并且确实一直在顶端,并且其绘制过程中使用了sun.awt.windows.WWindowPeer和BufferedImage类(参考lz把窗体设为很大导致溢出),我倾向于认为这样的不规则窗体依然使用了OS的window作为对等的peer,只是JVM先把不规则窗体中的所有内容先绘制到BufferedImage上,再向OS的window绘制Image,这个过程和Swing正常状态下直接使用window的绘制上下文绘制Swing组件还是略有不同的。不过我对Windows的底层编程实在不熟悉,也仅局限于这样猜测。为什么Windows的window现在可以是不规则、透明的?为什么以前不能?底层的实现原理是什么?关于这点疑问很希望和大家交流相关资料或见解!:) 再另外,半透明的Jcomponent绘制可以参考: import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Composite; import java.awt.Graphics; import java.awt.Graphics2D; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UIManager.LookAndFeelInfo; public class TanslucentJButtonDemo extends JFrame { TanslucentJButtonDemo() { setSize(300, 300); setDefaultCloseOperation(EXIT_ON_CLOSE); setLayout(null); getContentPane().setBackground(Color.YELLOW); MyButton b = new MyButton(); b.setBounds(100,50,100,100); add(b); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { try { for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(info.getName())) { UIManager.setLookAndFeel(info.getClassName()); break; } } } catch (Exception e) { // If Nimbus is not available, you can set the GUI to another look and feel. } new TanslucentJButtonDemo().setVisible(true); } }); } } class MyButton extends JButton { MyButton() { super("Push Me!"); setOpaque(false); // critical! Make this line a comment and guess what happens. } @Override public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; Composite com = g2.getComposite(); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f)); super.paint(g2); g2.setComposite(com); } } 选择在Jcomponent里面覆盖paint而不是在某个UIDelegate里覆盖,是因为这样可以无论什么LAF,都可以获得渲染后的半透明组件。 感谢lz的尝试和工作!向老汪致敬! |
|
返回顶楼 | |
发表时间:2010-09-04
另外,通过尝试,可以由以下小技巧实现用Shape定义的Frame的antilias。效果对比:
import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsEnvironment; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.Transparency; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.image.BufferedImage; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; import com.sun.awt.AWTUtilities; public class AntiliasShapedFrame extends JFrame { /** * */ private static final long serialVersionUID = 3390474537469218502L; private Shape s = null; private int width = 0; private int height = 0; AntiliasShapedFrame() { initShape(); setUndecorated(true); AWTUtilities.setWindowOpaque(this, false); setSize(width, height); setContentPane(new MyPanel()); setDefaultCloseOperation(EXIT_ON_CLOSE); setLocationRelativeTo(null); } private void initShape() { final GlyphVector vector = new Font(Font.SANS_SERIF, Font.BOLD, 100).createGlyphVector(new FontRenderContext(null, false, false), "Hello, World!"); s = vector.getOutline(); width = (int) (s.getBounds().getWidth()); height = (int) (s.getBounds().getHeight()); } private BufferedImage createImg() { final BufferedImage img = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration() .createCompatibleImage(width, height, Transparency.TRANSLUCENT); final Graphics2D g2 = img.createGraphics(); g2.setComposite(AlphaComposite.Clear); g2.fillRect(0, 0, width, height); g2.translate(-s.getBounds().getX(), -s.getBounds().getY()); g2.setComposite(AlphaComposite.Src); //g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setPaint(new GradientPaint(0, 0, Color.RED, width, height, Color.YELLOW)); g2.fill(s); g2.dispose(); return img; } public static void main(final String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new AntiliasShapedFrame().setVisible(true); } }); } class MyPanel extends JPanel { private static final long serialVersionUID = 1034001230923305745L; @Override protected void paintComponent(final Graphics g) { super.paintComponent(g); ((Graphics2D) g).drawImage(createImg(), 0, 0, null); } } } |
|
返回顶楼 | |
发表时间:2010-09-04
sun的论坛里有不少swing的牛人,基本上任何问题在那里都可以找到答案。但某些人对oop不太精通,有时候和他们很难沟通。
|
|
返回顶楼 | |
发表时间:2010-10-19
ubuntu10.10下
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: The window must use a translucency-compatible graphics configuration at com.sun.awt.AWTUtilities.setWindowOpaque(AWTUtilities.java:377) at free.FreeLoginUI.init(FreeLoginUI.java:96) at free.FreeLoginUI.<init>(FreeLoginUI.java:89) at free.FreeLoginUI$4.run(FreeLoginUI.java:207) |
|
返回顶楼 | |
发表时间:2010-11-02
强大的LZ,正在学习swing,感谢分享
|
|
返回顶楼 | |
发表时间:2010-11-03
xiangkun 写道 为什么我的这里运行出来是这样的呢? Windows Xp下的. 已经很漂亮了哦 |
|
返回顶楼 | |
发表时间:2010-11-05
楼主,感谢你的奉献!刚学Swing。你的文章对我帮助很大!谢谢
|
|
返回顶楼 | |