2016-02-13 21 views
0

对于我的二叉树程序,我一直使用JTextFields作为节点,并且当我点击左键并选择两个JTextFields,它会在它们之间画一条线。问题是,如果我想拖动JtextField,我希望该行在JTextField的两个中点之间。我不知道只使用paintComponent是否可能。我确实尝试过,但它就像一个一次性的东西,它会留下所有先前画出的线条的痕迹。 这里是目前为止的代码,还有其他类,所以有些位不起作用。该代码已被调试一下以及测试。使用paintComponent绘制和拖拽线条,而不会与JPanel中的任何其他GUI组件冲突

公共类BinaryTreeMainPnl扩展JPanel {

public static Graphics g1; 
public int Width = 75; 
public int Height = 45; 
public String tempNode1 = ""; 
public int tempNode1Pos = 0; 
public int tempNode2Pos = 0; 
public String tempNode2 = ""; 
public static boolean leftBtnSelected; 
public static boolean rightBtnSelected; 
private static int x1, y1 = 50; 
private static int x2, y2 = 500; 

JToggleButton leftBtn = new JToggleButton("Left"); 
JToggleButton rightBtn = new JToggleButton("Right"); 
JTextField[] myArray = new JTextField[60]; 
ArrayList<String> nodeNames = new ArrayList<String>(); 
JFrame MainFrame; 
JTextField txtFld1 = new JTextField("Enter Questions here"); 
JButton btn1 = new JButton("Submit"); 

public BinaryTreeMainPnl(JFrame frame) { 
    super(); 

    setSize(800, 700); 
    MainFrame = frame; 
    readInput(); 
    leftBtn.setFont(new Font("Arial", Font.BOLD, 15)); 
    leftBtn.setForeground(Color.blue); 
    leftBtn.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent evt) { 
      rightBtn.setSelected(false); 
      leftBtnSelected = leftBtn.getModel().isSelected(); 
      rightBtnSelected = false; 

      System.out.println(leftBtnSelected); 
      System.out.println(rightBtnSelected); 
     } 
    }); 
    add(leftBtn); 

    rightBtn.setFont(new Font("Arial", Font.BOLD, 15)); 
    rightBtn.setForeground(Color.green); 
    rightBtn.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent evt) { 
      leftBtn.setSelected(false); 
      rightBtnSelected = rightBtn.getModel().isSelected(); 
      leftBtnSelected = false; 
      System.out.println(leftBtnSelected); 
      System.out.println(rightBtnSelected); 
     } 
    }); 
    add(rightBtn); 

} 

@Override 
public void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    updateLine(g); 

} 

public void readInput() { 
    btn1.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent evt) { 
      identifyNodeNames(txtFld1.getText()); 
      displayNodes(nodeNames); 
      new TreeSorting().treeSort(nodeNames); 
     } 
    }); 
    this.add(txtFld1); 
    this.add(btn1); 

} 

public void displayNodes(ArrayList<String> nodeNames) { 

    for (int i = 0; i < nodeNames.size(); i++) { 
     String currentSetText = nodeNames.get(i); 
     myArray[i] = new JTextField(currentSetText); 
     myArray[i].setEditable(false); 
    } 

    for (int i = 0; i < nodeNames.size(); i++) { 
     int I = i; 
     myArray[I].addMouseMotionListener(new MouseAdapter() { 

      @Override 
      public void mouseDragged(MouseEvent evt) { 

       int x = evt.getX() + myArray[I].getX(); 
       int y = evt.getY() + myArray[I].getY(); 
       myArray[I].setBounds(x, y, myArray[I].getWidth(), myArray[I].getWidth()); 
       System.out.println(myArray[I] + "dragged"); 

      } 

     }); 
     myArray[I].addMouseListener(new MouseAdapter() { 

      @Override 

      public void mouseClicked(MouseEvent evt) { 
       if (leftBtnSelected) { 
        if (tempNode1.equals("")) { 
         tempNode1 = myArray[I].getText(); 
         System.out.println(tempNode1 + "clicked"); 
        } else { 
         tempNode2 = myArray[I].getText(); 
         System.out.println(tempNode2 + "Clicked as well"); 
         leftBtn.setSelected(false); 
         leftBtnSelected = false; 
         x1 = 40; 
         y1 = 40; 
         x2 = 400; 
         y2 = 400; 
         updateLine(g1); 
         System.out.println("asdasd"); 

        } 
       } 
       if (rightBtnSelected) { 

       } 
      } 

      public void moveComponent(MouseEvent evt) { 

      } 
     }); 
     System.out.println("I " + I); 
     System.out.println(myArray[I].getText()); 

     add(myArray[I]); 
    } 
    MainFrame.revalidate(); 

} 

public int findMidPoint(JTextField temp) { 
    Point p = temp.getLocation(); 
    Dimension d = temp.getSize(); 
    return p.x + (d.width)/2; 

} 
int coun = 0; 

public void updateLine(Graphics g) { 
    g.drawLine(x1, x2, y1, y2); 
    x1 = x1 + 10; 
    y1 = y1 + 10; 
    y2 = y2 + 10; 
    x2 = x2 + 10; 
    System.out.println("Line Updated" + coun); 
    coun++; 
} 

public void identifyNodeNames(String answer) { 
    int arrayCounter = 0; 
    int lastNodePosition = 0; 
    for (int i = 0; i < answer.length(); i++) { 
     char c = answer.charAt(i); 
     if (c == ',') { 
      nodeNames.add(arrayCounter, answer.substring(lastNodePosition, i + 1).replaceAll(",", "").replaceAll(" ", "")); 
      lastNodePosition = i + 1; 
      arrayCounter++; 
     } 

     if (i == answer.length() - 1) { 
      nodeNames.add(arrayCounter, answer.substring(lastNodePosition, answer.length()).replaceAll(" ", "")); 
     } 

    } 

} 

}

进口的java.util.ArrayList;

公共类TreeSorting {

public static int arrayLength; 
String[][] Child; 
String root = ""; 
boolean nodeSorted = false; 
int parentCounter = 1; 

public void treeSort(ArrayList<String> passedQuestions) { 
    // declaring nodes 
    arrayLength = passedQuestions.size(); 
    System.out.println(arrayLength + "ARRAY LENGTH"); 
    Child = new String[arrayLength][3]; 
    for (int i = 0; i < arrayLength; i++) { 
     Child[i][0] = passedQuestions.get(i); 
    } 
    //initially calling the mainprocess with parentCounter 1; 
    root = Child[0][0]; 
    mainProcess(1); 

} 

public void mainProcess(int parentCounter) { 

    if (parentCounter < Child.length) { 
     System.out.println(parentCounter); 
     sortingTree(Child[parentCounter][0], root, 0); //where the next node is passed on the tree is sorted recursively 
     for (int i = 0; i < Child.length; i++) { 
      System.out.println(Child[i][0]); 
      System.out.println(Child[i][1] + "," + Child[i][2]); 
     } 

    } 
} 

public void sortingTree(String CurrentNode, String PreviousNode, int PreviousPosition) { 
    nodeSorted = false;// node is not sorted in the beginning 
    if (isAfter(CurrentNode.toLowerCase(), PreviousNode.toLowerCase())) { 
     System.out.println(Child[PreviousPosition][2]); 
     if (Child[PreviousPosition][2] == null) { //checks if the right of the node is empty, if found empty the node is placed there. 
      Child[PreviousPosition][2] = CurrentNode; 
      nodeSorted = true; // if the node finds a position in the array node is sorted. 
     } else { 
      sortingTree(CurrentNode, Child[PreviousPosition][2], getPositionInArray(Child[PreviousPosition][2])); 
      //if the array position was not empty, the loop will process again this time with the item found in the filled position. 
     } 
    } else if (Child[PreviousPosition][1] == null) { // if the left of the node is empty, the item will be placed there 
     Child[PreviousPosition][1] = CurrentNode; 
     nodeSorted = true; 
    } else { 
     sortingTree(CurrentNode, Child[PreviousPosition][1], getPositionInArray(Child[PreviousPosition][1])); 
     //if the array position was not empty, the loop will process again this time with the item found in the filled position. 
    } 

    if (nodeSorted) { // if the node finds a position in the array, the nodeCounter increments and the next node in the question is processed. 
     parentCounter++; 
     mainProcess(parentCounter); 
    } 
} 

public int getPositionInArray(String node) { 
    int position = 0; 
    loop: 
    for (int i = 0; i < Child.length; i++) { 
     if (Child[i][0].equals(node)) { 
      position = i; 
      break loop; 

     } 
    } 
    return position; 
} 

public boolean isAfter(String CurrentNode, String PreviousNode) { 
    int loopLength = determineLoopLength(CurrentNode, PreviousNode); 
    boolean result = false; 
    String tempCheck = ""; 
    loop: 
    for (int i = 0; i < loopLength; i++) { 
     if ((int) CurrentNode.charAt(i) > (int) PreviousNode.charAt(i)) { 
      result = true; 
      break loop; 
     } 
     if ((int) CurrentNode.charAt(i) < (int) PreviousNode.charAt(i)) { 
      result = false; 
      break loop; 
     } else if (CurrentNode.charAt(i) == PreviousNode.charAt(i) && CurrentNode.length() > PreviousNode.length()) { 
      System.out.println("I'm here"); 
      tempCheck = tempCheck + CurrentNode.charAt(i) + ""; 
      if (i == loopLength - 1 && tempCheck.equals(PreviousNode)) { 
       result = true; 
       break loop; 
      } 
     } 
    } 
    return result; 
} 

public int determineLoopLength(String CurrentNode, String PreviousNode) { 
    int loopLength = 0; 
    if (CurrentNode.length() < PreviousNode.length()) { 
     loopLength = CurrentNode.length(); 
    } 
    if (PreviousNode.length() < CurrentNode.length()) { 
     loopLength = PreviousNode.length(); 
    } else { 
     loopLength = CurrentNode.length(); 
    } 
    return loopLength; 
} 

}

+3

'“我不知道是否有可能使用只有paintComponent或不。“ - 是的,这是可能的。 ''我确实尝试过,但它就像是一次性的事情,它会留下所有先前画出的线条的踪迹。“ - 如果我们能看到你当前最好的代码尝试,最好在这里发布你的问题作为有效[mcve],而不是链接,我们将能够更好地帮助您弄清楚您可能会做错什么,从而帮助您纠正错误。在此之前,这个问题不会轻易回答。 –

+0

虽然猜测 - 你会想在你自己的覆盖中调用'super.paintComponent(g);'方法,通常作为这个方法中的第一个调用。这将有助于清理包括旧画线的任何“脏”像素。 –

+1

除了Hovercraft的说法之外,您还可以通过点击问题下方的“编辑”链接来提供这样的[MCVE](https://stackoverflow.com/help/mcve)。在您的问题中粘贴一个最小完整和可验证示例,选择代码并按下'{}'按钮以正确格式化代码。 –

回答

3

WTF,这方面的工作,.....

import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.RenderingHints; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class DragMyFields extends JPanel { 
    private static final int PREF_W = 1000; 
    private static final int PREF_H = 800; 
    private static final int COLS = 8; 
    private static final int DELTA_Y = 120; 
    private static final int MAX_DEPTH = 3; 
    private MySimpleTreeNode<JTextField> treeRoot = new MySimpleTreeNode<>(); 
    private MyMouse myMouse = new MyMouse(); 

    public DragMyFields() { 
     setLayout(null); // this is *** BAD *** 
       // much better would be to create a custom layout 

     JTextField field = new JTextField(COLS); 
     field.addMouseListener(myMouse); 
     field.addMouseMotionListener(myMouse); 
     field.setSize(field.getPreferredSize()); 
     int x = (PREF_W - field.getPreferredSize().width)/2; 
     int y = DELTA_Y; 
     field.setLocation(x, y); 
     add(field); 
     treeRoot.setNode(field); 

     recursiveCreateTree(treeRoot, MAX_DEPTH, x, y); 
    } 

    private void recursiveCreateTree(MySimpleTreeNode<JTextField> node, int depth, int x, int y) { 
     if (depth == 0) { 
      return; 
     } 

     JTextField leftField = new JTextField(COLS); 
     JTextField rightField = new JTextField(COLS); 

     MySimpleTreeNode<JTextField> leftNode = new MySimpleTreeNode<>(leftField); 
     MySimpleTreeNode<JTextField> rightNode = new MySimpleTreeNode<>(rightField); 
     node.setLeft(leftNode); 
     node.setRight(rightNode); 

     int multiplier = 4; 
     for (int i = 0; i < MAX_DEPTH - depth; i++) { 
      multiplier *= 2; 
     } 

     int xL = x - getPreferredSize().width/multiplier; 
     int xR = x + getPreferredSize().width/multiplier; 
     y += DELTA_Y; 

     leftField.setSize(leftField.getPreferredSize()); 
     rightField.setSize(rightField.getPreferredSize()); 
     leftField.setLocation(xL, y); 
     rightField.setLocation(xR, y); 
     leftField.addMouseListener(myMouse); 
     leftField.addMouseMotionListener(myMouse); 
     rightField.addMouseListener(myMouse); 
     rightField.addMouseMotionListener(myMouse); 
     add(leftField); 
     add(rightField); 

     recursiveCreateTree(leftNode, depth - 1, xL, y); 
     recursiveCreateTree(rightNode, depth - 1, xR, y); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D) g; 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
     recursiveDraw(g, treeRoot); 
    } 

    private void recursiveDraw(Graphics g, MySimpleTreeNode<JTextField> node) { 
     MySimpleTreeNode<JTextField> left = node.getLeft(); 
     MySimpleTreeNode<JTextField> right = node.getRight(); 

     Point p = getNodeCenter(node); 

     if (left != null) { 
      Point p2 = getNodeCenter(left); 
      g.drawLine(p.x, p.y, p2.x, p2.y); 
      recursiveDraw(g, left); 
     } 
     if (right != null) { 
      Point p2 = getNodeCenter(right); 
      g.drawLine(p.x, p.y, p2.x, p2.y); 
      recursiveDraw(g, right); 
     } 

    } 

    private Point getNodeCenter(MySimpleTreeNode<JTextField> node) { 
     JTextField field = node.getNode(); 
     Point location = field.getLocation(); 
     Dimension size = field.getSize(); 
     return new Point(location.x + size.width/2, location.y + size.height/2); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
      return super.getPreferredSize(); 
     } 
     return new Dimension(PREF_W, PREF_H); 
    } 

    private class MyMouse extends MouseAdapter { 
     Component source = null; 
     private Point pressedP; 
     private Point pressedLoc; 
     private Point parentP; 

     @Override 
     public void mousePressed(MouseEvent e) { 
      if (e.getButton() != MouseEvent.BUTTON1) { 
       return; 
      } 

      source = e.getComponent(); 
      parentP = source.getParent().getLocationOnScreen(); 
      pressedLoc = source.getLocationOnScreen(); 
      pressedP = e.getLocationOnScreen(); 
     } 

     @Override 
     public void mouseReleased(MouseEvent e) { 
      moveComponent(e); 
      source = null; 
      pressedP = null; 
      pressedLoc = null; 
     } 

     @Override 
     public void mouseDragged(MouseEvent e) { 
      if (source == null) { 
       return; 
      } 
      moveComponent(e); 
     } 

     private void moveComponent(MouseEvent e) { 
      Point p = e.getLocationOnScreen(); 
      int x = pressedLoc.x + p.x - pressedP.x - parentP.x; 
      int y = pressedLoc.y + p.y - pressedP.y - parentP.y; 

      Point newP = new Point(x, y); 
      source.setLocation(newP); 
      repaint(); 
     } 
    } 

    private static void createAndShowGui() { 
     DragMyFields mainPanel = new DragMyFields(); 

     JFrame frame = new JFrame("DragMyFields"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> { 
      createAndShowGui(); 
     }); 
    } 
} 

