LINUX.ORG.RU

Как связать Gui и обработку введенной информации?

 , ,


1

3

Доброго времени суток. Столкнулся с проблемой. Пусть у меня есть Gui, с textField, по нажатию кнопки я считываю то, что в textField и хочу отдавать это обработчику, а обработчик - отдельный класс в программе. Как мне связать Gui и обработку?Потому что сейчас Gui живет отдельно в своем Thread-е, а обработчик в своем, как организовать пересылку? Пробовал static переменные, пробовал get-ры, но это все не то. Прошу помощи.

Пользуюсь Swing.

Заранее спасибо!

Swing живет с своем event dispatch thread, работать с элементами интерфейса из других тредов напрямую нельзя. Передать данные из GUI в другой поток не проблема. В обратную сторону нужно засылать задачи через SwingUtilities.invokeLater.

stevejobs ★★★★☆ ()

чисто для примеру:

public class Main {
    public static void main(String[] args) throws InterruptedException {
        final AtomicReference<String> result = new AtomicReference<String>();
        final CountDownLatch latch = new CountDownLatch(1);

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                String input = JOptionPane.showInputDialog(null, "Stop?", "Stop?", JOptionPane.QUESTION_MESSAGE);
                result.set(input);

                latch.countDown();
            }
        });

        latch.await();
        System.out.println(result.get());
    }
}

вместо latch можно заюзать SwingUtilities.invokeAndWait()

stevejobs ★★★★☆ ()
Ответ на: комментарий от stevejobs
setSize(400, 400);
        setLayout(new BorderLayout());

        JButton sendSubcrButton = new JButton("Send");

        JTextField subscrLine = new JTextField(50);

        JLabel label = new JLabel("Enter your data here:");
        JPanel inputPanel = new JPanel();
        inputPanel.add(label);
        inputPanel.add(subscrLine);

        add(inputPanel, BorderLayout.PAGE_START);
        add(sendSubcrButton, BorderLayout.PAGE_END);

        pack();
        setResizable(false);

        sendSubcrButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (e.getSource() == sendSubcrButton)
                {
                    subscribe = subscrLine.getText();
                }
            }
        });

        setLocationRelativeTo(null);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }

Не очень понимаю, как мне данные отсюда получить в другом месте? Чтобы по нажатию на send считывалось все и отправлялось. Поясните, пожалуйста.

aarexer ()
Ответ на: комментарий от stevejobs

Вместо latch в такой конструкции разумнее использовать SettableFuture например

maxcom ★★★★★ ()
Ответ на: комментарий от aarexer

Другое место это у тебя что, отдельный тред? Или просто функция которую нужно выполнить вне event thread?

maxcom ★★★★★ ()
Ответ на: комментарий от maxcom

Ну вообще отдельный тред. Есть Main класс, есть Gui, мне надо переслать из Gui(из EDT) в Main то, что я ввел в текстфилд(при нажатии send) и просто пускай вывести в консольный оутпут. Не могу разобраться с обменом данными между ними, говорю же..

aarexer ()
Ответ на: комментарий от maxcom

Запускаю Гуи вот так

public static void main(String[] args) throws InterruptedException
    {
        /** Gui for subscriber in edt **/
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                SubscriberGui sgui = new SubscriberGui();
                sgui.setVisible(true);
            }
        });
System.out.println(data); //где data - то, что пришло

aarexer ()
Ответ на: комментарий от aarexer

не совсем понимаю, что ты хочешь сделать, и что должно получиться в результате. Может, написал бы ты какой-то код, который не компилируется или не работает?

спроси у дурака как организовать concurrency, сам дураком станешь (с). Чтобы понять многопоточность, читай книжку Java Concurrency in Practice. А пока вот тебе для размышлений:

public class Test {
public static void main(String... args) {

    final BlockingQueue<String> queue = new LinkedBlockingQueue<String>();
    Thread running = new Thread(new Runnable() {
        @Override
        public void run() {
            while (true) {
                try {
                    String data = queue.take();
                    //handle the data
                } catch (InterruptedException e) {
                    System.err.println("Error occurred:" + e);
                }
            }
        }
    });

    running.start();
    // Send data to the running thread
    for (int i = 0; i < 10; i++) {
        queue.offer("data " + i);
    }
}
}
stevejobs ★★★★☆ ()

Как я понял, всё упирается в пересылку данных между потоками*, а GUI здесь — просто частный случай. Для реализации безопасного межпоточного взаимодействия существует множество средств. Можно сделать ставку на потокобезопасные коллекции. Например добавьте в обработчик блокирующую очередь** (java.util.concurrent.BlockingQueue). Тогда изнутри метода actionPerformed можно что-нибудь положить в очередь обработчика, а сам обработчик, вызывая метод очереди take, эти данные получит. Но получит только в том случае, если они есть, иначе будет ждать, что вероятно и есть желаемое поведение.

