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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Задержка в потоке событий, Нужен показ слайдов 
V
    Опции темы
Mirkes
Дата 20.8.2011, 22:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Вопрос поднимался на форуме раз 5 (может и более, но я нашел пять). Внимательно прочитал все. Ни в одном случае не приведен код, давший нужный результат. По сути все варианты вопросов сводятся к аналогии с показом слайдов: пользователь нажимает кнопку и из процедуры обработки события нажатия кнопки (это очень важный момент) запускается процедура которая отрисовывает одну картинку, засыпет на n секунд, отрисовывает следующую и т.д.
К сожалению поток событий в Java, в отличии от, например, Delphi, не позволяет реализовать это так, как я написал.
Из рекомендаций, данных разным товарищам в связи с аналогичными вопросами, я выудил ссылку на две утилиты SwingUtilities.invokeAndWaite и SwingUtilities.invokeLater. В соответствии с официальной документацией первую НЕЛЬЗЯ запускать из потока событий. Вторую вроде бы можно, но ни один из моих экспериментов не привел к нужному результату. Просьба к мастерам привести простенький (по возможности) рабочий вариант решения этой задачки и зафиксировать ее в FAQ.
Заранее благодарен.


--------------------
Mirkes
PM MAIL   Вверх
Mirkes
Дата 21.8.2011, 02:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Предлагаю свой вариант решения - работающий апплет.
Хотелось бы услышать мнение профессионалов (вдруг что-то сработало случайно: не знаю как в Java, а в паскале, фортране, VB это точно бывает)

Код вспомогательного класса, поставляющего слайды и работающего семафором
Код

package delay;

public class Inform {
    private boolean go = false;
    private int delay = 1000;
    private String[] slids = {"Первый слайд", "Второй слайд", "Третий слайд"};
    private int currSlide = 0;
    
    public Inform() {
        super();
    }

    /**
     * @param go
     */
    public void setGo(boolean go) {
        this.go=go;
    }

    /**
     * @return
     */
    public boolean getGo() {
        return go;
    }

    /**
     * @return
     */
    public int getDelay() {
        return delay;
    }

    /**
     * @return
     */
    public String getNextString() {
        if (currSlide==3) currSlide=0;
        return slids[currSlide++];
    }
}


Код главного класса
Код

package delay;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Toolkit;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;

public class Slide extends JApplet {
    private JButton jButton1 = new JButton("Начать шоу");
    private JButton jButton2 = new JButton("Кончить шоу");
    private JLabel label = new JLabel("Еще не начиналось", SwingConstants.CENTER);

    private transient Inform inform = new Inform();

    public Slide() {
    }

    private void jbInit() throws Exception {
        this.getContentPane().setLayout(null);
        this.setSize(new Dimension(400, 137));
        jButton1.setBounds(new Rectangle(45, 20, 130, 20));
        jButton1.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    jButton1_actionPerformed(e);
                }
            });
        jButton2.setBounds(new Rectangle(210, 20, 135, 20));
        jButton2.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    jButton2_actionPerformed(e);
                }
            });
        label.setBounds(new Rectangle(115, 85, 120, 15));
        this.getContentPane().add(label, null);
        this.getContentPane().add(jButton2, null);
        this.getContentPane().add(jButton1, null);
    }
    
    public void start(){
        // Попытка создать отдельный процесс, который будет отвечать за показ слайдов
        Runnable r = new Runnable() {
            @Override
            public void run() {
                while (true) {
                    if (inform.getGo()) {
                        label.setText(inform.getNextString());
                        try {
                            Thread.currentThread().sleep(inform.getDelay());
                        } catch (InterruptedException e) {
                        }
                        
                    } else {
                        try {
                            Thread.currentThread().sleep(1000);
                        } catch (InterruptedException e) {
                        }
                    }
                }
            }
        };
        Thread th = new Thread (r);
        // Starten des Threads
        th.start ();
    }

    public void init() {
        try {
            jbInit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Slide applet = new Slide();
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(applet, BorderLayout.CENTER);
        frame.setTitle("Applet Frame");
        applet.init();
        applet.start();
        frame.setSize(400, 150);
        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension frameSize = frame.getSize();
        frame.setLocation((d.width - frameSize.width) / 2, (d.height - frameSize.height) / 2);
        frame.setVisible(true);
    }


    static {
        try {
        } catch (Exception e) {
        }
    }

    private void jButton1_actionPerformed(ActionEvent e) {
        inform.setGo(true);
    }

    private void jButton2_actionPerformed(ActionEvent e) {
        inform.setGo(false);
    }
}


