2010-02-18 5 views
9

Comment ajouter un comportement de sélection au texte de JLabel?Comment ajouter un comportement de sélection à JLabel

J'ai essayé

JLabel search = new JLabel("<html><marquee>Search</marquee><html>"); 

mais sa ne fonctionne pas.

+10

Vous allez bientôt venir ici demander comment calmer la les utilisateurs qui ont vu ce chapiteau. Cherchez un abri avant le lancement. –

Répondre

3

S'il vous plaît voir http://forums.sun.com/thread.jspa?forumID=57&threadID=605616 pour plus de détails sur la façon de le faire :)

(Edit: Je probablement utiliser System.currentTimeMillis() directement dans la méthode de peinture() au lieu d'utiliser une minuterie, puis diviser/modulo (%) pour l'obtenir dans la plage requise pour 'x offset' sur les exemples). En augmentant la taille du numéro de division, vous pouvez modifier la vitesse ((System.currentTimeMillis()/200)% 50).

(Edit 2: Je mis à jour le code ci-dessous pour résoudre un problème avec repeindre Maintenant, nous programmons un repeindre dans la méthode de peinture, peut-être il y a une meilleure façon, mais cela fonctionne :).)

(Edit 3: Heu, j'ai essayé avec une chaîne plus longue et il foiré. C'était facile à corriger (plage d'augmenter à nouveau par la largeur pour compenser les valeurs négatives, soustrayez par largeur)

package mt; 

import java.awt.Graphics; 

import javax.swing.Icon; 
import javax.swing.JLabel; 

public class MyJLabel extends JLabel { 
    public static final int MARQUEE_SPEED_DIV = 5; 
    public static final int REPAINT_WITHIN_MS = 5; 

    /** 
    * 
    */ 
    private static final long serialVersionUID = -7737312573505856484L; 

    /** 
    * 
    */ 
    public MyJLabel() { 
     super(); 
     // TODO Auto-generated constructor stub 
    } 

    /** 
    * @param image 
    * @param horizontalAlignment 
    */ 
    public MyJLabel(Icon image, int horizontalAlignment) { 
     super(image, horizontalAlignment); 
     // TODO Auto-generated constructor stub 
    } 

    /** 
    * @param image 
    */ 
    public MyJLabel(Icon image) { 
     super(image); 
     // TODO Auto-generated constructor stub 
    } 

    /** 
    * @param text 
    * @param icon 
    * @param horizontalAlignment 
    */ 
    public MyJLabel(String text, Icon icon, int horizontalAlignment) { 
     super(text, icon, horizontalAlignment); 
     // TODO Auto-generated constructor stub 
    } 

    /** 
    * @param text 
    * @param horizontalAlignment 
    */ 
    public MyJLabel(String text, int horizontalAlignment) { 
     super(text, horizontalAlignment); 
     // TODO Auto-generated constructor stub 
    } 

    /** 
    * @param text 
    */ 
    public MyJLabel(String text) { 
     super(text); 
    } 



    /* (non-Javadoc) 
    * @see javax.swing.JComponent#paintComponent(java.awt.Graphics) 
    */ 
    @Override 
    protected void paintComponent(Graphics g) { 
     g.translate((int)((System.currentTimeMillis()/MARQUEE_SPEED_DIV) % (getWidth() * 2)) - getWidth(), 0); 
     super.paintComponent(g); 
     repaint(REPAINT_WITHIN_MS); 
    } 
} 
+1

Hm, et que feriez-vous avec ce nombre de millis que vous calculez dans paint()? Gardez à l'esprit que la peinture swing est un thread unique, et donc, tout sommeil dans la méthode paint() suspendra le reste de l'interface utilisateur. Toutes mes excuses si j'ai mal interprété votre réponse. –

+0

Modifié le message original pour refléter ce dont vous avez besoin :) –

+1

Pour mesurer le temps écoulé (relatif), vous devez utiliser System.nanoTime(). System.currentTimeMillis() vous donne l'heure absolue en fonction de l'horloge système. L'horloge du système pourrait changer brusquement si une application externe change l'heure du système (par exemple, ntp). http: // stackoverflow.com/questions/351565/système-currenttimemillis-vs-system-nanotime – Ajay

1

Comme vous l'avez constaté, le code HTML sur JLabel est limité au formatage et ne prend pas en charge le tag <marquee>. Vous devrez utiliser quelque chose comme un SwingWorker ou un ExecutorService pour changer le texte toutes les quelques millisecondes.

+0

une autre option est javax.swing.Timer – Karussell

0

hier est une solution sale rapide. Si vous avez besoin, je peux préciser le code en quelques points:


package gui; 

import java.awt.Color; 
import java.awt.GridLayout; 

import javax.swing.BorderFactory; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JScrollBar; 
import javax.swing.JScrollPane; 
import javax.swing.ScrollPaneConstants; 

public class ScrollLabel extends JPanel { 
    private static final long serialVersionUID = 3986350733160423373L; 
    private final JLabel  label; 
    private final JScrollPane sPane; 
    private final ScrollMe  scrollMe; 

    public ScrollLabel(String text) { 
     setLayout(new GridLayout(1, 1)); 
     label = new JLabel(text); 
     sPane = new JScrollPane(label); 
     sPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); 
     JScrollBar horizontalScrollBar = new JScrollBar(JScrollBar.HORIZONTAL); 
     sPane.setHorizontalScrollBar(horizontalScrollBar); 
     setBorder(BorderFactory.createLineBorder(Color.RED)); 
     add(sPane.getViewport()); 
     scrollMe = new ScrollMe(this, label, sPane); 
     scrollMe.start(); 
    } 

    class ScrollMe extends Thread { 
     JScrollPane sPane; 
     ScrollLabel parent; 
     JLabel  label; 

     ScrollMe(ScrollLabel parent, JLabel label, JScrollPane sPane) { 
      this.sPane = sPane; 
      this.parent = parent; 
      this.label = label; 
     } 

     boolean isRunning = true; 

     @Override 
     public void run() { 
      int pos = 0; 
      try { 
       while (isRunning) { 
        if (sPane.isVisible()) { 
         int sWidth = parent.getSize().width; 
         int lWidth = label.getWidth(); 

         if (sWidth < lWidth) { 
          if (pos + sWidth > lWidth) 
           pos = 0; 
          sPane.getHorizontalScrollBar().setValue(pos); 
         } 
        } 
        synchronized (this) { 
         wait(50); 
         pos += 1; 
        } 
       } 
      } 
      catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      finally { 
       isRunning = false; 
      } 
     } 
    } 

    public static void main(String[] args) { 
     JFrame jFrame = new JFrame("ScrollLabel"); 
     jFrame.getContentPane().add(new ScrollLabel("how to add marquee behaviour to Jlabel !Java")); 
     jFrame.setVisible(true); 
    } 
} 

