2016-04-04 7 views
3

Ich schreibe gerade an einem kleinen "Paint" -Programm von mir; Bisher können Sie mit einem Stift darauf zeichnen, bis zu 100-fach vergrößern und eine Farbe wählen. Das nächste, was ich hinzufügen wollte, war (oder ist) die Möglichkeit, die JPanel-Unterklasse, auf der das zu bearbeitende Bild gezeichnet wird, zu ziehen. Wenn Sie die rechte Maustaste gedrückt halten, ändern Sie den Speicherort der JPanel-Unterklasse, die sich auf einem JInternalFrame befindet. Ich habe ein Codebeispiel, das alleine gut funktionieren sollte; zumindest tut es für mich. Um das Problem zu replizieren, starten Sie einfach die DragPanelTest Klasse und ziehen Sie Ihre Maus über die Komponente mit dem roten Rand - das Panel wird nicht sanft gezogen, sondern springt ständig hin und her.JPanel-Unterklasse "springt herum", wenn sie gezogen wird

Code:

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Point; 
import java.awt.Toolkit; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 
import java.awt.event.MouseMotionListener; 

import javax.swing.BorderFactory; 
import javax.swing.JDesktopPane; 
import javax.swing.JFrame; 
import javax.swing.JInternalFrame; 
import javax.swing.JPanel; 

@SuppressWarnings("serial") 
public class DragPanelTest extends JPanel implements MouseMotionListener, MouseListener { 
    Point oldDragPt; 
    boolean dragEnabled; 
    int newX; 
    int newY; 

    public static void main(String[] args) { 
     System.out.println("Launching Test.java ..."); 

     JFrame frame = new JFrame("Title"); 
     JInternalFrame intFrame = new JInternalFrame("title", true, true, true, true); 
     JDesktopPane deskPane = new JDesktopPane(); 
     DragPanelTest dragPanel = new DragPanelTest(); 

     frame.setSize(300, 300);; 
     frame.setLayout(null); 
     frame.setVisible(true); 
     Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); 
     int x = (d.width - frame.getWidth())/2; 
     int y = (d.height - frame.getHeight())/2; 
     frame.setLocation(x, y); 

     deskPane.setBounds(50, 50, 200, 200); 
     deskPane.setBorder(BorderFactory.createLineBorder(Color.BLACK)); 
     frame.add(deskPane); 


     deskPane.add(intFrame); 
     intFrame.setSize(150, 150); 
     intFrame.add(dragPanel); 
     intFrame.setVisible(true); 
    } 

    public DragPanelTest() { 
     this.setSize(100,100); 
     this.setBorder(BorderFactory.createLineBorder(Color.RED)); 
     this.addMouseListener(this); 
     this.addMouseMotionListener(this); 
    } 

    public void mousePressed(MouseEvent e) { 
     if (e.isMetaDown()) { 
      dragEnabled = true; 
      oldDragPt = new Point((int) this.getMousePosition().getX(), (int) this.getMousePosition().getY()); 
     } 
     repaint(); 
    } 

    public void mouseReleased(MouseEvent e) { 
     dragEnabled = false; 
     oldDragPt = null; 
    } 

    public void mouseDragged(MouseEvent e) { 
     if (e.isMetaDown() && this.getMousePosition() != null) { 
      if (oldDragPt != null) { 
       if (dragEnabled) { 
        int mouseX = (int) this.getMousePosition().getX(); 
        int mouseY = (int) this.getMousePosition().getY(); 
        int x = this.getX(); 
        int y = this.getY(); 
        int diffX = (mouseX - (int) oldDragPt.getX()); 
        int diffY = (mouseY - (int) oldDragPt.getY()); 
        newX = getX() + diffX; 
        newY = getY() + diffY; 
        this.setLocation(newX, newY); 
        this.repaint(); 
        oldDragPt = new Point(mouseX, mouseY); 
       } 
      } else { 
       oldDragPt = new Point((int) this.getMousePosition().getX(), (int) this.getMousePosition().getY()); 
      } 
     } 
    } 

    public void mouseClicked(MouseEvent e) {} 
    public void mouseEntered(MouseEvent e) {} 
    public void mouseExited(MouseEvent e) {} 
    public void mouseMoved(MouseEvent e) {} 
} 

Bitte beachte, dass ich einige System.out.println() oder @Override Befehle den Code ein wenig zu verkürzen, weggelassen.

Jedenfalls, wenn jemand weiß, was ich falsch mache/was ich verbessern soll, wäre ich sehr dankbar!

+1

Der Grund es herumspringen ist wegen 'getMousePosition'. Das ist relativ zur aktuellen Komponente, aber da sich diese Komponente bewegt, beeinflusst sie, wo der Code denkt, dass die Maus das letzte Mal war. – resueman

Antwort

6

Das Panel wird nicht reibungslos gezogen, sondern springt ständig hin und her.

Wenn Sie springen, weil die relativen Bewegungen zwischen der Maus und der Komponente und dem übergeordneten Panel ausgeschaltet ist. Ihr Code ist zu kompliziert, um auf die genaue Linie hinzuweisen, die das Problem verursacht.

Der Basiscode für eine Komponente um einen Panel ziehen ist:

public class DragListener extends MouseInputAdapter 
{ 
    Point location; 
    MouseEvent pressed; 

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

    public void mouseDragged(MouseEvent me) 
    { 
     Component component = me.getComponent(); 
     location = component.getLocation(location); 
     int x = location.x - pressed.getX() + me.getX(); 
     int y = location.y - pressed.getY() + me.getY(); 
     component.setLocation(x, y); 
    } 
} 

Für fortgeschrittenere Code mit mehr Funktion, die Sie auch in Moving Windows gefunden Component Mover Klasse überprüfen können.

0

Ich hatte ein ähnliches Problem mit dem Verschieben des Ansichtsfensters für eine Bildlaufleiste. Ich denke, dass wenn eine Komponente neu positioniert wird, der Wert des gespeicherten Punkts relativ zum ursprünglichen Speicherort ist und in Bezug auf den neuen Speicherort falsch ist. Meine Lösung, die mir unlogisch erscheint, ließ den Ziehvorgang reibungslos ablaufen. Was ich getan habe, ist, das Punktdelta zurück in den gespeicherten Ort hinzuzufügen.

Dies ist der grundlegende Code das Ansichtsfenster ziehen:

Point priorPanPoint; 

public void mouseDragged(MouseEvent e) { 
    Point newPt = subtractPoints(priorPanPoint, e.getPoint()); 
    priorPanPoint = addPoints(e.getPoint(), newPt); 
    newPt = addPoints(getVisibleRect().getLocation(), newPt); 
    viewport.setViewPosition(newPt); 
} 

public void mousePressed(MouseEvent e) { 
    priorPanPoint = e.getPoint(); 
} 

private Point addPoints(Point p1, Point p2) { 
    return new Point(p1.x + p2.x, p1.y + p2.y); } 

private Point subtractPoints(Point p1, Point p2) { 
    return new Point(p1.x - p2.x, p1.y - p2.y); 
} 
Verwandte Themen