将组件放置在玻璃板上
我有一个 JLabel 的子类,它构成了我的 GUI 的一个组件。我已经实现了将组件从一个容器拖放到另一个容器的功能,但没有任何视觉效果。我想让这个 JLabel 在将项目从一个容器拖动到另一个容器时跟随光标。我想我可以创建一个玻璃板并在上面绘制它。但是,即使我将组件添加到玻璃窗格,将组件设置为可见,将玻璃窗格设置为可见,并将玻璃窗格设置为不透明,我仍然看不到该组件。我知道该组件可以工作,因为我可以将其添加到内容窗格并显示它。
如何将组件添加到玻璃板?
终于弄清楚如何让这个简单的例子工作了。谢谢,@akf。我能够根据我原来的问题调整这个解决方案,从而允许我删除大约 60 行手动呈现 JLabel 表示的 Java2D 代码。
package test;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class MainFrame extends JFrame {
/**
* @param args
*/
public static void main(String[] args) {
MainFrame mf = new MainFrame();
mf.setSize(400, 400);
mf.setLocationRelativeTo(null);
mf.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
mf.setGlassPane(new JPanel());
JLabel l = new JLabel();
l.setText("Hello");
l.setBorder(new LineBorder(Color.BLACK, 1));
l.setBounds(10, 10, 50, 20);
l.setBackground(Color.RED);
l.setOpaque(true);
l.setPreferredSize(l.getSize());
//mf.add(l);
((JPanel)mf.getGlassPane()).add(l);
mf.getGlassPane().setVisible(true);
mf.setVisible(true);
}
}
I have a subclass of JLabel that forms a component of my GUI. I have implemented the ability to drag and drop the component from one container to another, but without any visual effects. I want to have this JLabel follow the cursor during the drag of the item from one container to another. I figured that I could just create a glass pane and draw it on there. However, even after I add the component to the glass pane, set the component visible, and set the glass pane visible, and set the glass pane as opaque, I still so not see the component. I know the component works because I can add it to the content pane and have it show up.
How do I add a component to the glass pane?
Finally figured how to get the simple example working. Thanks, @akf. I was able to adapt this solution to my original problem, allowing me to remove ~60 lines of Java2D code that manually rendered a representation of the JLabel.
package test;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class MainFrame extends JFrame {
/**
* @param args
*/
public static void main(String[] args) {
MainFrame mf = new MainFrame();
mf.setSize(400, 400);
mf.setLocationRelativeTo(null);
mf.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
mf.setGlassPane(new JPanel());
JLabel l = new JLabel();
l.setText("Hello");
l.setBorder(new LineBorder(Color.BLACK, 1));
l.setBounds(10, 10, 50, 20);
l.setBackground(Color.RED);
l.setOpaque(true);
l.setPreferredSize(l.getSize());
//mf.add(l);
((JPanel)mf.getGlassPane()).add(l);
mf.getGlassPane().setVisible(true);
mf.setVisible(true);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
下面的示例代码展示了如何在棋盘上拖动棋子。它使用 JLayeredPane 而不是玻璃窗格,但我确信概念是相同的。即:
a) 将玻璃窗格添加到根窗格
b) 使玻璃板可见
c) 将组件添加到玻璃窗格中,确保边界有效
d) 使用 setLocation() 来动画组件的拖动编辑
:添加代码来修复 SSCCE
当使用布局管理器时,您永远不会使用 setSize() 或 setBounds() 方法。在您的情况下,您只需将首选大小设置为 (0, 0),因为这是所有组件的默认大小。
当您将标签添加到框架时,它会起作用,因为框架内容窗格的默认布局管理器是边框布局,因此忽略标签的首选大小,并将标签设置为框架的大小。
然而,默认情况下,JPanel 使用 FlowLayout,它确实尊重组件的首选大小。由于首选尺寸为 0,因此无需绘制任何内容。
此外,玻璃板需要变得可见才能进行涂漆。
我建议您阅读Swing 教程。其中有关于布局管理器如何工作以及玻璃板如何工作的部分,每个部分都有工作示例。
编辑:下面添加的示例代码:
The example code below shows how to drag a chess piece around a chess board. It uses JLayeredPane instead of a glass pane, but I'm sure the concepts would be the same. That is:
a) add the glass pane to the root pane
b) make the glass pane visible
c) add the component to the glass pane making sure the bounds are valid
d) use setLocation() to animate the dragging of the component
Edit: added code to fix SSCCE
When using layout managers you never use the setSize() or setBounds() methods. In your case you just set the preferred size to (0, 0) since this is the default size of all components.
It works when you add the label to the frame because the default layout manger for the content pane of the frame is a border layout, therefore the preferred size of the label is ignored and the label is made the size of the frame.
However, by default a JPanel uses a FlowLayout which does respect the preferred size of the component. Since the preferred size is 0, there is nothing to paint.
Also, the glass pane needs to made visible in order for it to be painted.
I suggest you read the Swing tutorial. There are section on how layout managers work and on how glass panes work and each section has working examples.
Edit: Example code added below:
尽管与问题无关,@camickr 引用的
JLayeredPane
示例 承认了以下改编,其中强调了mouseReleased()
对现有组件的影响。Although tangential to the question, the
JLayeredPane
example cited by @camickr admits the following adaptation, which highlights the effect ofmouseReleased()
over an existing component.除了已经提供的指向 LayerPane 示例的指针之外,原始代码的问题集中在标签的首选大小的设置上。您在 JLabel 调整大小之前设置它,因此您的:
无效。另一方面,如果您在调用
setBounds
之后进行该调用,您将看到所需的结果。考虑到这一点,重新排序:看起来像这样:
Besides the pointers to the LayerPane examples already provided, the issue with your original code centers around the setting of the preferred size of your label. You set it before the JLabel has been sized, so your:
is ineffectual. If, on the other hand, you make that call after you make your call to
setBounds
, you will see your desired results. With that in mind, reorder this:to look like this:
因为我很长时间以来一直关注 Romain Guy 在 Swing 上的博客。我有一个您可能感兴趣的链接。他发布了源代码 - 使用 GlassPane 实现 DnD 效果。
http://jroller.com/gfx/entry/drag_and_drop_effects_the
我自己从来没有使用过碳酸饮料DnD 上的动画/效果,因此无法进一步评论:-|
Since I had been following Romain Guy's blogs on Swing for a long time. I have a link that you might be interested in. He released the source - which used a GlassPane for DnD effects.
http://jroller.com/gfx/entry/drag_and_drop_effects_the
I myself never did use a fizzy animation/effect on DnD, so can't comment any further :-|