IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Composants Java Discussion :

Double JSlider et gestion des événements


Sujet :

Composants Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 023
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 023
    Par défaut Double JSlider et gestion des événements
    Salut,
    je suis en train d'essayer une méthode pour simuler un Slider avec 2 thumbs. Voici le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    package swing;
     
    import java.awt.event.MouseListener;
     
    import javax.swing.JPanel;
    import javax.swing.JSlider;
    import javax.swing.OverlayLayout;
    import javax.swing.plaf.basic.BasicSliderUI;
     
    public class JRangeSliderPanel extends JPanel {
     
     
    	protected JSlider lowerSlider;
    	protected JSlider upperSlider;
     
     
    	public JRangeSliderPanel(int orientation, int min, int max, int lowerValue, int upperValue) {
    		super();
    		this.initcomponents(orientation, min, max, lowerValue, upperValue);
    		this.initListeners();
    	}
     
     
    	protected void initcomponents(int orientation, int min, int max, int lowerValue, int upperValue) {
    		// Layout
    		OverlayLayout overlay = new OverlayLayout(this);
    		this.setLayout(overlay);
     
    		this.lowerSlider = new JSlider(orientation, min, max, lowerValue);
    		this.upperSlider = new JSlider(orientation, min, max, upperValue);
     
    		this.add(this.lowerSlider);
    		this.add(this.upperSlider);
     
    		this.lowerSlider.setOpaque(false);
    		this.upperSlider.setOpaque(false);
     
    	}
     
     
    	private void initListeners() {
     
    		// Lower
    		MouseListener[] listeners = this.lowerSlider.getMouseListeners();
            for (int i = listeners.length - 1; i >= 0; i--) {
            	this.lowerSlider.removeMouseListener(listeners[i]);
    		}
     
            BasicSliderUI.TrackListener trackListener = ((BasicSliderUI) this.lowerSlider.getUI()).new TrackListener() {
                 @Override
                 public boolean shouldScroll(int dir) {
             		setComponentZOrder(upperSlider, 0);
             		upperSlider.setPaintTrack(false);
             		lowerSlider.setPaintTrack(true);
                    return false;
                 }
             };
    		this.lowerSlider.addMouseListener(trackListener);
     
    		// Upper
    		listeners = this.upperSlider.getMouseListeners();
            for (int i = listeners.length - 1; i >= 0; i--) {
            	this.upperSlider.removeMouseListener(listeners[i]);
    		}
     
            trackListener = ((BasicSliderUI) this.upperSlider.getUI()).new TrackListener() {
                 @Override
                 public boolean shouldScroll(int dir) {
             		setComponentZOrder(lowerSlider, 0);            	 
             		lowerSlider.setPaintTrack(false);
             		upperSlider.setPaintTrack(true);
             		return false;
                 }
             };
    		this.upperSlider.addMouseListener(trackListener);
    	}
     
     
     
    	public void setUpperValue(int n)	{
    		this.upperSlider.setValue(n);
    	}
     
     
    	public void setLowerValue(int n)	{
    		this.lowerSlider.setValue(n);
    	}
     
     
    	public int getLowerValue()	{
    		return this.lowerSlider.getValue();
    	}
     
    	public int getUpperValue()	{
    		return this.upperSlider.getValue();
    	}
     
    	public void setMajorTickSpacing(int n)	{
    		this.lowerSlider.setMajorTickSpacing(n);
    		this.upperSlider.setMajorTickSpacing(n);
    	}
     
    	public void setPaintTicks(boolean b)	{
    		this.lowerSlider.setPaintTicks(b);
    		this.upperSlider.setPaintTicks(b);
    	}
     
    	public void setPaintLabels(boolean b)	{
    		this.lowerSlider.setPaintLabels(b);
    		this.upperSlider.setPaintLabels(b);
    	}
     
    	public static void main(String[] args) {
    		try {
    			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
     
    		JFrame frame = new JFrame();
     
    		JRangeSliderPanel slider = new JRangeSliderPanel(JSlider.HORIZONTAL, 0, 500, 50, 320);
    		slider.setMajorTickSpacing(100);
    		slider.setPaintTicks(true);
    		slider.setPaintLabels(true);
     
    		frame.add(slider);
    		frame.setSize(400, 400);
    		frame.setVisible(true);
    	}
    }
    L'idée est de tracer 2 JSlider l'un sur l'autre grâce au layout OverlayLayout.
    Le problème est que seuls les événements du JSlider au premier plan sont pris en compte. D'où ma redéfinition du TackListener qui change le z index des composants si je clique ailleurs que sur le curseur.
    Si je clique ailleurs que sur le curseur, "l'autre" JSlider passe au premier plan et je peux donc bouger le curseur. Le souci est qu'il faut que je clique 2 fois : une fois pour repasser le composant au premier plan et une autre fois pour que l'événement sur le nouveau composant soit pris en compte.
    Il y a un petit test-case dans le main.

    Est-ce que vous verriez une solution plus simple à ce problème ?

    D'autre part, j'aimerais bloquer l'événement quand la valeur du lowerSlider dépasse celle de l'upperSlider et vice-versa, pour éviter les chevauchements mais je n'ai pas trouvé comment annuler l'événement. Auriez-vous une idée sur la question ?
    Merci d'avance

  2. #2
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765

  3. #3
    Membre Expert Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 023
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 023
    Par défaut
    Merci pour le lien
    En fait, j'aimerais bien mettre en oeuvre la solution que je propose dans le premier post.

  4. #4
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    C'est du hack foireux par essence ce que tu cherches à faire.

    Si tu veux avoir une solution que tu auras codée par toi même, je te conseille plutôt de créer ton composant en t'inspirant des sources du JSlider qui sont fournies dans le JDK. De fait du devrais même pouvoir te servir des UIDelegate du JSlider, en te basant sur le fait que la quasi totalité des Look&Feel reposent sur les classes BasicXXXUI (BasicSliderUI dans notre cas) pour déléger un maximum de dessin à la l'UIDelegate courante du JSlider.

  5. #5
    Membre Expert Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 023
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 023
    Par défaut
    Oui, c'est bien possible héhé.
    Je vais voir ça.

  6. #6
    Membre Expert Avatar de Djakisback
    Profil pro
    Inscrit en
    Février 2005
    Messages
    2 023
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 2 023
    Par défaut
    Bon j'ai codé un truc sans "hack foireux" en étendant JSlider et BasicSliderUI qui fonctionne très bien. Le problème est que je voudrais utiliser le L&F de l'OS, c'est pour ça à la base que j'avais pensé à la première méthode :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     BasicSliderUI.TrackListener trackListener = ((BasicSliderUI) this.lowerSlider.getUI()).new TrackListener() {
                 @Override
    ...
             };
    qui me permettait de modifier à la volée l'UI courante.

    Le souci est qu'en créant une classe BasicRangeSliderUI qui étend BasicSliderUI, pour l'utiliser je dois redéfinir dans une classe JRangeSlider étendant JSlider :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        public void updateUI() {
        	setUI(new BasicRangeSliderUI(this));
            updateLabelUIs();
        }
    Et ce faisant, l'appel aux méthodes paint() de BasicSliderUI ne me trace pas le même rendu que si je fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      public void updateUI() {
        	setUI((SliderUI)UIManager.getUI(this));
            updateLabelUIs();
        }
    Si quelqu'un a une idée pour déléguer toutes mes méthodes paint() de BasicRangeSliderUI à la vraie implémentation courante de l'UI, elle est la bienvenue

    Concrètement, si j'ai bien compris il faudrait que ma classe BasicRangeSliderUI étende l'implémentation courante et non pas BasicSliderUI. Mais je ne vois pas comment faire du code dynamique et générique de ce type :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    BasicRangeSliderUI extends (SliderUI)UIManager.getUI(slider)

Discussions similaires

  1. [XML] [EXPAT] xml_parse et la gestion des événements...
    Par Herode dans le forum Bibliothèques et frameworks
    Réponses: 2
    Dernier message: 05/02/2006, 21h59
  2. Gestion des évènements Netscape 7.0
    Par RATHQUEBER dans le forum Autres langages pour le Web
    Réponses: 6
    Dernier message: 19/12/2005, 17h26
  3. Problème avec la gestion des événements
    Par CynO dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 17/10/2005, 11h07
  4. [JTable] gestion des événements
    Par soulhouf dans le forum Composants
    Réponses: 4
    Dernier message: 19/08/2005, 14h21
  5. Gestion des évènements lors d'un clique sur une image.
    Par yoghisan dans le forum Débuter
    Réponses: 7
    Dernier message: 23/06/2005, 20h04

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo