我正在尝试设置在Jlabels网格上拖动图像。 它工作正常,但图像“清爽”,有时落后于鼠标。
有没有办法改善这一点并使图像完全“平滑”运动?
编辑:好了,感谢Andrew Thompson的建议我将paint()方法更新为paintComponent()。但是现在为什么我拖动它时我的组件会消失?我可能在这里遗漏了一些东西......
EDIT2:为什么会出现以下行为:使用paint()方法时,组件显示在JLabel的顶部。但是当使用paintComponent()时,组件消失被不透明的Jlabels掩盖?
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;
public class DragNDrop {
public static void main(String[] args)
{
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(new DragPanel());
f.pack();
f.setLocation(200,200);
f.setVisible(true);
}
}
class DragPanel extends JPanel {
JLabel[][] labels;
SelectableAction action;
Image image;
Point p;
public DragPanel()
{
p = new Point();
setOpaque(true);
createLabels();
action = new SelectableAction(this);
addMouseListener(action);
addMouseMotionListener(action);
}
private void createLabels() {
labels = new JLabel[8][8];
Dimension dim50 = new Dimension(50,50);
GridBagConstraints gbc = new GridBagConstraints();
this.setLayout(new GridBagLayout());
for (int x=0;x<8;x++){
for (int y=0;y<8;y++){
labels[x][y] = new JLabel();
labels[x][y].setOpaque(true);
labels[x][y].setPreferredSize(dim50);
String str = new String("("+x+","+y+")");
labels[x][y].setText(str);
if ((x+y) % 2 == 0){
labels[x][y].setBackground(Color.lightGray);
} else
{
labels[x][y].setBackground(Color.white);
}
gbc.gridx = x;
gbc.gridy = 7-y;
this.add(labels[x][y],gbc);
}
URL url = getClass().getResource("images/50px-Knight.pgn");
Image img;
try {
img = ImageIO.read(url);
labels[0][0].setIcon(new ImageIcon(img));
} catch (IOException e) {
e.printStackTrace();
}
}
}
public JLabel[][] getLabels()
{
return labels;
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if(action.dragging)
g.drawImage(image, p.x, p.y, this);
}
public void setImage(Image i)
{
image = i;
}
public void setOrigin(Point p)
{
this.p = p;
repaint();
}
}
/**
* Mouse code to enable image dragging
*/
class SelectableAction extends MouseInputAdapter
{
DragPanel MyPanel;
Image selectedImage;
boolean dragging;
Rectangle r;
Point offset;
public SelectableAction(DragPanel dp)
{
MyPanel = dp;
dragging = false;
offset = new Point();
}
public void mousePressed(MouseEvent e)
{
Point p = e.getPoint();
JLabel[][] labels = MyPanel.getLabels();
for(int i = 0; i < labels.length; i++)
{
for (int j=0;j<labels[0].length;j++){
r = labels[i][j].getBounds();
if(r.contains(p))
{
if ( ((ImageIcon)labels[i][j].getIcon()).getImage() != null) {
selectedImage = ((ImageIcon)labels[i][j].getIcon()).getImage();
MyPanel.setImage(selectedImage);
labels[i][j].setIcon(null);
offset.x = p.x - r.x;
offset.y = p.y - r.y;
dragging = true;
MyPanel.setOrigin(new Point(r.x, r.y));
break;
}
}
}
}
}
public void mouseReleased(MouseEvent e)
{
Point p = e.getPoint();
JLabel[][] labels = MyPanel.getLabels();
for(int i = 0; i < labels.length; i++)
{
for (int j=0;j<labels[0].length; j++){
r = labels[i][j].getBounds();
if(r.contains(p)) {
ImageIcon tmpIcon = new ImageIcon(selectedImage);
labels[i][j].setIcon(tmpIcon);
MyPanel.repaint();
dragging = false;
}
}
}
}
public void mouseDragged(MouseEvent e)
{
if(dragging)
{
r.x = e.getX() - offset.x;
r.y = e.getY() - offset.y;
MyPanel.setOrigin(new Point(r.x, r.y));
}
}
}
答案 0 :(得分:3)
+1给AndrewThompson和GuillaumePolet评论。特别是:
它消失了,因为你有不透明的儿童组件画画 自己在上面。
要克服此问题,我们不需要/想要覆盖paintComponent(..)
,而是要覆盖paintChildren(..)
并调用super.paintChildren(..)
,然后调用我们的自定义代码。因此,所有组件都将在调用super
时绘制,我们的图像将在之后绘制,从而使其显示/可见于所有其他组件之上。
使用以下代码替换被覆盖的paintComponent
,它将起作用:
@Override
protected void paintChildren(Graphics g) {
super.paintChildren(g);
if (action.dragging) {
g.drawImage(image, p.x, p.y, null);//also notice i use null and not this, unless the class you are using extends ImageObserver no need for this
}
}