________________
* http://en.wikipedia.org/wiki/Producer–consumer_problem
** http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingQueue.html

CARS ★★★★ ()
Последнее исправление: CARS (всего исправлений: 1)
Ответ на: комментарий от stevejobs

Гуи:

public class SubscriberGui extends JFrame
{
    private String subscribe = "";
    private String answer;

    public SubscriberGui()
    {
        super("Frame");
        initGui();
    }

    private void initGui()
    {
        setSize(400, 400);
        setLayout(new BorderLayout());

        JButton sendSubcrButton = new JButton("Send");

        JTextField subscrLine = new JTextField(50);

        JLabel label = new JLabel("Enter your data here:");
        JPanel inputPanel = new JPanel();
        inputPanel.add(label);
        inputPanel.add(subscrLine);

        add(inputPanel, BorderLayout.PAGE_START);
        add(sendSubcrButton, BorderLayout.PAGE_END);

        pack();
        setResizable(false);

        sendSubcrButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (e.getSource() == sendSubcrButton)
                {
                    subscribe = subscrLine.getText();
                }
            }
        });

        setLocationRelativeTo(null);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }
}

Main

public class Main
{
    public static void main(String[] args) throws InterruptedException
    {
        /** Gui in edt **/
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                SubscriberGui sgui = new SubscriberGui();
                sgui.setVisible(true);
            }
        });
System.out.println(); //тут печатать
}

Хочу написать в JTextField строку, нажать на Send и распечатать ее в main-методе класса Main обычным System.out.println().

Код написал.

Про дураков не будем говорить лучше. Книжку почитаю, спасибо, поищу на трекерах.

aarexer ()
Ответ на: комментарий от aarexer

Если твоему main thread'у нечем заняться, то можно в GUI передать SettableFuture (из guava), а в основном треде сделать .get(). Он заблокируется пока пользователь не нажмет кнопку.

maxcom ★★★★★ ()
Последнее исправление: maxcom (всего исправлений: 1)
Ответ на: комментарий от aarexer

//тут печатать

тут как раз не надо печатать, т.к. sout в этом месте выполнится в момент старта программы xD

поправил твой кот, дописал пару строчек. По быдлански, но зато используя кот только из етого треда, хехе https://gist.github.com/olegchir/280a16685eac44a13f5e

Main.java:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

class ParallelPrinter {
    final BlockingQueue<String> messageQueue;

    public ParallelPrinter(BlockingQueue<String> messageQueue) {
        this.messageQueue = messageQueue;
    }

    public void poll() {
        Thread running = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        String data = messageQueue.take();
                        System.out.println(data);
                    } catch (InterruptedException e) {
                        System.err.println("Error occurred:" + e);
                    }
                }
            }
        });
        running.start();
    }
}

class SubscriberGui extends JFrame
{
    final BlockingQueue<String> messageQueue;

    private String subscribe = "";
    private String answer;

    public SubscriberGui(BlockingQueue<String> messageQueue)
    {
        super("Frame");
        this.messageQueue = messageQueue;
        initGui();
    }

    private void initGui()
    {
        setSize(400, 400);
        setLayout(new BorderLayout());

        final JButton sendSubcrButton = new JButton("Send");

        final JTextField subscrLine = new JTextField(50);

        JLabel label = new JLabel("Enter your data here:");
        JPanel inputPanel = new JPanel();
        inputPanel.add(label);
        inputPanel.add(subscrLine);

        add(inputPanel, BorderLayout.PAGE_START);
        add(sendSubcrButton, BorderLayout.PAGE_END);

        pack();
        setResizable(false);

        sendSubcrButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (e.getSource() == sendSubcrButton)
                {
                    subscribe = subscrLine.getText();
                    messageQueue.offer(subscribe);
                }
            }
        });

        setLocationRelativeTo(null);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }
}

public class Main {
    public static void main(String[] args) throws InterruptedException {
        final BlockingQueue<String> queue = new LinkedBlockingQueue<String>();
        ParallelPrinter parallelPrinter = new ParallelPrinter(queue);
        parallelPrinter.poll();
        /** Gui in edt **/
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                SubscriberGui sgui = new SubscriberGui(queue);
                sgui.setVisible(true);
            }
        });
        System.out.println("stop"); //тут печатать
    }
}
stevejobs ★★★★☆ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.