Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: GUI и Java FX приложения > Swing. Взаимодействие контролов на интерфейсе


Автор: anti_snayper 8.2.2011, 09:49
Есть календарь, написанный на свинге. Выполнен в виде JMenuPopup с набором кнопок, ддл, текстовым полем. Он встраивается в интерфейс с другими контролами. Нужно чтобы при клике на внешнем контроле календарь скрывался, при клике на внутреннем позволял произвести выбор значения(например, ддл выбора месяца).  Я могу перехватывать в нем события changeState или связанные с изменением фокуса. Но не знаю как узнать от кого оно пришло. К примеру, в случае с ддл, ивент говорит, что создатель события - MenuSelectionManager, из которого ничего полезного выудить не получается.

Как решают такие ситуации? Наверняка же должен какой-то типовой подход...

Спасибо.

Автор: _Y_ 8.2.2011, 21:35
Ну а если разными слушателями (Listener) разные клики отслеживать? А в слушателе прописать атрибут, который знает "хозяина"?

Автор: anti_snayper 9.2.2011, 02:01
Утром торопился потому написал видимо не очень понятно. Попробую еще раз... На интерфейсе есть JComboBox-ы. При клике на каком либо из них автоматом генерится стандартное событие, которое оповещает остальные элементы интерфейса о том что им надо закрыться. Это обычное поведение любого интерфейса. Я добавил выпадающий по клику на кнопке календарь, который выполнен в виде JMenuPopup. В нем есть JComboBox с месяцами. Так вот при клике на этом ддл - календарь закрывается. Т.е. этот контрол генерит событие которое закрывает свой собственный контейнер(JMenuPopup). Такого само собой быть не должно.
Я недавно занялся свингом и вполне возможно что-то недопонимаю. 

Автор: _Y_ 9.2.2011, 10:33
Вместо стандартного Listener пишешь свой, наследующий от стандартного.  Я сейчас не могу посмотреть видно ли из кода Listener-а на каком контроле кликнули. 
  • Если  да, в коде обработки события пишешь "закрыть все JComboBox-ы, кроме того, на котором кликнули".
  • Если нет, пишешь у Listener-а атрибут, указывающий на "свой" JComboBox. Уже в конструкторе Listener-а присваиваещь значение этому атрибуту. В коде обработки события пишешь "закрыть все JComboBox-ы, кроме того, на который указывает этот атрибут". Понятное дело, каждому  JComboBox-у создаещь и присваиваешь свой обьект этого Listener-ого класса.

Хочешь напишу код. Но быстро не обещаю. В форуме сижу пока компы делом заняты. Может вечерком или завтра.

Автор: anti_snayper 9.2.2011, 11:10
За пример был бы  очень благодарен... Можете сказать какой event оповещает остальные элементы интерфейса о своем закрытии? 

Автор: _Y_ 9.2.2011, 23:14
Поскольку я не знаю что за классы вы используете в качестве календарей, набросал пример иллюстрирующий общий принцип. Работает по первому варианту. Оказалось я помнил правильно и событие знает на каком объекте кликнули.

Програмка показывает множество кнопок. При клике на одну кнопку она увеличивается, а размеры остальных становятся стандартными. Что непонятно - спрашивайте.

Код

import java.awt.Dimension;
import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JFrame;


public class DemoClickableButtons extends JFrame{
    
    private static final int N_BUTTONS = 35;
    
    private static final Dimension SMALL_BUTTON = new Dimension(70, 30), BIG_BUTTON = new Dimension(120, 50);
    
    private JButton[] buttons;
    
    public DemoClickableButtons(){    
        super();
        
        //Form-related steps
        
        this.setLayout(new FlowLayout());
        this.setSize(900, 200);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        //Create buttons
        
        buttons = new JButton[N_BUTTONS];
        
        for(int i = 0; i < N_BUTTONS; i++){
            
            //Create button
            
            buttons[i] = new JButton("Button " + i);
            
            //Create and add action listener
            
            buttons[i].addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    
                    //Change size of the buttons if a button is clicked
                    
                    for(JButton but : buttons){
                        if(but == (JButton)evt.getSource()){
                            but.setSize(BIG_BUTTON);
                        } else {
                            but.setSize(SMALL_BUTTON);
                        }
                    }
                    
                }
            });
            
            //Add buttons to the form
            
            this.add(buttons[i]);

            
        }
        
        //Show the form
        
        this.setVisible(true);
    }
    
    


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

}

Автор: anti_snayper 10.2.2011, 00:55
Вот простой пример . Есть 2 JComboBoxa. Кликаем по первому - он открывается. Кликаем по второму - первый закрывается, второй открывается. Вот меня и интересует. Какой listener мне нужно переопределить и как, чтобы они друг друга не закрывали? 

Код

import java.awt.Color;
import java.awt.FlowLayout;

import javax.swing.BorderFactory;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TestListeners extends JFrame{
    
    private JPanel panel;
    private JComboBox comboBox1;
    private JComboBox comboBox2;
    
    private String[] commonItems = new String[] {"1", "2", "3"};
    
    public TestListeners(){    
        super();
        
        this.setLayout(new FlowLayout());
        this.setSize(200, 200);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        panel =  new JPanel();
        panel.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, Color.BLACK));
        comboBox1 = new JComboBox(commonItems);        
        comboBox2 = new JComboBox(commonItems);
                
        panel.add(comboBox1);
        panel.add(comboBox2);
        add(panel);        
        setVisible(true);
    }
    
    
    public static void main(String[] args) {
        new TestListeners();
    }
}

Автор: _Y_ 11.2.2011, 11:03
Эге. Теперь проблема понятнее. Надо подумать.  Закрытие JComboBox, видимо, связано с потерей им фокуса, но я не уверен - надо проверять.

Автор: anti_snayper 11.2.2011, 17:14
Решил оставить поведение JComboBox-ов как есть, адаптировав под него интерфейс.  

P.S. Вообще  была идея использовать вместо JMenuPopup - JDialog. При этом проблема решается сама собой, но нужно поколдовать над диалоговым окном для его кастомизации под попап. Думаю, что этот вариант вполне реализуем, но надо проверять.

Автор: _Y_ 11.2.2011, 22:36
Если не заморачиваться именно с JComboBox-ами, то можно написать самому их иммитацию. На JPanel поместить текстовое поле и обычный список JList ниже него. Этот список прятать-показывать когда захочется. Но в этом случае, естественно, придется много кодить рутинных вещей.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)