На всякий случай код пускача (классы должны лежать в подкаталоге delay того каталога, в котором лежит этот файл)/
Прошу прощения за внешний вид файла
Код

<HTML>
 <BODY>
  <table border="1" bordercolor="#000000"><tr><td>
   <APPLET CODE="delay.Slide.class" 
          HEIGHT="500" 
          WIDTH="607" 
          ALIGN="bottom">This browser does not support Applets.
   </APPLET>
  </table>
 </BODY>
</HTML>



Если решение представляет интерес могу его откомментировать (код).


--------------------
Mirkes
PM MAIL   Вверх
COVD
Дата 22.8.2011, 16:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 4
Всего: 43



Цитата

К сожалению поток событий в Java, в отличии от, например, Delphi, не позволяет реализовать это так, как я написал.


"поток событий в Java" - это, очевидно,  EventDispatchThread (EDT). Это поток, который извлекает из очереди события (обьекты, имплементирующие Runnable) и выполняет их. Любое действие пользователя (например, нажатие кнопки) приводит к созданию нового события и добавление его в очередь. Все действия по изменению визуальных компонентов следует выполнять в EDT, т.е. их следует оформлять в виде событий. Это является гарантией, что изменение и перерисовка будут выполняться последовательно. 

Применительно к вашему коду это означает, что команду
Код

 label.setText(inform.getNextString());


, которая меняет содержимое метки и которая у вас выполняется в "отдельном" потоке, следует выполнить в EDT 

Код

  SwingUtilities.invokeLater(new Runnable() {
    public void run() {      
      label.setText(inform.getNextString());
    }
  });

PM MAIL   Вверх
Mirkes
Дата 23.8.2011, 01:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Цитата(COVD @  22.8.2011,  16:50 Найти цитируемый пост)
Применительно к вашему коду это означает, что команду

Код

 label.setText(inform.getNextString());


, которая меняет содержимое метки и которая у вас выполняется в "отдельном" потоке, следует выполнить в EDT 

Код

  SwingUtilities.invokeLater(new Runnable() {
    public void run() {      
      label.setText(inform.getNextString());
    }
  });


Два вопроса.
Во первых, насколько я понимаю вызов метода setText породит событие, которое будет занесено в очередь событий. Или я не прав? Если это не так, то тогда все методы, влекущие изменения в любом из графических компонентов (потомков от Component и Container) следует упаковывать в такую же обертку, а это заведомо не так.

Во вторых, в чем причина кавычек в "отдельном" потоке? Он не отдельный? Я имел в виду отдельный от потока обработки событий (EDT).

Это сообщение отредактировал(а) Mirkes - 23.8.2011, 01:52


--------------------
Mirkes
PM MAIL   Вверх
jk1
Дата 23.8.2011, 04:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 21
Всего: 75



Цитата

 то тогда все методы, влекущие изменения в любом из графических компонентов (потомков от Component и Container) следует упаковывать в такую же обертку, а это заведомо не так.


Все методы, влекущие изменения в любом из графических компонентов (потомков от Component и Container) следует упаковывать в такую же обертку если вызов происходит не из EDT.

А вообще Вы стреляете из пушки по воробьям, никаких потоков в явном виде тут не нужно. Вот накидал пример через таймер:
Код

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

