Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Часть 4 - GUI, предварительные знания 
:(
    Опции темы
AntonSaburov
Дата 18.10.2006, 11:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Штурман
****


Профиль
Группа: Модератор
Сообщений: 5658
Регистрация: 2.7.2002
Где: Санкт-Петербург

Репутация: 51
Всего: 118



Список - model и listeners. Пример попроще

Давайте рассмотрим постепенно все необходимые нам части пользовательского интерфейса. И начнем мы со списка групп. Здесь нас будет интересовать два момента:
- Возможность реагировать на изменение выбранной строки в списке. Нам необходимо показывать список студентов выделенной группы.
- Возможность добавить/удалить элемент списка. 
В нашем "отделе кадров" мы не ставили себе задачу редактировать именно список - студенты будут представлены в виде таблицы. Список будет содержать группы, и его мы не собирались редактировать. Но для понимания основ лучше будет пока рассмотреть именно список.  Идеологически редактирование и представление данных в таблице будет очень похоже на работу со списком.

Кроме списка мы коснемся работы с кнопками, которые нам тоже понадобятся в будущем.

В данной части мы пока оставим наш "отдел кадров" в стороне, чтобы не было сразу сложно. Нам ведь предстоит немало потрудится. И если писать сразу весь код, то скорее всего Вы запутаетесь.

Поэтому рассмотрим все на тестовом примере - создадим простую форму и положим на нее всего лишь один объект - список. В SWING для этого существует специальный класс - JList. Позже добавим еще пару кнопок и панель. 

Наше самое простое приложение будет выглядеть вот так:
Код

import java.util.*;
import javax.swing.*;

public class Test extends JFrame
{
  private JList list;

  public Test()
  {
    // Для инициализации списка нам потребуется вектор - посмотрите коллекции
    Vector v = new Vector();
    v.add("1");
    v.add("2");
    v.add("3");
    v.add("4");
    v.add("5");
    list = new JList(v);

    // Добавляем список на панель формы
    getContentPane().add(new JScrollPane(list));

    // Устанавливаем границы   
    setBounds(100,100, 200, 200);
  }

  public static void main(String[] args)
  {
    Test t = new Test();
    t.setDefaultCloseOperation(t.EXIT_ON_CLOSE);
    t.setVisible(true);
  }
}

Вообщем ничего сложного пока нет. Давайте теперь добавим в наш список возможность реагировать на события - а именно на перемещение указателя. Теперь мы вплотную подошли в слушателям (listeners). По сути они и являются теми самыми контроллерами в паттерне MVC) Model-View-Controller).
Если Вы внимательно читали первую часть посвященную SWING, то помните, что механизм листенеров (автор приносит свои извинения за русский вариант английского слова, но в программистской среде понятие "слушатель" встречается крайне редко) основан на простой идее - объект, который принимает какие-либо события может содержать список объектов, которые "подписались" на "прослушку" событий. Т.е. для примера - кнопка при своем нажатии проверяет список листенеров и каждому посылает сообщение, что ее нажали. Предварительно каждый, кто хочет знать о нажатии добавляет себя в список листенеров для кнопки. Чтобы принять сообщение от кнопки листенер должен реализовать интерфейс. Давайте посмотрим это на примере.
Для списка листенер должен реализовать интерфейс ListSelectionListener. В нашем случае листенером будет сама форма.
Также мы сразу введем режим выделения для списка - только одна строка. Список может выделять несколько пунктов сразу, но нас этот режим не интересует. Кто хочет рассмотреть подробно - читайте документацию.

Код

import java.util.*;
import javax.swing.*;
import javax.swing.event.*;

// Обратите внимание, что теперь наша форма реализует интерфейс
public class Test extends JFrame implements ListSelectionListener
{
  private JList list;

  public Test()
  {
    // Для инициализации списка нам потребуется вектор - посмотрите коллекции
    Vector v = new Vector();
    v.add("1");
    v.add("2");
    v.add("3");
    v.add("4");
    v.add("5");
    list = new JList(v);

    // Вот здесь выставляем режим выделения одного пункта
    list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

    // Список будет посылать сообщения форме
    list.addListSelectionListener(this);

    // Добавляем список на панель формы
    getContentPane().add(new JScrollPane(list));

    // Устанавливаем границы   
    setBounds(100,100, 200, 200);
  }


