Как получить доступ к нескольким JPanels внутри JFrame?
-
11-07-2019 - |
Вопрос
У меня есть JFrame
который содержит "дисплей" JPanel
с JTextField
и "контроль" JPanel
с кнопками, которые должны обеспечивать доступ к содержимому дисплея JPanel
.Я думаю, что моя проблема связана с тем, как использовать шаблон observer, который в принципе я понимаю.Вам нужно разместить прослушиватели и обновлять сообщения, но я понятия не имею, куда их поместить, как получить доступ с одной панели на другую и, возможно, при необходимости ввести класс "datamodel".Например, я хочу получить доступ к содержимому JTextField
с панели управления, и я использую анонимный прослушиватель действий следующим образом:
JButton openfile = new JButton("Convert file");
openfile.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
openButtonPressed();
}
});
Решение
Вам нужно уменьшить связь между этими объектами.
У вас может быть главный объект, которому принадлежат все текстовые поля и кнопка (панели не имеют значения)
Затем отдельный мастер действий в этом главном объекте (я называю его медиатором, см. шаблон медиатора)
Этот слушатель действия выполняет метод посредника, который, в свою очередь, берет значения из текстовых полей и, возможно, создает объект передачи. Р>
Таким образом, вы уменьшаете связь между панелями, текстовыми полями и т. д. и оставляете элемент управления в одном месте (посреднике), то есть вы не позволяете им узнать друг друга. Р>
Вы можете взглянуть на код в этом вопросе: https://stackoverflow.com/questions/324554/#324559
Это показывает эти понятия в работающем коде. Р>
Кстати, шаблон наблюдателя уже реализован в JTextField, JButton, ActionListener и т. д. Вам просто нужно добавить хуки. Р>
Надеюсь, это поможет.
РЕДАКТИРОВАТЬ . Объединили два ответа в один.
Это код.
class App { // this is the mediator
// GUI components.
private JFrame frame;
private JTextField name;
private JTextField count;
private JTextField date;
// Result is displayed here.
private JTextArea textArea;
// Fired by this button.
private JButton go;
private ActionListener actionListener;
public App(){
actionListener = new ActionListener(){
public void actionPerformed( ActionEvent e ){
okButtonPressed();
}
};
}
private void okButtonPressed(){
// template is an object irrelevant to this code.
template.setData( getData() );
textArea.setText( template.getTransformedData() );
}
public void initialize(){
frame = new JFrame("Code challenge v0.1");
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
name = new JTextField();
count = new JTextField();
date = new JTextField();
textArea = new JTextArea();
go = new JButton("Go");
go.addActionListener( actionListener ); // prepare the button.
layoutComponents(); // a lot of panels are created here. Irrelevant.
}
}
Полный и работающий код можно получить здесь:
Важно отдавать предпочтение композиции, а не наследованию, когда это возможно. Р>
Другие советы
Это делает код чище, если вы создаете модели в одном слое и добавляете один или два слоя выше для создания компонентов и макета. Конечно, не расширять подобные JFrame
и JPanel
.
Не нужно, чтобы иерархия композиции в слое модели точно соответствовала отображению. Тогда нужно просто взять текст из Document
и выполнить соответствующую операцию.
Хорошо, Perhpas не так просто. Модели Swing немного грязные. В частности, ButtonModel поврежден мозгом, и область кода контроллера может быть не совсем чистой.
У нас есть так называемые сборщики, которые будут строить родительскую панель из дочерних элементов. В этом компоновщике у вас будет доступ ко всем подкомпонентам, которые вам нужно слушать, и вы сможете реализовать там любую логику.
Наконец, конструктор вернет родительскую панель с полной логикой.
После того, как вы получили родительскую панель, это действительно беспорядок, попадающий на дочерние компоненты и заставляющий их делать что угодно.
Спасибо.Я добавил слой datamodel, который каким-то образом обрабатывает связь между панелями.
Я также нашел эту ссылку на Listeners в JTextField полезной: