2013-02-08 117 views
-2

我有兩點,我畫了一條線drawline(x1,y1,x2,y2); 我想在這條線上移動一個標籤(在這兩點之間)。如何在兩點之間移動jlabel?

m=y2-y1/x2-x1; 

if(x1<x2) 
    for (int i=x1;i<x2;i++) 
    { 
    label.setbound(i,y1+(x-i)*m,label.getwidth(),label.gethigh()); 
    } 
    else{ 
    for (int i=x1;i<x2;i--) 
    { 
    label.setbound(i,y1+(x-i)*m,label.getwidth(),label.gethigh()); 
    } 
    } 

我使用線程來移動。

//

我問這個問題,因爲我正在寫旅行商問題的代碼,我想移動的東西的路線上,使用線程標籤的改變位置。 例如:drawline(23, 65, 231,124);移動銷售員就行了。

我的IDE是NetBeans和JPanel的佈局設計無

+1

爲什麼和在哪裏需要幫助?什麼是問題(非編譯代碼除外)? – 2013-02-08 22:52:15

+1

標籤是使用佈局管理器連接到的容器嗎?如果沒有,你嘗試重新繪製容器嗎? – MadProgrammer 2013-02-08 22:52:56

+0

發佈代碼的一個問題是,在設置標籤的位置後,您永遠不會睡覺()。由於代碼執行速度如此之快,它看起來就像是從一開始就一直移動到結束位置。 – camickr 2013-02-09 01:50:39

回答

1

有信息很少走,爲什麼你可能會碰到問題上和這麼多的理由的。

下面是我如何解決您的問題的一個簡單示例。請注意 - 我個人不喜歡null佈局,他們與Swing的內部工作方式混淆很多,並傾向於產生更多的問題,然後他們解決。相反,當我想取消佈局管理器時,我使用了JLayeredPane

public class BouncingLabel { 

    public static void main(String[] args) { 
     new BouncingLabel(); 
    } 

    public BouncingLabel() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JLayeredPane { 

     private JLabel label; 
     private Point p; 
     private int dv = 2; 

     public TestPane() { 
      p = new Point(); 
      label = new JLabel("Look Ma, no hands!"); 
      add(label); 

      Timer timer = new Timer(60, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        p.y = (getHeight() - label.getHeight())/2; 
        p.x = p.x + dv; 
        if (p.x + label.getWidth() > getWidth()) { 
         dv *= -1; 
         p.x = getWidth() - label.getWidth() + dv; 
        } else if (p.x < 0) { 
         dv *= -1; 
         p.x = 0 + dv; 
        } 
        label.setLocation(p); 
        repaint(); 
       } 
      }); 
      timer.setRepeats(true); 
      timer.setCoalesce(true); 
      timer.start(); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 100); 
     } 

     @Override 
     public void doLayout() { 
      super.doLayout(); 
      label.setSize(label.getPreferredSize()); 
      label.getLocation(p); 
     } 

    } 

} 

更新

在代碼的仔細檢查,你似乎是違反事件調度線程 - 沒有阻止規則。所有UI更新都保存在單個線程(EDT)中,任何阻止此線程的操作都將阻止EDT將事件分派給所有組件,包括重新繪製請求。

做這樣的事情..

for (int i=x1;i<x2;i++) 
{ 
    label.setbound(i,y1+(x-i)*m,label.getwidth(),label.gethigh()); 
} 

你從調度所需的任何更新事件UI的休息,防止它更新屏幕,直到退出方法停止EDT手段。

查看Concurrency in Swing瞭解更多詳情。

對於某些解決方案,我還會仔細查看How to use Swing TimersSwing Worker

+0

+1,爲定時器顯示動畫。不知道我是否理解了您關於使用JLayeredPane的意見,當您想要取消佈局管理器時。 JLayeredPane確實使用「空佈局」。 JLayeredPane被設計爲包含許多專門的功能,這對於這個問題並不是必需的。所以我會保持簡單,只需使用帶有空佈局的JPanel。 – camickr 2013-02-09 01:49:02

+0

@camickr你可能是對的,在使用空佈局和JLayeredPane似乎工作的時候,我似乎有更新面板的問題...... – MadProgrammer 2013-02-09 02:13:42

+0

不知道爲什麼你會有問題。根據你發佈的代碼,唯一的區別是在構造函數的頂部添加一個setLayout(null)。我同意,通常在使用空佈局時會出現問題,通常應避免使用空佈局。我希望看到一個SSCCE,其中空佈局分層窗格解決方案比空佈局JPanel解決方案的效果更好。當然,我正在討論在單個面板上使用組件,而不是多層面板。 – camickr 2013-02-09 02:41:00