2012-04-10 3 views
2

Моя программа включает в себя рисование треугольников, где я их нажимаю.Преобразование координат мыши в соответствии с масштабным коэффициентом - java swing

Существует два класса, класс Ecad и Line. Ecad - основной кадр, а класс Line - для рисования линий.

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 
import java.util.*; 
public class Ecad extends JFrame implements MouseListener{ 
    ArrayList<Line2> lines=new ArrayList(); 
    public Ecad(){ 
     this.setVisible(true); 
     this.setSize(600,400); 
     this.addMouseListener(this); 
    } 
    public void mouseReleased(MouseEvent me){ 
     Point p1,p2,p3; 
     int X=me.getX(); 
     int Y=me.getY(); 
     p1=new Point(X,Y);              
     p2=new Point((int)(p1.getX()-100),(int)(p1.getY()+(1.732/2*200))); 
     p3=new Point((int)(p1.getX()+100),(int)(p1.getY()+(1.732/2*200)));           
     Line2 l1=new Line2(p2,p1); 
     Line2 l2=new Line2(p1,p3); 
     Line2 l3=new Line2(p2,p3); 
     lines.add(l1); 
     lines.add(l2); 
     lines.add(l3); 
     this.repaint(); 
    } 
    public void mouseClicked(MouseEvent me){ 

    } 
    public void mouseExited(MouseEvent me){ 

    } 
    public void mouseEntered(MouseEvent me){ 

    } 
    public void mousePressed(MouseEvent me){ 
    } 
    public void mouseMoved(MouseEvent me){ 

    } 
    public static void main(String args[]){ 
     new Ecad(); 
    } 
    public void paint(Graphics g){ 
     Graphics2D g2=(Graphics2D)g; 
     super.paintComponents(g2); 
     //g2.scale(0.5, 0.5); 
     for(final Line2 r:lines){ 
      r.paint((Graphics2D)g2); 
     } 
    } 
} 

Это линия класс

import java.awt.*; 
public class Line2 { 
    Point start,end; 
    public Line2(Point a,Point b){  
     start=a; 
     end=b; 
    } 
    public void paint(Graphics2D g){ 
     g.drawLine((int)start.getX(),(int)start.getY(),(int)end.getX(),(int)end.getY()); 
    } 

} 

В краске Класс ECAD (в) метод, если я использовать параметр масштаба, чтобы увеличить или уменьшить масштаб, мышь координаты не трансформируются. Поэтому после того, как он будет увеличен, если я нажму на одну точку, треугольник будет помещен в какую-то другую точку. Есть ли способ преобразовать координаты мыши, когда я масштабирую компонент Graphics?

+0

Не уверен в вашей главной проблеме, но ваш рисунок не прав. Вы не должны рисовать непосредственно в методе 'paint (...)' JFrame, а скорее в методе 'paintComponent (...)' JComponent (или дочернем компоненте JComponent, таком как JPanel). Тогда вы бы назвали истинный метод супер. Я не уверен, почему вы вызываете 'super.paintComponents (...)'. –

+0

Я не рисовал JFrame в своей реальной программе. Я сделал это в JPanel. Я хочу сосредоточиться на этой проблеме масштабирования, поэтому пропустил создание JPanel в этом примере. Когда я нажимаю мышь в нормальном масштабе, треугольник попадает туда, куда я хочу. Но если я установил шкалу в 0.5, треугольник не будет помещен туда, где я нажимаю. Попробуйте запустить программу, устанавливая различные масштабные коэффициенты. У тебя будет идея. –

+0

Вам нужно использовать небольшую простую геометрию для перевода объекта Graphics2D для каждой формы треугольника на основе шкалы и фиксированной точки (здесь вершина треугольника). –

ответ

2

Опять же, вы должны перевести фигуру, которую вы рисуете, используя масштаб и неподвижную точку (опять же, кажется, что неподвижная точка каждой фигуры будет вершиной треугольника, но это может быть центр должен вы так решаете. Перевод основан на простых геометрических принципах и будет фиксированным (x - 1) шкалой), а также для перевода y.

Например (и в этом случае используется JPanel as ваш пример выше должен):

import javax.swing.*; 
import javax.swing.event.*; 
import java.awt.*; 
import java.awt.event.*; 
import java.awt.geom.*; 
import java.util.*; 
import java.util.List; 