public class SlideShow extends JFrame implements ActionListener {

    private Timer timer = new Timer(1000, this);
    private JLabel slideHolder = new JLabel("<Hit start to launch the show>");
    private String[] slides = {"Slide 1", "Slide 2", "Slide 3"};
    private int currSlide = 0;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new SlideShow().setVisible(true);
            }
        });
    }

    public SlideShow() {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(200, 100);
        JPanel contentPane = new JPanel();
        contentPane.add(slideHolder);
        JButton start = new JButton("Start");
        JButton stop = new JButton("Stop");
        start.addActionListener(this);
        stop.addActionListener(this);
        start.setActionCommand("start");
        stop.setActionCommand("stop");
        contentPane.add(start);
        contentPane.add(stop);
        this.setContentPane(contentPane);
        this.setVisible(true);

    }

    public void actionPerformed(ActionEvent e) {
        if ("start".equals(e.getActionCommand())) {
            timer.start();
        } else if ("stop".equals(e.getActionCommand())) {
            timer.stop();
        } else { // timer event
            if (currSlide == 3) currSlide = 0;
            slideHolder.setText(slides[currSlide++]);
        }
    }
}


Обратите внимание на то, что в примере отрисовка изначально запускается на EDT.

Это сообщение отредактировал(а) jk1 - 23.8.2011, 13:35


--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
COVD
Дата 23.8.2011, 12:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 4
Всего: 43



Цитата

Во вторых, в чем причина кавычек в "отдельном" потоке? Он не отдельный? Я имел в виду отдельный от потока обработки событий (EDT).

Это просто ссылка на ваше название потока. Конечно он отдельный от EDT.

Цитата

Обратите внимание на то, что в примере отрисовка изначально запускается на EDT.

Я бы уточнил и обратил внимание на то, что в варианте jk1 используется javax.swing.Timer. И поэтому метод actionPerformed(ActionEvent e) вызывается в EDT. А если использовать java.util.Timer, то нет. И тогда надо использовать упомянутую обертку. Использование javax.swing.Timer в данном примере - изящное решение. Но отдельный поток, будь то java.util.Timer или просто new Thread(), как сделал автор топика, также применим. 

Изменим слегка "обертку":

  
Код

  final String newString = inform.getNextString();

  SwingUtilities.invokeLater(new Runnable() {
    public void run() {      
      label.setText(newString);
    }
  });


Метод getNextString() теперь выполняется в отдельном от EDT потоке. Чем это хорошо? Представим, что внутри метода осуществляется запрос в базу данных, в интернет или чтение с диска. Непредсказуемо длительные операции. Если это выполнять в EDT, то возможно "замораживание" пользовательского интерфейса.

Добавлено через 10 минут и 34 секунды
Цитата(jk1 @ 23.8.2011,  04:31)
Несмотря на то, что обработка события произойдет на EDT, отрисовка будет выполнена в контексте вызывающего потока.

Что значит "в контексте  вызывающего потока". Разве не в порядке общей очереди? А очередь - одна.
PM MAIL   Вверх
jk1
Дата 23.8.2011, 13:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 21
Всего: 75



Цитата

Что значит "в контексте  вызывающего потока". Разве не в порядке общей очереди? А очередь - одна. 

Конечно одна, просто неудачно выразился. Спасибо.


--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
Mirkes
Дата 28.9.2011, 09:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Если я правильно понимаю, вырисовалось три разных варианта решения:
1. с разными потоками без использования таймера, но с "засыпанием" исполнителя вне EDT. Годится приведенный в начале топика пример с добавлением соответствующей обертки изменений в графическом интерфейсе.
2. с таймером из java.util.Timer так же требующий обертки изменений в графическом интерфейсе.
3. с таймером из javax.swing.Timer, не требующий обертки, но грозящий "заморозкой" пользовательского интерфейса в некоторых ситуациях.

