|
| 1 | + |
| 2 | +//The third day, there was a marriage in Cana of Galilee. Jesus' mother was there. (John 2:1) |
| 3 | + |
| 4 | +package com.javarush.task.task30.task3008.client; |
| 5 | + |
| 6 | +import javax.swing.*; |
| 7 | +import java.awt.*; |
| 8 | +import java.awt.event.ActionEvent; |
| 9 | +import java.awt.event.ActionListener; |
| 10 | + |
| 11 | +public class ClientGuiView { |
| 12 | + private final ClientGuiController controller; |
| 13 | + |
| 14 | + private JFrame frame = new JFrame("Чат"); |
| 15 | + private JTextField textField = new JTextField(50); |
| 16 | + private JTextArea messages = new JTextArea(10, 50); |
| 17 | + private JTextArea users = new JTextArea(10, 10); |
| 18 | + |
| 19 | + public ClientGuiView(ClientGuiController controller) { |
| 20 | + this.controller = controller; |
| 21 | + initView(); |
| 22 | + } |
| 23 | + |
| 24 | + private void initView() { |
| 25 | + textField.setEditable(false); |
| 26 | + messages.setEditable(false); |
| 27 | + users.setEditable(false); |
| 28 | + |
| 29 | + frame.getContentPane().add(textField, BorderLayout.NORTH); |
| 30 | + frame.getContentPane().add(new JScrollPane(messages), BorderLayout.WEST); |
| 31 | + frame.getContentPane().add(new JScrollPane(users), BorderLayout.EAST); |
| 32 | + frame.pack(); |
| 33 | + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); |
| 34 | + frame.setVisible(true); |
| 35 | + |
| 36 | + textField.addActionListener(new ActionListener() { |
| 37 | + public void actionPerformed(ActionEvent e) { |
| 38 | + controller.sendTextMessage(textField.getText()); |
| 39 | + textField.setText(""); |
| 40 | + } |
| 41 | + }); |
| 42 | + } |
| 43 | + |
| 44 | + public String getServerAddress() { |
| 45 | + return JOptionPane.showInputDialog( |
| 46 | + frame, |
| 47 | + "Введите адрес сервера:", |
| 48 | + "Конфигурация клиента", |
| 49 | + JOptionPane.QUESTION_MESSAGE); |
| 50 | + } |
| 51 | + |
| 52 | + public int getServerPort() { |
| 53 | + while (true) { |
| 54 | + String port = JOptionPane.showInputDialog( |
| 55 | + frame, |
| 56 | + "Введите порт сервера:", |
| 57 | + "Конфигурация клиента", |
| 58 | + JOptionPane.QUESTION_MESSAGE); |
| 59 | + try { |
| 60 | + return Integer.parseInt(port.trim()); |
| 61 | + } catch (Exception e) { |
| 62 | + JOptionPane.showMessageDialog( |
| 63 | + frame, |
| 64 | + "Был введен некорректный порт сервера. Попробуйте еще раз.", |
| 65 | + "Конфигурация клиента", |
| 66 | + JOptionPane.ERROR_MESSAGE); |
| 67 | + } |
| 68 | + } |
| 69 | + } |
| 70 | + |
| 71 | + public String getUserName() { |
| 72 | + return JOptionPane.showInputDialog( |
| 73 | + frame, |
| 74 | + "Введите ваше имя:", |
| 75 | + "Конфигурация клиента", |
| 76 | + JOptionPane.QUESTION_MESSAGE); |
| 77 | + } |
| 78 | + |
| 79 | + public void notifyConnectionStatusChanged(boolean clientConnected) { |
| 80 | + textField.setEditable(clientConnected); |
| 81 | + if (clientConnected) { |
| 82 | + JOptionPane.showMessageDialog( |
| 83 | + frame, |
| 84 | + "Соединение с сервером установлено", |
| 85 | + "Чат", |
| 86 | + JOptionPane.INFORMATION_MESSAGE); |
| 87 | + } else { |
| 88 | + JOptionPane.showMessageDialog( |
| 89 | + frame, |
| 90 | + "Клиент не подключен к серверу", |
| 91 | + "Чат", |
| 92 | + JOptionPane.ERROR_MESSAGE); |
| 93 | + } |
| 94 | + |
| 95 | + } |
| 96 | + |
| 97 | + public void refreshMessages() { |
| 98 | + messages.append(controller.getModel().getNewMessage() + "\n"); |
| 99 | + } |
| 100 | + |
| 101 | + public void refreshUsers() { |
| 102 | + ClientGuiModel model = controller.getModel(); |
| 103 | + StringBuilder sb = new StringBuilder(); |
| 104 | + for (String userName : model.getAllUserNames()) { |
| 105 | + sb.append(userName).append("\n"); |
| 106 | + } |
| 107 | + users.setText(sb.toString()); |
| 108 | + } |
| 109 | +} |
| 110 | + |
| 111 | +/* |
| 112 | +Чат (21) |
| 113 | +У меня есть отличнейшая новость для тебя. Компонент представление (View) уже готов. Я добавил класс ClientGuiView. Он использует библиотеку javax.swing. Ты должен как следует разобраться в каждой строчке этого класса. Если тебе все понятно – это замечательно, если нет – обязательно найди ответы на свои вопросы с помощью дебага, документации или поиска в Интернет. |
| 114 | +
|
| 115 | +Осталось написать компонент контроллер (Controller): |
| 116 | +1. Создай класс ClientGuiController унаследованный от Client. |
| 117 | +2. Создай и инициализируй поле, отвечающее за модель ClientGuiModel model. |
| 118 | +3. Создай и инициализируй поле, отвечающее за представление ClientGuiView view. Подумай, что нужно передать в конструктор при инициализации объекта. |
| 119 | +4. Добавь внутренний класс GuiSocketThread унаследованный от SocketThread. Класс GuiSocketThread должен быть публичным. В нем переопредели следующие методы: |
| 120 | +а) void processIncomingMessage(String message) – должен устанавливать новое сообщение у модели и вызывать обновление вывода сообщений у представления. |
| 121 | +б) void informAboutAddingNewUser(String userName) – должен добавлять нового пользователя в модель и вызывать обновление вывода пользователей у отображения. |
| 122 | +в) void informAboutDeletingNewUser(String userName) – должен удалять пользователя из модели и вызывать обновление вывода пользователей у отображения. |
| 123 | +г) void notifyConnectionStatusChanged(boolean clientConnected) – должен вызывать аналогичный метод у представления. |
| 124 | +5. Переопредели методы в классе ClientGuiController: |
| 125 | +а) SocketThread getSocketThread() – должен создавать и возвращать объект типа GuiSocketThread. |
| 126 | +б) void run() – должен получать объект SocketThread через метод getSocketThread() и вызывать у него метод run(). Разберись, почему нет необходимости вызывать метод run в отдельном потоке, как мы это делали для консольного клиента. |
| 127 | +в) getServerAddress(), getServerPort(), getUserName(). Они должны вызывать одноименные методы из представления (view). |
| 128 | +6. Реализуй метод ClientGuiModel getModel(), который должен возвращать модель. |
| 129 | +7. Реализуй метод main(), который должен создавать новый объект ClientGuiController и вызывать у него метод run(). |
| 130 | +Запусти клиента с графическим окном, нескольких консольных клиентов и убедись, что |
| 131 | +все работает корректно. |
| 132 | +
|
| 133 | +
|
| 134 | +Требования: |
| 135 | +1. В пакете client должен быть корректно объявлен класс ClientGuiController и вложенный в него класс GuiSocketThread. |
| 136 | +2. В классе ClientGuiController должны быть корректно объявлены и инициализированы поля перечисленные в условии задачи. |
| 137 | +3. Метод processIncomingMessage должен быть реализован в классе GuiSocketThread в соответствии с условием задачи. |
| 138 | +4. Метод informAboutAddingNewUser должен быть реализован в классе GuiSocketThread в соответствии с условием задачи. |
| 139 | +5. Метод informAboutDeletingNewUser должен быть реализован в классе GuiSocketThread в соответствии с условием задачи. |
| 140 | +6. Метод notifyConnectionStatusChanged должен быть реализован в классе GuiSocketThread в соответствии с условием задачи. |
| 141 | +7. Метод getSocketThread в классе ClientGuiController должен возвращать новый объект типа GuiSocketThread. |
| 142 | +8. Метод run в классе ClientGuiController должен получать объект SocketThread через метод getSocketThread и вызывать у него метод run. |
| 143 | +9. Методы getServerAddress, getServerPort, getUserName в классе ClientGuiController должны вызывать соответствующие методы у объекта view. |
| 144 | +10. Метод getModel в классе ClientGuiController должен возвращать значение поля model. |
| 145 | +11. Метод main в классе ClientGuiController должен создавать новый объект типа ClientGuiController и вызывать у него метод run. |
| 146 | +12. Класс ClientGuiController должен быть потомком класса Client. |
| 147 | +*/ |
0 commit comments