class EcadB extends JPanel { 
    private static final int PREF_W = 800; 
    private static final int PREF_H = 600; 
    private List<MyShape> myShapes = new ArrayList<MyShape>(); 
    private double scale = 1.0; 
    private JSlider slider = new JSlider(0, 200, 100); 

    public EcadB() { 
     addMouseListener(new MyMouseAdapter()); 
     setLayout(new BorderLayout()); 

     slider.setOpaque(false); 
     slider.setMajorTickSpacing(20); 
     slider.setMinorTickSpacing(10); 
     slider.setPaintLabels(true); 
     slider.setPaintTicks(true); 
     slider.addChangeListener(new SliderChangeListener()); 
     add(slider, BorderLayout.SOUTH); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D) g; 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
      RenderingHints.VALUE_ANTIALIAS_ON); 
     Graphics2D g2b = (Graphics2D)g2.create(); 
     g2b.scale(scale, scale); 
     for (MyShape myShape : myShapes) { 
     myShape.draw(g2b, scale); 
     } 
     g2b.dispose(); 
    } 

    public void setScale(double scale) { 
     this.scale = scale; 
     repaint(); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(PREF_W, PREF_H); 
    } 

    private class MyMouseAdapter extends MouseAdapter { 
     @Override 
     public void mousePressed(MouseEvent e) { 
     Point2D p1 = e.getPoint(); 
     Point2D p2 = new Point((int) (p1.getX() - 100), 
       (int) (p1.getY() + (1.732/2 * 200))); 
     Point2D p3 = new Point((int) (p1.getX() + 100), 
       (int) (p1.getY() + (1.732/2 * 200))); 
     Path2D path = new Path2D.Double(); 
     path.moveTo(p1.getX(), p1.getY()); 
     path.lineTo(p2.getX(), p2.getY()); 
     path.lineTo(p3.getX(), p3.getY()); 
     path.lineTo(p1.getX(), p1.getY()); 

     myShapes.add(new MyShape(path, p1)); 
     repaint(); 
     } 
    } 

    private class SliderChangeListener implements ChangeListener { 
     @Override 
     public void stateChanged(ChangeEvent arg0) { 
     double value = slider.getValue()/100.0; 
     setScale(value); 
     } 
    } 

    public static void main(String args[]) { 
     // new Ecad(); 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      EcadB ecadB = new EcadB(); 
      JFrame frame = new JFrame("Scale"); 
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      frame.getContentPane().add(ecadB); 
      frame.pack(); 
      frame.setLocationRelativeTo(null); 
      frame.setVisible(true); 
     } 
     }); 
    } 
} 

class MyShape { 
    Shape shape; 
    Point2D fixedPoint; 

    public MyShape(Shape shape, Point2D fixedPoint) { 
     this.shape = shape; 
     this.fixedPoint = fixedPoint; 
    } 

    public void draw(Graphics2D g2, double scale) { 
     Graphics2D g2b = (Graphics2D) g2.create(); 
     double tx = fixedPoint.getX() * (1.0 - scale)/scale; 
     double ty = fixedPoint.getY() * (1.0 - scale)/scale; 
     g2b.translate(tx, ty); 
     g2b.draw(shape); 
     g2b.dispose(); 
    } 
} 

Обратите внимание, что я делаю копии моих графического объекта, прежде чем превращать их так, чтобы не иметь пла nsform влияет на другие объекты, которые могут быть нарисованы объектом Graphic. Например, если вы избавитесь от копии Graphics2D, которую я использую в методе JPANEL paintComponent(...), вы обнаружите, что JSlider получает масштабирование со всем остальным.

+0

Спасибо! Эта идея работает, но я немного изменил геометрические вычисления. Но другая проблема заключается в том, что я создаю JLabels в концах треугольника и использую mouseListener для метки. Поскольку чертежи смещены из-за масштаба, i не может получить события мыши для меток. Как мы можем это исправить? И если я добавлю JScrollPane, он тоже не обновит полосу прокрутки. –

+0

@SivaSubramaniam: давайте не будем слишком перекладывать требования, и я думаю, что ваш вопрос выше должен быть для вашего следующего вопроса о переполнении стека, поскольку я думаю, что это сообщение выше ответил на ваш оригинальный вопрос достаточно подробно и с достаточным усилием. –

+0

Спасибо, брат !! Я постараюсь работать над этим! –

Смежные вопросы