  // Единственный метод, который реализует интерфейс ListSelectionListener
  public void valueChanged(ListSelectionEvent e)
  {
    System.out.println("New index:"+list.getSelectedIndex());
  }

  public static void main(String[] args)
  {
    Test t = new Test();
    t.setDefaultCloseOperation(t.EXIT_ON_CLOSE);
    t.setVisible(true);
  }
}

Теперь если мы запустим наше приложение из командной строки, то при перемещении увидим на экране строку с номером индекса.
Но если Вы попробуете изменять строки мышкой, то заметите, что наш метод valueChanged вызывается ДВА раза. Это связано с тем, что список может выделять сразу много строк. В нашем случае нам этот эффект ольше мешает, чем помогает. Но мы можем найти на него управу - оказывается объект класса ListSelectionEvent имеет метод getValueIsAdjusting который возвращает true если событие вызывается по причине выбора нескольких пунктов. Нам интересен момент, когда этот метод возвращает false - нам же не надо отслеживать многострочные выделения внутри нашего списка. Поэтому наш пример немного изменится.

Код

import java.util.*;
import javax.swing.*;
import javax.swing.event.*;

// Обратите внимание, что теперь наша форма реализует интерфейс
public class Test extends JFrame implements ListSelectionListener
{
  private JList list;

  public Test()
  {
    // Для инициализации списка нам потребуется вектор - посмотрите коллекции
    Vector v = new Vector();
    v.add("1");
    v.add("2");
    v.add("3");
    v.add("4");
    v.add("5");
    list = new JList(v);

    // Вот здесь выставляем режим выделения одного пункта
    list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

    // Список будет посылать сообщения форме
    list.addListSelectionListener(this);

    // Добавляем список на панель формы
    getContentPane().add(new JScrollPane(list));

    // Устанавливаем границы   
    setBounds(100,100, 200, 200);
  }

  // Единственный метод, который реализует интерфейс ListSelectionListener
  public void valueChanged(ListSelectionEvent e)
  {
    if(!e.getValueIsAdjusting()) {
      System.out.println("New index:"+list.getSelectedIndex());
    }
  }

  public static void main(String[] args)
  {
    Test t = new Test();
    t.setDefaultCloseOperation(t.EXIT_ON_CLOSE);
    t.setVisible(true);
  }
}


Теперь давайте попробуем изменять наш список динамически. Если вы будете пробовать просто добавлять в наш вектор какие-либо значения, то эффекта на экране вы не увидите. Вернее может и увидите, но что там точно будет гарантировать я не могу.
Как уже упоминалось, нам надо действовать через модель. Модель можно получить вызовом JList.getModel(). Этот метод возвращает нам не класс, а интерфейс ListModel. Конечно же за ним кроется какой-то настоящий класс, но в том удобство и состоит, что Вы можете написать свою модель, которая обязана реализовать интерфейс ListModel по своему вкусу, и расширить его теми функциями, которые Вам необходимы.
Давайте напишем пример, который будет добавлять в наш список строки. Предварительно сделаем вот какое замечание - наш список на самом деле уже имеет некоторую модель. Но она не является стандартной и что она умеет точно - мы не знаем. В пакете SWING есть уже готовая модель, которая умеет то, что нам надо - а именно добавлять строки. Это DefaultListModel. Давайте ее и используем.
Кроме этого мы добавим кнопку, которая будет давать команду на добавление. Для "прослушивания" событий от кнопки нам надо реализовать интерфейс ActionListener. В нем тоже всего один метод - actionPerformed.

Код

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

// Обратите внимание, что теперь наша форма реализует два интерфейса - один для
// списка, другой - для кнопки
public class Test extends JFrame implements ListSelectionListener, ActionListener
{
  private JList list;
  private JButton add = new JButton("Add");

  public Test()
  {
    list = new JList();
    // Вот здесь выставляем режим выделения одного пункта
    list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

    // Создадим модель и отдади ее нашему списку вместо его стандартной
    DefaultListModel dlm = new DefaultListModel();
    list.setModel(dlm);

    // Список будет посылать сообщения форме
    list.addListSelectionListener(this);

    // Кнопка тоже будет посылать сообщения форме
    add.addActionListener(this);

    // Добавляем список на панель формы
    getContentPane().add(new JScrollPane(list), BorderLayout.CENTER);

    // Добавляем кнопку в нижнюю часть
    getContentPane().add(add, BorderLayout.SOUTH);

    // Устанавливаем границы   
    setBounds(100,100, 200, 200);
  }