2

Cela fonctionne très bien (je l'ai écrit cela en moi-même, donc il pourrait y avoir quelques erreurs):

import java.awt.Font; 
import java.awt.FontMetrics; 
import java.awt.Graphics; 

import javax.swing.JLabel; 
import javax.swing.JPanel; 

public class JMarqueeLabel extends JPanel implements Runnable 
{ 
    /** 
    * 
    */ 
    private static final long serialVersionUID = -2973353417536204185L; 
    private int x; 
    private FontMetrics fontMetrics; 
    public static final int MAX_SPEED = 30; 
    public static final int MIN_SPEED = 1; 
    private int speed; 
    public static final int SCROLL_TO_LEFT = 0; 
    public static final int SCROLL_TO_RIGHT = 1; 
    private int scrollDirection = 0; 
    private boolean started = false; 
    private JLabel label; 

    public JMarqueeLabel(String text) 
    { 
     super(); 
     label = new JLabel(text) 
     { 
      /** 
      * 
      */ 
      private static final long serialVersionUID = -870580607070467359L; 

      @Override 
      protected void paintComponent(Graphics g) 
      { 
       g.translate(x, 0); 
       super.paintComponent(g); 
      } 
     }; 
     setLayout(null); 
     add(label); 
     setSpeed(10); 
     setScrollDirection(SCROLL_TO_RIGHT); 
    } 

    @Override 
    protected void paintComponent(Graphics g) 
    { 
     super.paintComponent(g); 
     label.paintComponents(g); 
    } 

    public void setScrollDirection(int scrollDirection) 
    { 
     this.scrollDirection = scrollDirection; 
    } 

    public int getScrollDirection() 
    { 
     return scrollDirection; 
    } 

    public void setSpeed(int speed) 
    { 
     if (speed < MIN_SPEED || speed > MAX_SPEED) 
     { 
      throw new IllegalArgumentException("speed out of range"); 
     } 
     this.speed = speed; 
    } 

    public int getSpeed() 
    { 
     return speed; 
    } 

    @Override 
    public void validateTree() 
    { 
     System.out.println("Validate..."); 
     super.validateTree(); 
     label.setBounds(0, 0, 2000, getHeight()); 
     if (!started) 
     { 
      x = getWidth() + 10; 
      Thread t = new Thread(this); 
      t.setDaemon(true); 
      t.start(); 
      started = true; 
     } 
    } 

    public String getText() 
    { 
     return label.getText(); 
    } 

    public void setText(String text) 
    { 
     label.setText(text); 
    } 

    public void setTextFont(Font font) 
    { 
     label.setFont(font); 
     fontMetrics = label.getFontMetrics(label.getFont()); 
    } 

    @Override 
    public void run() 
    { 
     fontMetrics = label.getFontMetrics(label.getFont()); 
     try 
     { 
      Thread.sleep(100); 
     } catch (Exception e) 
     { 
     } 
     while (true) 
     { 
      if (scrollDirection == SCROLL_TO_LEFT) 
      { 
       x--; 
       if (x < -fontMetrics.stringWidth(label.getText()) - 10) 
       { 
        x = getWidth() + 10; 
       } 
      } 
      if (scrollDirection == SCROLL_TO_RIGHT) 
      { 
       x++; 
       if (x > getWidth() + 10) 
       { 
        x = -fontMetrics.stringWidth(label.getText()) - 10; 
       } 
      } 
      repaint(); 
      try 
      { 
       Thread.sleep(35 - speed); 
      } catch (Exception e) 
      { 
      } 
     } 
    } 

} 

Cela fonctionne pour les très longues cordes. Si vous avez besoin de chaînes plus longues, vous devez remplacer 2000 par un nombre plus élevé.

Hope this est ce que vous voulez :-)

Questions connexes