class MySimpleTreeNode<T> { 
    private T node; 
    private MySimpleTreeNode<T> left; 
    private MySimpleTreeNode<T> right; 

    public MySimpleTreeNode() { 
     // default constructor 
    } 

    public MySimpleTreeNode(T node) { 
     this.node = node; 
    } 

    public void setNode(T node) { 
     this.node = node; 
    } 

    public T getNode() { 
     return node; 
    } 

    public MySimpleTreeNode<T> getLeft() { 
     return left; 
    } 

    public void setLeft(MySimpleTreeNode<T> left) { 
     this.left = left; 
    } 

    public MySimpleTreeNode<T> getRight() { 
     return right; 
    } 

    public void setRight(MySimpleTreeNode<T> right) { 
     this.right = right; 
    } 

} 
+0

我可以看到你有你的moveComponent方法来更新节点的位置(JTextFields),但我仍然无法弄清楚你更新线的位置,我只能看到它的绘制位置。你能帮我吗?但是你究竟如何试图做同样的事情呢? –

+0

@CuriousOne:这些线是在由paintComponent调用的递归方法内绘制的,并且基于每个JTextField的计算中心点。递归是通过我的简单树。至于我究竟是怎么做同样的事情 - 我对你的问题很感兴趣,并在现场为这个问题创建了这个问题。 –

+0

换句话说,只有在绘制线条时才会创建线条。这是他们唯一需要的时间,对吧? –

相关问题