  // Единственный метод, который реализует интерфейс ListSelectionListener
  public void valueChanged(ListSelectionEvent e)
  {
    if(!e.getValueIsAdjusting()) {
      System.out.println("New index:"+list.getSelectedIndex());
    }
  }

  public void actionPerformed(ActionEvent e)
  {
    // Мы знаем, что у списка модель класса DefaultListModel
    // И поэтому можем ее привести к такому типу
    DefaultListModel dlm = (DefaultListModel)list.getModel();
    // Модель позволяет добавить новый элемент
    dlm.addElement(String.valueOf(dlm.getSize()));
  }

  public static void main(String[] args)
  {
    Test t = new Test();
    t.setDefaultCloseOperation(t.EXIT_ON_CLOSE);
    t.setVisible(true);
  }
}


И наконец напишем пример, которы не только добавляет, но и удаляет. Для этого добавим еще одну кнопку. Заметьте, что обработчик для обеих кнопок будет один и тот же. Для того, чтобы узнать какая кнопка нажата будем использовать методы getName/setName.
В примере есть одно неудобство - Вам надо каждый раз при удалении выделять какую строку вы хотите удалить. Но решение этой проблемки автор оставляет для читателя.

Код

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

// Обратите внимание, что теперь наша форма реализует интерфейс
public class Test extends JFrame implements ListSelectionListener, ActionListener
{
  private JList list;

  public Test()
  {
    list = new JList();
    // Вот здесь выставляем режим выделения одного пункта
    list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

    // Создадим модель и отдади ее нашему списку вместо его стандартной
    DefaultListModel dlm = new DefaultListModel();
    list.setModel(dlm);

    // Список будет посылать сообщения форме
    list.addListSelectionListener(this);

    JButton add = new JButton("Add");
    JButton del = new JButton("Del");

    // Кнопка тоже будет посылать сообщения форме
    add.addActionListener(this);
    del.addActionListener(this);

    // Дадим нашим кнопкам имена, чтобы их можно было различать
    // при обработке
    add.setName("add");
    del.setName("del");

    // Создадим панель для наших кнопок и сделаем ее layout
    // в виде таблицы - 1 строка, 2 столбца
    JPanel p = new JPanel();
    p.setLayout(new GridLayout(1,2));
    p.add(add);
    p.add(del);

    // Добавляем список на панель формы
    getContentPane().add(new JScrollPane(list), BorderLayout.CENTER);

    // Добавляем панель в нижнюю часть
    getContentPane().add(p, BorderLayout.SOUTH);

    // Устанавливаем границы   
    setBounds(100,100, 200, 200);
  }


  // Единственный метод, который реализует интерфейс ListSelectionListener
  public void valueChanged(ListSelectionEvent e)
  {
    if(!e.getValueIsAdjusting()) {
      System.out.println("New index:"+list.getSelectedIndex());
    }
  }

  public void actionPerformed(ActionEvent e)
  {
    // Мы знаем, что у списка модель класса DefaultListModel
    // И поэтому можем ее привести к такому типу
    DefaultListModel dlm = (DefaultListModel)list.getModel();

    JButton sender = (JButton)e.getSource();

    if(sender.getName().equals("add")) {
      dlm.addElement(String.valueOf(dlm.getSize()));
    }
    // Проверяем имя для удаления и проверяем индекс - если он =-1, 
    // значит нет выделенной строки
    if(sender.getName().equals("del") && list.getSelectedIndex()>=0) {
      dlm.remove(list.getSelectedIndex());
    }
  }

  public static void main(String[] args)
  {
    Test t = new Test();
    t.setDefaultCloseOperation(t.EXIT_ON_CLOSE);
    t.setVisible(true);
  }
}


Теперь Вы готовы к более сложным испытаниям, а именно к работе с наши отделом кадров. В следующей части мы с вами создадим более интересный интерфейс, чем тот, который был ранее.
Мы будем делать это постепенно - вводить листенеры, реализовывать команды. Итак смотрим Часть 5 - Улучшаем интерфейс и вводим команды
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0644 ]   [ Использовано запросов: 23 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.