Требуется мнение "Суперов" по поводу необходимости описания всех трех вариантов или только двух последних.
И нужен доброволец для формирования окончательного варианта для FAQ.

Я могу попытаться сделать описание методов, но уж точно не являюсь экспертом для оценки того, какие из предложенных решений стоит выносить в FAQ. Просьба отозваться тех, кто экспертами является.



--------------------
Mirkes
PM MAIL   Вверх
Mirkes
Дата 28.9.2011, 13:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Прилагаю исправленный, слегка реструктуризированный (более гибкий) вариант своего решения.
Решение с таймером из  javax.swing.Timer вроде вполне понятен и без переработки.
Вариант с таймером из  java.util.Timer мне не до конца понятен.
Предлагаю следующий вариант текста для FAQ, который нуждается в дополнении третьим вариантом

Постановка задачи.
Необходимо организовать показ слайдов с задержкой между отображением слайдов.
Возможно несколько вариантов решения этой задачи.

Первый вариант оформлен как апплет, который может запускаться автономно.
Создаются два специальных класса:
1. Slider - объект, который после команды "начать" начинает с заданным интервалом времени вызывать отрисовку слайдов. Фактически этот объект служит диспетчером.
2. Drawer - объект, котороый при вызове из Slider производит отрисовку очередного слайда. Он же следит за сменой слайдов. Исходно это пустышка, ничего не делающая. Наполнение при реализации.
При создании Slider производится запуск отдельного потока, в котором работает только сам Slider. Большую часть времени он спит, поэтому не потребляет большого количества ресурсов.

код интерфейса Drawer
Код

package delay;

/**
 * Это интерфейс для отрисовщика слайдов.
 * Фактическое наполнение создается в момент создания экземпляра соответсвующего класса
 */

public interface Drawer {
    /**
     * метод отрисовывающий очередной слайд и переходящий к следующему слайду.
     * если предполагается завершение показа после достижения последнего слайда, 
     * то после отрисовки последнего слайда следует вернуть false.
     * @return Возвращает признак необходимости завершить показ слайдов
     */
    public boolean drawNextSlide();
}



Код диспетчера Slider
Код

package delay;

/**
 * Это класс-исполнитель.
 * Переменные
 *   go - признак необходимости выыполнять какие-либо действия.
 *   delay - время задержки в мс
 *   drawer - интерфейс (объект) показывающий слайды.
 */

public class Slider implements Runnable {
    boolean go = false;
    int delay = 1000;
    Drawer drawer = null;

    public Slider() {
        super();
    }

    public Slider(Drawer drawer) {
        super();
        this.drawer = drawer;
    }

    /**
     * @param go - устанавливает признак показа. true - вести показ шоу, false - не вести.
     */
    public void setGo(boolean go) {
        this.go = go;
    }

    /**
     * @return Возвращает текущий признак показа.
     */
    public boolean getGo() {
        return go;
    }

    /**
     * @return возвращает текущую задержку между слайдами
     */
    public int getDelay() {
        return delay;
    }

    // устанавливает новую задержку

    public void setDelay(int delay) {
        this.delay = delay;
    }

    public void setDrawer(Drawer drawer) {
        go=false;
        this.drawer = drawer;
    }

    /**
     * метод, осуществляющий всю обработку по времени и вызывающий отрисовку слайдов.
     */
    @Override
    public void run() {
        while (true) {
            if (go && (drawer != null)) {
                go=drawer.drawNextSlide();
                try {
                    Thread.currentThread().sleep(delay);
                } catch (InterruptedException e) {
                }

            } else {
                try {
                    Thread.currentThread().sleep(delay);
                } catch (InterruptedException e) {
                }
            }
        }
    }
}



Код главного класса
Код

package delay;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;

/**
 * Главный класс. В данном случае он оформлен как апплет, но может запускаться
 * и как отдельное приложение
 */

