Как пофиксить баг при работе с несколькими окнами? Java Swing?

В общем, есть приложение, написанное с использованием MVC. Набросал простой пример (баг в наличии) как оно работает. Java только начинаю осваивать, а с MVC вообще ни разу не работал.



В общем, получается, что после нескольких переключений между окнами пункты в менюшке всё накапливаются, и накапливаеюся… Думаю, это не единственный косяк, но сразу бросающийся в глаза — именно этот.



И вообще, был бы рад, если бы кто-нибудь объяснил как сделать правильно переключение окон в моем случае, ибо понимаю, что неправильно, но как сделать правильно — не знаю.



TestSwing.java
public class TestSwing {<br>
    public static void main(String[] args) {<br>
        FirstModel model = new FirstModel();<br>
<br>
        FirstController controller = new FirstController(model);<br>
<br>
        FirstWindow window = new FirstWindow(controller);<br>
<br>
        controller.setView(window);<br>
<br>
        window.run();<br>
<br>
    }<br>
}<br>






Window.java
import javax.swing.*;<br>
import java.awt.event.ActionEvent;<br>
import java.awt.event.ActionListener;<br>
<br>
public class Window extends JFrame {<br>
    private static Window window = null;<br>
<br>
    private Window() {<br>
        this.setTitle("My window");<br>
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);<br>
<br>
        JMenuBar test = new JMenuBar();<br>
<br>
        JMenu testMenu = new JMenu("test");<br>
<br>
        JMenuItem testMenuItem = new JMenuItem("test");<br>
        testMenuItem.addActionListener(new ActionListener() {<br>
            @Override<br>
            public void actionPerformed(ActionEvent e) {<br>
                JOptionPane.showMessageDialog(Window.this, "Message");<br>
            }<br>
        });<br>
        testMenu.add(testMenuItem);<br>
        test.add(testMenu);<br>
<br>
        this.setJMenuBar(test);<br>
    }<br>
<br>
    public static Window getInstance() {<br>
        if(window == null) {<br>
            window = new Window();<br>
        }<br>
<br>
        return window;<br>
    }<br>
}<br>
<br>






FirstController.java
import java.awt.event.MouseEvent;<br>
import java.awt.event.MouseListener;<br>
<br>
public class FirstController implements MouseListener {<br>
    private FirstModel model = null;<br>
    private FirstWindow window = null;<br>
<br>
    public FirstController(FirstModel model) {<br>
        this.model = model;<br>
    }<br>
<br>
    public void setView(FirstWindow window) {<br>
        this.window = window;<br>
    }<br>
<br>
    public String getData() {<br>
        return this.model.getFirstData();<br>
    }<br>
<br>
    @Override<br>
    public void mouseClicked(MouseEvent e) {<br>
        if(e.getButton() == 1) {<br>
            this.window.close();<br>
<br>
            SecondModel model = new SecondModel();<br>
            SecondController controller = new SecondController(model);<br>
            SecondWindow window = new SecondWindow(controller);<br>
            controller.setView(window);<br>
            window.run();<br>
        }<br>
    }<br>
<br>
    @Override<br>
    public void mousePressed(MouseEvent e) {<br>
<br>
    }<br>
<br>
    @Override<br>
    public void mouseReleased(MouseEvent e) {<br>
<br>
    }<br>
<br>
    @Override<br>
    public void mouseEntered(MouseEvent e) {<br>
<br>
    }<br>
<br>
    @Override<br>
    public void mouseExited(MouseEvent e) {<br>
<br>
    }<br>
}<br>
<br>






FirstModel.java
public class FirstModel {<br>
    public String getFirstData() {<br>
        return "First data";<br>
    }<br>
}<br>






FirstWindow.java
import javax.swing.*;<br>
import java.awt.event.ActionEvent;<br>
import java.awt.event.ActionListener;<br>
<br>
public class FirstWindow extends JPanel {<br>
    private FirstController controller = null;<br>
    private Window window = Window.getInstance();<br>
<br>
    public FirstWindow(FirstController controller) {<br>
        this.window.setTitle("First window");<br>
<br>
        this.controller = controller;<br>
<br>
        JButton button = new JButton("New window");<br>
        button.addMouseListener(controller);<br>
        this.add(button);<br>
<br>
        JMenuBar menu = this.window.getJMenuBar();<br>
<br>
        JMenuItem firstData = new JMenuItem("Show data");<br>
        firstData.addActionListener(new ActionListener() {<br>
            @Override<br>
            public void actionPerformed(ActionEvent e) {<br>
                JOptionPane.showMessageDialog(FirstWindow.this, FirstWindow.this.controller.getData(), "Text", JOptionPane.INFORMATION_MESSAGE);<br>
<br>
            }<br>
        });<br>
        menu.getMenu(0).add(firstData);<br>
    }<br>
<br>
    public void run() {<br>
        this.window.setContentPane(this);<br>
        this.window.setVisible(true);<br>
    }<br>
<br>
    public void close() {<br>
        this.setVisible(false);<br>
    }<br>
}<br>






SecondController.java
import java.awt.event.MouseEvent;<br>
import java.awt.event.MouseListener;<br>
<br>
public class SecondController implements MouseListener {<br>
    private SecondModel model = null;<br>
    private SecondWindow window = null;<br>
<br>
    public SecondController(SecondModel model) {<br>
        this.model = model;<br>
    }<br>
<br>
    public String getData() {<br>
        return this.model.getSecondData();<br>
    }<br>
<br>
    public void setView(SecondWindow window) {<br>
        this.window = window;<br>
    }<br>
<br>
    @Override<br>
    public void mouseClicked(MouseEvent e) {<br>
        if(e.getButton() == 1) {<br>
            this.window.close();<br>
<br>
            TestSwing.main(null);<br>
        }<br>
    }<br>
<br>
    @Override<br>
    public void mousePressed(MouseEvent e) {<br>
<br>
    }<br>
<br>
    @Override<br>
    public void mouseReleased(MouseEvent e) {<br>
<br>
    }<br>
<br>
    @Override<br>
    public void mouseEntered(MouseEvent e) {<br>
<br>
    }<br>
<br>
    @Override<br>
    public void mouseExited(MouseEvent e) {<br>
<br>
    }<br>
}<br>
<br>






SecondModel.java
public class SecondModel {<br>
    public String getSecondData() {<br>
        return "Second data!";<br>
    }<br>
}<br>
<br>






SecondWindow.java
import javax.swing.*;<br>
import java.awt.event.ActionEvent;<br>
import java.awt.event.ActionListener;<br>
<br>
public class SecondWindow extends JPanel {<br>
    private SecondController controller = null;<br>
    private Window window = Window.getInstance();<br>
<br>
    public SecondWindow(SecondController controller) {<br>
        this.window.setTitle("Second window");<br>
        this.controller = controller;<br>
<br>
        JMenuBar menu = this.window.getJMenuBar();<br>
<br>
        JMenuItem secondData = new JMenuItem("Show data");<br>
        secondData.addActionListener(new ActionListener() {<br>
            @Override<br>
            public void actionPerformed(ActionEvent e) {<br>
                JOptionPane.showMessageDialog(SecondWindow.this, SecondWindow.this.controller.getData(), "Text", JOptionPane.INFORMATION_MESSAGE);<br>
<br>
            }<br>
        });<br>
        menu.getMenu(0).add(secondData);<br>
<br>
        JButton close = new JButton("Return to first window");<br>
        close.addMouseListener(controller);<br>
<br>
        this.add(close);<br>
    }<br>
<br>
    public void run() {<br>
        this.window.setContentPane(this);<br>
        this.window.setVisible(true);<br>
    }<br>
<br>
    public void close() {<br>
        this.setVisible(false);<br>
    }<br>
}<br>
<br>






Сразу скажу, что не надо оставлять комментариев в духе «А зачем вам вообще MVC, напишите лучше так… и так ...» и «Зачем контроллер сделан MouseListener'ом, почему бы не написать просто анонимные классы?» Эти вопросы к делу не относятся, а написал я так, потому что так надо.
  • Вопрос задан
  • 3423 просмотра
Пригласить эксперта
Ответы на вопрос 1
serso
@serso
Window синглетоном по дизайну?
Помимо Window.getInstance() можно написать Window.getBareInstance(), внутри которого дёграть Window.getInstance() и зачищать данные от предидущего «окна», включая менюшки, контент и т.д.

Ответ на вопрос: менюшки остаются поотому-что вы их сами добваляете в ОДИН экземпляр класса Window (внутри конструкторов FirstWindow и SecondWindow) и не очищаете. Выход — либо зачищать объект window по выходу из вью (в вашем случае по переходу между окнами), либо по входу в новую вью (то что я написал выше)
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы