-1

I am quite new to GUI programming and I don't know how to update an object and show the change on the screen. I have a class Sudoku which extends JPanel. I have a JFrame and the sudoku is part of it. I have a button, which calls the function openFile. Here is how it is called:

private void openFileActionPerformed(java.awt.event.ActionEvent evt) {                                         
    sudoku = FileManagement.openFile(this, sudoku);
}

The sudoku object has a 9x9 grid and when I debug it it's okay, the new values are in the grid. But I don't know how to display the new values on the screen. I read a few comments and tried sudoku.validate(), sudoku.repaint() or just packing the JFrame again but it didn't work. So I would appreciate if someone tells me how to fix it. If my explanation is insufficient or unclear, please tell me what else to add in the description. Thanks!

Edit - added code:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import javax.swing.JFileChooser;
import javax.swing.JFrame;

public class Sample extends javax.swing.JFrame {
    public Sample() {
        initComponents();
    }

    private void initComponents() {
        sudoku = new sudoku.Sudoku();
        openFile = new javax.swing.JButton();

        openFile.setText("Open");
        openFile.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openFileActionPerformed(evt);
            }
        });
        /*sorry for that part - automaticlly generated, don't know how to make it less*/
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addComponent(sudoku)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(openFile)))));
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(sudoku)
                .addComponent(openFile)));
        pack();
    }                     

    private void openFileActionPerformed(java.awt.event.ActionEvent evt) {                                         
        sudoku = openFile(this, sudoku);
    }                                        

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Sample().setVisible(true);
            }
        });
    }

    private javax.swing.JButton openFile;
    private sudoku.Sudoku sudoku;                  

    public static Sudoku openFile(JFrame frame, Sudoku sudoku) {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        int result = fileChooser.showOpenDialog(frame);
        if (result == JFileChooser.CANCEL_OPTION) {
            return sudoku;
        }

        File fileName = fileChooser.getSelectedFile();

        try (ObjectInputStream input = new ObjectInputStream(new FileInputStream(fileName))) {
            sudoku = (Sudoku) input.readObject();
        } catch (IOException | ClassNotFoundException ioException) {
            System.out.println(ioException);
        }
        return sudoku;
    }
}
vixenn
  • 177
  • 2
  • 5
  • 15
  • 1
    1) For better help sooner, post a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). 2) BTW - it's likely you could use a [`CardLayout`](http://download.oracle.com/javase/8/docs/api/java/awt/CardLayout.html) as shown in [this answer](http://stackoverflow.com/a/5786005/418556). – Andrew Thompson Feb 18 '17 at 09:05

1 Answers1

1

A quick fix for the problem would be to remove the JPanel from the JFrame, change its value, and then re-add the JPanel to the JFrame. This can be seen in the example below.

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

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class PanelFix extends JFrame {
    JFrame frame = this;
    private JPanel view = a();

    PanelFix() {
        super("Panel Fix");
        setSize(400, 400);
        setLocationRelativeTo(null);
        getContentPane().add(view);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private JPanel a() {
        JPanel panel = new JPanel();
        JButton but = new JButton("Press Me");
        but.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                getContentPane().remove(view);
                view = b();
                getContentPane().add(view);
                repaint();
                validate();
            }
        });
        panel.add(but);
        return panel;
    }

    private JPanel b() {
        JPanel panel = new JPanel();
        panel.add(new JLabel("Second Panel"));
        return panel;
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> new PanelFix());
    }
}

If this does not fix the problem, like Andrew Thompson said, add an MCVE. This should allow us to help fix the exact problem you have

Community
  • 1
  • 1
Dan
  • 7,286
  • 6
  • 49
  • 114
  • 1
    That worked! Thank you very much :) – vixenn Feb 18 '17 at 09:45
  • @vixenn No problem – Dan Feb 18 '17 at 09:46
  • 1
    From the sounds of `revalidate` and `repaint` would have been simpler solution, but since the OP failed to deliver an example of their work, well never know – MadProgrammer Feb 18 '17 at 10:51
  • @MadProgrammer Where would you have put those two functions in the code? I tried placing them after `view = b();` on both `view` and the `JFrame` and it still had no effect – Dan Feb 18 '17 at 12:07
  • @Dan `invalidate` and `repaint` should follow any change which might require the layout to be changed or the UI to be updated – MadProgrammer Feb 18 '17 at 21:36
  • @MadProgrammer I agree, it's just that your last comment made it sound like you could mitigate `getContentPane().remove(view);` and `getContentPane().add(view);` by just using `revalidate()` and `repaint()`. – Dan Feb 18 '17 at 21:49
  • @dan Basically, yes, revalidate and repaint will do what remove/add finally does, but with less overhead, because you're going have revalidate the layout and repaint the container anyway – MadProgrammer Feb 18 '17 at 23:06
  • @MadProgrammer, thank you for the comment. If I understand right you suggest `openFile()` then `revalidate` then `repaint` without removing the sudoku from the JFrame (although in you next comment you say something about `invalidate` so maybe I didn't get it right). I tried it now but it did not work. – vixenn Feb 19 '17 at 20:09
  • @vixenn Take a look at [this](http://stackoverflow.com/a/9511578/4601149). That explains the difference between the different validations – Dan Feb 19 '17 at 20:12
  • 1
    @Dan Thanks! That clears things up! Does the code now satisfy the MCVE or should I add the code for the Sudoku class too? – vixenn Feb 19 '17 at 20:16
  • @vixenn *"Does the code now satisfy the MCVE"* is it a self contained example which demonstrates your problem? Does it compile? Does it run? Does it demonstrate your problem? What is `Sudoku`? - My point is, in most cases, if you're updating the contents of a container, you should only need to call `revalidate` and `repaint` to have it update, but with no context to what you are actually doing, it's impossible to know what solution is right for you – MadProgrammer Feb 19 '17 at 20:27