gpt4 book ai didi

java - 在使用 mouseDrag 滚动时暂时禁用或阻止重新绘制 JViewPort

转载 作者:行者123 更新时间:2023-11-30 07:00:37 26 4
gpt4 key购买 nike

我已经编写了如下定义的 MouseListener,这样我就可以移动 JButton 来重新排序 JPanel 中的组件。 JPanel 位于 JScrollPane 中,因此当添加多个组件时,它们可以滚动。

我遇到的问题是,当拖动组件并且鼠标离开滚动 Pane /视口(viewport)时,组件将快速回到其在 JPanel 中的位置,然后将绘制在正确的位置.我假设此行为是由于视口(viewport)在我调用 scrollRectToVisible()

时调用其子项的重绘

有什么方法可以防止这种情况发生吗?

请注意,我仅限于 Java 5

监听器

import java.awt.Component;
import java.awt.Container;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import javax.swing.event.MouseInputAdapter;

public class DragListener extends MouseInputAdapter
{
private Point location;
private MouseEvent pressed;
private MouseEvent dragged;
private MouseEvent dropped;

@Override
public void mousePressed(MouseEvent me)
{
pressed = me;
}

@Override
public void mouseDragged(MouseEvent me)
{
dragged = me;
Component component = dragged.getComponent();
Container parent = component.getParent();
Container superParent = parent.getParent();

if(superParent instanceof JViewport)
{
JViewport vp = (JViewport)superParent;
Rectangle vpb = vp.getBounds();
Point pt = MouseInfo.getPointerInfo().getLocation();
SwingUtilities.convertPointFromScreen(pt, vp);

if(!vpb.contains(pt))
{
int yDiff = (pt.y < vpb.y ) ? pt.y : pt.y - vpb.height;
vpb.translate(0, yDiff);
vp.scrollRectToVisible(vpb);
}
}

location = component.getLocation(location);
int x = location.x - pressed.getX() + me.getX();
int y = location.y - pressed.getY() + me.getY();
component.setLocation(x, y);
}

// Mouse release omitted
}

Gui(在 NetBeans 中创建)

import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import javax.swing.JButton;
import javax.swing.JPanel;

public class DragginTest extends javax.swing.JFrame
{
public DragginTest()
{
initComponents();
addListeners(jButton1, jButton2, jButton3, jButton4, jButton5, jButton6, jButton7, jButton8, jButton9);
}

private void addListeners(JButton... buttons)
{
DragListener drag = new DragListener();
for(JButton b : buttons)
{
b.addMouseListener(drag);
b.addMouseMotionListener(drag);
}
}

@SuppressWarnings("unchecked")

private void initComponents()
{
jLayeredPane1 = new javax.swing.JLayeredPane();
jScrollPane1 = new javax.swing.JScrollPane();
mainPanel = new javax.swing.JPanel();
jButton1 = new javax.swing.JButton();
jButton2 = new javax.swing.JButton();
jButton3 = new javax.swing.JButton();
jButton4 = new javax.swing.JButton();
jButton5 = new javax.swing.JButton();
jButton6 = new javax.swing.JButton();
jButton7 = new javax.swing.JButton();
jButton8 = new javax.swing.JButton();
jButton9 = new javax.swing.JButton();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setPreferredSize(new java.awt.Dimension(450, 450));

mainPanel.setLayout(new java.awt.GridLayout(5, 2, 2, 2));

// Below Repeated for buttons 1-9 (left out for conciseness)
jButton1.setFont(new java.awt.Font("Tahoma", 1, 48)); // NOI18N
jButton1.setForeground(new java.awt.Color(255, 0, 0));
jButton1.setText("1");
mainPanel.add(jButton1);
// End Repeat

jScrollPane1.setViewportView(mainPanel);

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(40, 40, 40)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 205, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(38, 38, 38))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(40, 40, 40)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 226, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(53, Short.MAX_VALUE))
);

pack();
}

public static void main(String args[])
{
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable()
{
public void run()
{
new DragginTest().setVisible(true);
}
});
}

private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JButton jButton3;
private javax.swing.JButton jButton4;
private javax.swing.JButton jButton5;
private javax.swing.JButton jButton6;
private javax.swing.JButton jButton7;
private javax.swing.JButton jButton8;
private javax.swing.JButton jButton9;
private javax.swing.JLayeredPane jLayeredPane1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JPanel mainPanel;
}

最佳答案

我在您的 DragListener 代码中添加了一个 hack。基本上它会在您拖动时删除布局管理器,因此重新验证什么都不做,并在释放鼠标时恢复布局管理器:

import java.awt.*;
import java.awt.Container;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import javax.swing.event.MouseInputAdapter;

public class DragListener extends MouseInputAdapter
{
private Point location;
private MouseEvent pressed;
private MouseEvent dragged;
private MouseEvent dropped;
private LayoutManager layout;

@Override
public void mousePressed(MouseEvent me)
{
pressed = me;
Component component = me.getComponent();
Container parent = component.getParent();
parent.setPreferredSize(parent.getPreferredSize());
layout = parent.getLayout();
parent.setLayout(null);
}

@Override
public void mouseDragged(MouseEvent me)
{
dragged = me;
Component component = dragged.getComponent();
Container parent = component.getParent();
Container superParent = parent.getParent();

if(superParent instanceof JViewport)
{
JViewport vp = (JViewport)superParent;
Rectangle vpb = vp.getBounds();
Point pt = MouseInfo.getPointerInfo().getLocation();
SwingUtilities.convertPointFromScreen(pt, vp);

if(!vpb.contains(pt))
{
int yDiff = (pt.y < vpb.y ) ? pt.y : pt.y - vpb.height;
vpb.translate(0, yDiff);
vp.scrollRectToVisible(vpb);
}
}

location = component.getLocation(location);
int x = location.x - pressed.getX() + me.getX();
int y = location.y - pressed.getY() + me.getY();
component.setLocation(x, y);
}

// Mouse release omitted
@Override
public void mouseReleased(MouseEvent me)
{
Component component = me.getComponent();
Container parent = component.getParent();
parent.setPreferredSize( null );
parent.setLayout(layout);
parent.validate();
parent.repaint();
}
}

当然,我假设您的真实 mouseReleased 代码将具有将按钮插入容器中适当位置的逻辑,这样它的真实位置可以由 GridLayout 维护,否则组件将返回到其原始位置。

编辑:

这是一个在释放鼠标按钮时将按钮移动到新位置的版本。有点复杂,因为您需要担心 ZOrder。那就是把一个组件往下拉就可以了。但是,如果您尝试向上拖动一个组件,那么它会被绘制在其他按钮下方。临时重置 ZOrder 可以解决此问题。

男孩,代码开始成为一个大 hack:) 临时空布局和临时 ZOrder。

这里是代码:

import java.awt.*;
import java.awt.Container;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import javax.swing.*;
import javax.swing.SwingUtilities;
import javax.swing.event.MouseInputAdapter;

public class DragListener extends MouseInputAdapter
{
private Point location;
private MouseEvent pressed;
private MouseEvent dragged;
private MouseEvent dropped;
private LayoutManager layout;
private Rectangle originalBounds;
private int originalZOrder;

@Override
public void mousePressed(MouseEvent me)
{
pressed = me;
Component component = me.getComponent();
Container parent = component.getParent();
originalBounds = component.getBounds();
originalZOrder = parent.getComponentZOrder(component);
parent.setPreferredSize(parent.getPreferredSize());
layout = parent.getLayout();
parent.setLayout(null);
parent.setComponentZOrder(component, 0);
}

@Override
public void mouseDragged(MouseEvent me)
{
JComponent source = (JComponent) me.getComponent();
JComponent parent = (JComponent) source.getParent();

Point p = me.getPoint();
p = SwingUtilities.convertPoint(source, p, parent);

Rectangle bounds = source.getBounds();
bounds.setLocation(p);

bounds.x -= pressed.getX();
bounds.y -= pressed.getY();
source.setLocation(0, bounds.y);
parent.scrollRectToVisible(bounds);
}

@Override
public void mouseReleased(MouseEvent me)
{
boolean moved = false;
Component component = me.getComponent();
Container parent = component.getParent();
Point location = component.getLocation();

if (location.y < 0)
{
parent.add(component, 0);
moved = true;
}
else
{
for (int i = 0; i < parent.getComponentCount(); i++)
{
Component c = parent.getComponent(i);
Rectangle bounds = c.getBounds();

if (c == component)
bounds = originalBounds;

// Component is released in the space originally occupied
// by the component or over an existing component

if (bounds.contains(0, location.y))
{
if (c == component)
{
parent.setComponentZOrder(component, originalZOrder);
}
else
{
parent.add(component, i);
}

moved = true;
break;
}
}
}

// Component is positioned below all components in the container

if (!moved)
{
parent.add(component, parent.getComponentCount() - 1);
}

// Restore layout manager

parent.setPreferredSize( null );
parent.setLayout(layout);
parent.validate();
parent.repaint();
component.requestFocusInWindow();
}

private static void createAndShowGUI()
{
JPanel panel = new JPanel( new GridLayout(0, 1) );
DragListener drag = new DragListener();

for (int i = 0; i <10; i++)
{
JButton button = new JButton("" + i);
button.setFont(new java.awt.Font("Tahoma", 1, 48));
button.setForeground(new java.awt.Color(255, 0, 0));
button.addMouseListener(drag);
button.addMouseMotionListener(drag);
panel.add( button );
}

JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new JScrollPane(panel) );
frame.setLocationByPlatform( true );
frame.setSize(200, 400);
frame.setVisible( true );
}

public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}

关于java - 在使用 mouseDrag 滚动时暂时禁用或阻止重新绘制 JViewPort,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30429648/

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