Java Swing Проблемы с перемещением изображения, вставленного смещением
Вступление
Мне нужно переместить изображение в JtextPane, уловка 22 в том, что изображение не рисуется напрямую методом JTextPane paintComponent(), а вставляется через DefaultStyledDocument. Другими словами, моя проблема не похожа на это, но она почти похожа на перемещение или перемещение строки. Границы строки могут быть возвращены в виде прямоугольника, но как можно переместить прямоугольник с помощью мыши, чтобы фактически переместить строку? Как может показаться прямым ответом на перемещение прямоугольника, метод setbounds() печально известен тем, что не работаетдаже после установки макета как нулевого!! Даже setFrame,setSize и setLocation отказывались работать...!! не уверен, что делаю не так.
Постановка задачи: мне нужен способ синхронизации точек пикселей на VIEW (JTextPane) и смещения в MODEL (DefaultStyledDocument), чтобы включить репозицию при перетаскивании мышью.
Неудачное решение: я попытался переместить изображение / форму, выполнив итерацию VIEW, ища дочерние виды, чтобы получить их границы, и используя setBounds (или setLocation/setFrame), чтобы переместить или изменить положение не работает.
Код: изображение / форма - это элемент в структуре документа, помещенный методом DefaultStyledDocument initShape () через ElementSpec и помещенный в VIEW (JTextPane) с помощью смещения. В этом примере это прямоугольник. Для помощи создается getChildBounds() итерируйте по дочерним представлениям и получите их границы в VIEW (JTextPane), которые должны помочь установить представление в новом месте.
Вопрос: как эффективно получить getbounds() VIEW и переместить его в другое место, предпочтительно с помощью функции перетаскивания мышью?
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JTextPane;
import javax.swing.plaf.TextUI;
import javax.swing.text.AbstractDocument;
import static javax.swing.text.AbstractDocument.ElementNameAttribute;
import javax.swing.text.BadLocationException;
import javax.swing.text.BoxView;
import javax.swing.text.ComponentView;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Element;
import javax.swing.text.IconView;
import javax.swing.text.LabelView;
import javax.swing.text.ParagraphView;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
public class ModelViewSynch extends StyledEditorKit{
public static SynchPane tp = new SynchPane();
SynchDoc docc = new SynchDoc();
public ViewFactory getViewFactory() {
return new SynchFactory();
}
static class SynchFactory implements ViewFactory {
public View create(Element elem) {
String kind = elem.getName();
if (kind != null) {
if (kind.equals(AbstractDocument.ContentElementName)) {
return new LabelView(elem);
} else if (kind.equals(AbstractDocument.ParagraphElementName)) {
return new ParagraphView(elem);
} else if (kind.equals(AbstractDocument.SectionElementName)) {
return new BoxView(elem, View.Y_AXIS);
} else if (kind.equals(StyleConstants.ComponentElementName)) {
return new ComponentView(elem);
} else if (kind.equals(StyleConstants.IconElementName)) {
return new IconView(elem);
} else if (kind.equals(SynchDoc.ELEMENT_NAME_SHAPE)) {
return new OffsetShapeView(elem, View.Y_AXIS);
}
}
return new LabelView(elem);
}
}
static class OffsetShapeView extends BoxView{
//Rectangle rectShape;
public OffsetShapeView(Element elem, int axis) {
super(elem,View.Y_AXIS );
}
@Override
protected void paintChild(Graphics g, Rectangle alloc, int index) {
super.paintChild(g, alloc, index);
//rectShape = new Rectangle(10,10,100,100);
g.setColor(Color.red);
g.fillRect(50,50,100,100);
}
}
public static void main(String[] args) {
ModelViewSynch mv = new ModelViewSynch();
mv.editorKitInit();
}
public void editorKitInit(){
JFrame frame = new JFrame();
tp.setEditorKit(this);
tp.setDocument(docc);
tp.addMouseListener(tp);
tp.addMouseMotionListener(tp);
frame.getContentPane().add(tp);
initShapeDemo();
tp.getChildBounds();
frame.setVisible(true);
frame.setSize(500,500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void initShapeDemo(){
//SynchDoc doc = (SynchDoc) tp.getDocument();
SynchDoc doc = (SynchDoc) tp.getDocument();
doc.insertShape(0,10,10);
}
}
class SynchDoc extends DefaultStyledDocument{
public static String ELEMENT_NAME_SHAPE = "Shape";
public static String SHAPE_WIDTH = "Shape_Width";
int shapeWidth = 10;
public SynchDoc(){}
public void insertShape(int offset,int len,int wid){
try {
SimpleAttributeSet attrs = new SimpleAttributeSet();
ArrayList shapeSpecs = new ArrayList();
shapeSpecs.add(new DefaultStyledDocument.ElementSpec(attrs, DefaultStyledDocument.ElementSpec.EndTagType));
SimpleAttributeSet shapeAttrs = new SimpleAttributeSet();
shapeAttrs.addAttribute(ElementNameAttribute, ELEMENT_NAME_SHAPE);
//shapeAttrs.addAttribute(SHAPE_WIDTH,shapeWidth);
DefaultStyledDocument.ElementSpec shapeStart = new DefaultStyledDocument.ElementSpec(shapeAttrs, DefaultStyledDocument.ElementSpec.StartTagType);
shapeSpecs.add(shapeStart);
//Style shape = this.addStyle("image",null);
//SimpleAttributeSet shape = new SimpleAttributeSet();
//ImageIcon icon = new ImageIcon(getClass().getResource("/modelviewsynch/img.png"));
//StyleConstants.setIcon(shape,icon);
//insertString(this.getLength()," ",this.getStyle("image"));
DefaultStyledDocument.ElementSpec shapeContent = new DefaultStyledDocument.ElementSpec(new SimpleAttributeSet(), DefaultStyledDocument.ElementSpec.ContentType," ".toCharArray(), 0, 1);
shapeSpecs.add(shapeContent);
DefaultStyledDocument.ElementSpec shapeEnd = new DefaultStyledDocument.ElementSpec(shapeAttrs, DefaultStyledDocument.ElementSpec.EndTagType);
shapeSpecs.add(shapeEnd);
shapeSpecs.add(new DefaultStyledDocument.ElementSpec(attrs, DefaultStyledDocument.ElementSpec.StartTagType));
DefaultStyledDocument.ElementSpec[] spec = new DefaultStyledDocument.ElementSpec[shapeSpecs.size()];
shapeSpecs.toArray(spec);
this.insert(offset, spec);
}
catch (BadLocationException ex) {
ex.printStackTrace();
}
}
}
class SynchPane extends JTextPane implements MouseListener,MouseMotionListener{
Shape alloc;
public SynchPane(){
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseDragged(MouseEvent e) {
int x = e.getX();
int y = e.getY();
//reposition shape image by the dragging mouse
}
@Override
public void mouseMoved(MouseEvent e) {
}
public Rectangle getChildBounds(){
View view = this.getUI().getRootView(this);
String name = view.getClass().getName();
int start = view.getStartOffset();
int end = view.getEndOffset();
int viewCount = view.getViewCount();
System.out.println("View name: "+name+" Start Offset: "+start+" End Offset: "+end+" No of Children: "+viewCount);
System.out.println("-------------------------------------------------------------------------------------------");
if(viewCount>0){
for(int i = 0; i < viewCount; i++){
//int i = vParent.getViewIndex(v.getStartOffset(), Position.Bias.Forward);
alloc = view.getChildAllocation(i, new Rectangle(0,0, Short.MAX_VALUE, Short.MAX_VALUE));
System.out.println("Child View Bounds: Rectangle ("+alloc.getBounds().x+","+alloc.getBounds().y+
","+alloc.getBounds().width+","+alloc.getBounds().height+")");
System.out.println(".........................................................");
}
}
return new Rectangle(alloc.getBounds().x,alloc.getBounds().y,alloc.getBounds().x,alloc.getBounds().x);
}
}