public class Slide extends JApplet {
    /**
     * Кропки для запуска и остановки показа слайдов.
     */
    private JButton jButton1 = new JButton("Начать шоу");
    private JButton jButton2 = new JButton("Кончить шоу");

    /**
     * Место для показа слайдов. Вместо показа слайдов в данном примере происходит
     * изменение текста данной метки.
     */
    private JLabel label = new JLabel("Еще не начиналось", SwingConstants.CENTER);

    /**
     * Создаем диспетчера показа слайдов. В данном примере в момент создания так же создается и объект-отрисовщик.
     */
    private Slider slider = new Slider(new Drawer() {
        /**
         * три слайда для показа
         */
        private String[] slids = { "Первый слайд", "Второй слайд", "Третий слайд" };

        /**
         * Номер текущего слайда
         */
        private int currSlide = 0;

        /**
         * Строка, которую следует вывести.
         * Эта переменная необходима, поскольку отрисовка и переход к следующему слайду не синхронизируются и
         * обрабатываются в разных потоках.
         */
        private String string;

        @Override
        public boolean drawNextSlide() {
            // считываем очередную строку для показа
            string = slids[currSlide++];
            // вызываем процедуру отрисовки. Поскольку данный метод обрабатывается не в потоке обработки событий
            // необходимо создать "обертку" - поставить в очередь обработки событий смену текста метки.
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    label.setText(string);
                }
            });
            // смена номера слайда
            if (currSlide == 3)
                currSlide = 0;
            // поскольку в нашем случае показ слайдов зациклен, всегда возвращаем требование продолжения показа.
            return true;
        }
    });

    public Slide() {
    }

    // процедура инициации приложения.

    private void jbInit() throws Exception {
        this.getContentPane().setLayout(null);
        this.setSize(new Dimension(400, 137));
        jButton1.setBounds(new Rectangle(45, 20, 130, 20));
        jButton1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                jButton1_actionPerformed(e);
            }
        });
        jButton2.setBounds(new Rectangle(210, 20, 135, 20));
        jButton2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                jButton2_actionPerformed(e);
            }
        });
        label.setBounds(new Rectangle(115, 85, 120, 15));
        this.getContentPane().add(label, null);
        this.getContentPane().add(jButton2, null);
        this.getContentPane().add(jButton1, null);
    }

    public void start() {
        // Создание отдельного потока, который будет отвечать за показ слайдов
        Thread th = new Thread(slider);
        // Запуск созданного потока
        th.start();
    }

    public void init() {
        try {
            jbInit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // процедура инициации приложения для старта вне html страницы.

    public static void main(String[] args) {
        Slide applet = new Slide();
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(applet, BorderLayout.CENTER);
        frame.setTitle("Applet Frame");
        applet.init();
        applet.start();
        frame.setSize(400, 150);
        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension frameSize = frame.getSize();
        frame.setLocation((d.width - frameSize.width) / 2, (d.height - frameSize.height) / 2);
        frame.setVisible(true);
    }

    // запуск показа слайдов

    private void jButton1_actionPerformed(ActionEvent e) {
        slider.setGo(true);
    }

    // остановка показа слайдов

    private void jButton2_actionPerformed(ActionEvent e) {
        slider.setGo(false);
    }
}



Этот вариант работает достаточно быстро и не приводит к зависанию пользовательского интерфейса при продолжительной процедуре получения
нового слайда.


Второй вариант процедуры использует таймер из пакета javax.swing.Timer.
События этого таймера обрабатываются в потоке событий, поетому при вызове методов, именяющих графический интерфейс, не нужно предпринимать специальных мер по передаче событий в этот поток.
код примера с таймером
Код

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

public class SlideShow extends JFrame implements ActionListener {

    private Timer timer = new Timer(1000, this);
    private JLabel slideHolder = new JLabel("<Hit start to launch the show>");
    private String[] slides = {"Slide 1", "Slide 2", "Slide 3"};
    private int currSlide = 0;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new SlideShow().setVisible(true);
            }
        });
    }

    public SlideShow() {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(200, 100);
        JPanel contentPane = new JPanel();
        contentPane.add(slideHolder);
        JButton start = new JButton("Start");
        JButton stop = new JButton("Stop");
        start.addActionListener(this);
        stop.addActionListener(this);
        start.setActionCommand("start");
        stop.setActionCommand("stop");
        contentPane.add(start);
        contentPane.add(stop);
        this.setContentPane(contentPane);
        this.setVisible(true);

    }

    public void actionPerformed(ActionEvent e) {
        if ("start".equals(e.getActionCommand())) {
            timer.start();
        } else if ("stop".equals(e.getActionCommand())) {
            timer.stop();
        } else { // timer event
            if (currSlide == 3) currSlide = 0;
            slideHolder.setText(slides[currSlide++]);
        }
    }
}





--------------------
Mirkes
PM MAIL   Вверх
jk1
Дата 29.9.2011, 11:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 21
Всего: 75



Цитата

Вариант с таймером из  java.util.Timer мне не до конца понятен.

Вот пример реализации на java.util.Timer
Код

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.TimerTask;

public class SlideShow extends JFrame implements ActionListener {

    private java.util.Timer timer = new java.util.Timer();
    private JLabel slideHolder = new JLabel("<Hit start to launch the show>");
    private String[] slides = {"Slide 1", "Slide 2", "Slide 3"};
    private int currSlide = 0;

    private TimerTask task = null;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new SlideShow().setVisible(true);
            }
        });
    }

    public SlideShow() {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(200, 100);
        JPanel contentPane = new JPanel();
        contentPane.add(slideHolder);
        JButton start = new JButton("Start");
        JButton stop = new JButton("Stop");
        start.addActionListener(this);
        stop.addActionListener(this);
        start.setActionCommand("start");
        stop.setActionCommand("stop");
        contentPane.add(start);
        contentPane.add(stop);
        this.setContentPane(contentPane);
        this.setVisible(true);

    }

    public void actionPerformed(ActionEvent e) {
        if ("start".equals(e.getActionCommand())) {
            task = new TimerTask() {
                public void run() {
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            if (currSlide == 3) currSlide = 0;
                            slideHolder.setText(slides[currSlide++]);
                        }
                    });
                }
            };
            timer.schedule(task, 1000, 1000);
        } else if ("stop".equals(e.getActionCommand())) {
            task.cancel();
        }
    }
}



--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
Mirkes
Дата 29.9.2011, 15:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Теперь есть все примеры. Если это необходимо перенести в FAQ, это должен сделать кто-то ответственный (уполномоченный).  Кто может это сделать?


--------------------
Mirkes
PM MAIL   Вверх
jk1
Дата 30.9.2011, 06:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 21
Всего: 75



Цитата

Если это необходимо перенести в FAQ, это должен сделать кто-то ответственный (уполномоченный).  Кто может это сделать? 

Необязательно. Статью в базу знаний может написать любой пользователь форума.

Это сообщение отредактировал(а) jk1 - 11.10.2011, 21:56


--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
Mirkes
Дата 30.9.2011, 06:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Забавно, но у меня при переходе по ссылке получен ответ "Internet Explorer не может отобразить эту веб-страницу". Переходил с разных ссылок. В чем дело? Козлит IE или упала база?


--------------------
Mirkes
PM MAIL   Вверх
Mirkes
Дата 11.10.2011, 18:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 2
Всего: 17



Необходимо поменять ссылки на базу знаний: www.base.vingrad.ru вместо стоящей сейчас base.vingrad.ru. В IE и GoogleChrome указанная на данный момент ссылка не работает.

Большое спасибо всем, принявшим участие в обсуждении.
Результаты выложил в FAQ.


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

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

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


 




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


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

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