0

I've written a code in java that solves sudokus and I used Java Applet for designing it. Now, I'm trying to use Java Swing to make it look better and to add some features like "saving" a sudoku board etc. Unfortunately, I'm not too familiar with Java Swing and I'm having some trouble using Graphics(to draw the board 9x9). I also don't understand why I can't extend JFrame and JPanel at the same class.

import java.applet.*;

import javax.swing.*;
import javax.swing.border.*;

import java.awt.*;
import java.awt.event.*;
import java.net.URL;
import java.util.Scanner;

class Sudoku2 extends JPanel implements ActionListener, MouseListener,
        ItemListener {

    public JPanel createContentPane() {

        JPanel GUI = new JPanel();
        GUI.setLayout(null);

        JPanel titlePanel = new JPanel();
        titlePanel.setLayout(null);
        titlePanel.setLocation(10, 0);
        titlePanel.setSize(250, 30);
        GUI.add(titlePanel);

        JPanel scorePanel = new JPanel();
        scorePanel.setLayout(null);
        scorePanel.setLocation(10, 40);
        scorePanel.setSize(250, 30);
        GUI.add(scorePanel);

        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(null);
        buttonPanel.setLocation(0, 0);
        buttonPanel.setSize(300, 200);
        GUI.add(buttonPanel);

        JButton solve = new JButton("Solve");
        solve.setLocation(20, 100);
        solve.setSize(100, 30);
        buttonPanel.add(solve);

        JButton clear_digit = new JButton("Clear Digit");
        clear_digit.setLocation(20, 140);
        clear_digit.setSize(100, 30);
        buttonPanel.add(clear_digit);

        GUI.setOpaque(true);
        return GUI;
    }

    public JMenuBar createMenuBar() {

        JMenuBar menuBar = new JMenuBar();

        JMenu Menu = new JMenu("File");
        menuBar.add(Menu);

        JMenuItem new1 = new JMenuItem("New");
        new1.addActionListener(this);
        JMenuItem load = new JMenuItem("Load");
        load.addActionListener(this);
        JMenuItem save1 = new JMenuItem("Save");
        save1.addActionListener(this);
        JMenuItem save2 = new JMenuItem("Save As...");
        save2.addActionListener(this);

        Menu.add(new1);
        Menu.add(load);
        Menu.add(save1);
        Menu.add(save2);

        return menuBar;
    }

    private static void createAndShowGUI() {

        JFrame frame = new JFrame("Sudoku Solver");

        Sudoku2 demo = new Sudoku2();

        frame.setJMenuBar(demo.createMenuBar());

        frame.setContentPane(demo.createContentPane());

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setSize(500, 500);

        frame.setVisible(true);
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.drawLine(50, 50, 100, 100);
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mousePressed(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseReleased(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseExited(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    public void actionPerformed(ActionEvent e) {

    }

    public void itemStateChanged(ItemEvent e) {

    }

    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();

            }
        });

    }

}
`
  • "The designers of Java decided that multiple inheritance created too many problems for programmers and compiler writers, and decided that a single inheritance model was better overall." – Qiu Apr 06 '14 at 07:08
  • Because a JPanel and a JFrame are not the same thing. If an object "is a" panel, then it "is not a" frame, and vice versa. – Dawood ibn Kareem Apr 06 '14 at 07:10
  • There's a lot of things wrong here and I don't really get David's comment--anyway. First, you extend JPanel, why? What is this panel? Shouldn't your Sudoku panel be a bunch of sub-panels each of which is the square that may be modified (you can use a Border to indicate selected or not). The playing board, (imo), should be a bunch of a `JComponents`s (or `JPanel`'s--I have yet to understand the difference) each of which contains either a blank `JLabel` or a `JLabel` which contains the number of the current tile. – Jared Apr 06 '14 at 07:16
  • 1
    Remember, `JPanel` is opaque, that means, if you put it on top of something, it will cover it. You should also make appropriate use of [layout manager](http://docs.oracle.com/javase/tutorial/uiswing/layout/index.html) and save yourself a lot of hair pulling – MadProgrammer Apr 06 '14 at 07:17
  • @Jared `JComponent` is `abstract` and by default is transparent, `JPanel` is a concrete implementation of `JComponent` that is opaque by default – MadProgrammer Apr 06 '14 at 07:19
  • @MadProgrammer You can extend `JComponent`--I do it all the time (it's not abstract). Everything I have ever done, I can substitute `extends JComponent` for `extends JPanel` with no difference. – Jared Apr 06 '14 at 07:19
  • 1
    @Jared `public abstract class JComponent` would suggest otherwise, yes, of course you can extend it, you can extend any class that's not `final`, you just can't insensate it on it's own. *"I can substitute extends JComponent for extends JPanel with no difference"* - The difference is, one is transparent by default and one is not. The difference will come down to what it is you want to achieve. `JPanel` also provides accessibility and look and feel support (via the `set/getUI`) – MadProgrammer Apr 06 '14 at 07:26
  • @MadProgrammer I am telling you that I have implemented GUIs where I have _never_ used `extends JPanel` (as opposed to `extends JComponent`). Perhaps that is because I'm implementing them in the proper way--I don't know. I have yet to have a satisfactory explanation of the difference--perhaps you can give one. If you look at the documentation, then you will see that `JComponent` while declared as an abstract class is not really an abstract class (it has no abstract methods!): http://docs.oracle.com/javase/7/docs/api/javax/swing/JComponent.html – Jared Apr 06 '14 at 07:31
  • @Jared I guess from your '*never* used `extends JPanel`' that you also did not offer the user a choice of PLAF. A panel implements `getUI()`, `setUI(PanelUI)` & `updateUI()`. – Andrew Thompson Apr 06 '14 at 07:45
  • @MadProgrammer And understand that this include _both_ custom panels (i.e. panels for which I overwrite the `paintComponent` method) _and_ panels for which I use a Layout manager to add other `JComponent`'s. – Jared Apr 06 '14 at 07:46
  • Java GUIs might have to work on a number of platforms, on different screen resolutions & using different PLAFs. As such they are not conducive to exact placement of components. To organize the components for a robust GUI, instead use layout managers, or [combinations of them](http://stackoverflow.com/a/5630271/418556), along with layout padding & borders for [white space](http://stackoverflow.com/q/17874717/418556). – Andrew Thompson Apr 06 '14 at 07:46
  • @AndrewThompson I will admit that for all of my GUIs I have used the system look and feel (i.e. I called `try{ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());}catch(Exception e){}` before any component is shown). – Jared Apr 06 '14 at 07:49
  • I would love to continue this argument (especially if it reaches a conclusion), but my original comment doesn't have to do with `JPanel` vs. `JComponent`. Should I ask a question about `JComponent` vs. `JPanel`? I honestly would love to hear a valid argument when one should be used over the other. – Jared Apr 06 '14 at 07:57
  • Thank you everyone for your time and patience. I know the code I uploaded has mistakes in it (its only the basis for my program) but that's because I have never studied this material properly, I'm kind of improvising... – user3500777 Apr 06 '14 at 19:10

2 Answers2

1

You can't extend JFrame and JPanel in one class because Java does not allow multiple inheritance.

If you are unfamiliar with Swing Graphic, you should save yourself the trouble from graphic painting.

You could do something like this to make your life easier.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class SudokuBoard extends JPanel implements 
        ActionListener, MouseListener, ItemListener {

    private JPanel board;
    JTextField[] numberFields;

    public SudokuBoard() {
        super();
        numberFields = new JTextField[81];
        board = createContentPane();
    }

    public JPanel getBoard() {
        return board;
    }

    private JPanel createContentPane() {

        JPanel board = new JPanel();
        board.setLayout(new GridLayout(9, 9, 1, 1));

        for (int i = 0; i < numberFields.length; i++) {
            numberFields[i] = new JTextField();
            numberFields[i].setHorizontalAlignment(JTextField.CENTER);
            numberFields[i].setFont(new Font("Ariel", Font.BOLD, 25));
            numberFields[i].setText((i % 9)+1+"");

            //set border
            if ((i+1) % 3 == 0) {
                numberFields[i].setBorder(BorderFactory.createMatteBorder(1, 1, 1, 5, Color.black));
            }
            if (i > 17 && i < 27) {
                numberFields[i].setBorder(BorderFactory.createMatteBorder(1, 1, 5, 1, Color.black));
            }
            if (i > 44 && i < 54) {
                numberFields[i].setBorder(BorderFactory.createMatteBorder(1, 1, 5, 1, Color.black));
            }

            board.add(numberFields[i]);
        }

        numberFields[20].setBorder(BorderFactory.createMatteBorder(1, 1, 5, 5, Color.black));
        numberFields[23].setBorder(BorderFactory.createMatteBorder(1, 1, 5, 5, Color.black));
        numberFields[26].setBorder(BorderFactory.createMatteBorder(1, 1, 5, 5, Color.black));
        numberFields[47].setBorder(BorderFactory.createMatteBorder(1, 1, 5, 5, Color.black));
        numberFields[50].setBorder(BorderFactory.createMatteBorder(1, 1, 5, 5, Color.black));
        numberFields[53].setBorder(BorderFactory.createMatteBorder(1, 1, 5, 5, Color.black));

        return board;
    }

    public JMenuBar createMenuBar() {

        JMenuBar menuBar = new JMenuBar();

        JMenu Menu = new JMenu("File");
        menuBar.add(Menu);

        JMenuItem new1 = new JMenuItem("New");
        new1.addActionListener(this);
        JMenuItem load = new JMenuItem("Load");
        load.addActionListener(this);
        JMenuItem save1 = new JMenuItem("Save");
        save1.addActionListener(this);
        JMenuItem save2 = new JMenuItem("Save As...");
        save2.addActionListener(this);

        Menu.add(new1);
        Menu.add(load);
        Menu.add(save1);
        Menu.add(save2);

        return menuBar;
    }

    private static void createAndShowGUI() {

        JFrame frame = new JFrame("Sudoku Solver (Try Save)");
        SudokuBoard demo = new SudokuBoard();

        frame.setJMenuBar(demo.createMenuBar());
        frame.setContentPane(demo.getBoard());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500, 500);
        frame.setVisible(true);
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mousePressed(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseReleased(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseExited(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().equals("Save")) {
            int[][] numbers = new int[9][9];
            int c = 0;
            for(int i = 0; i < numbers.length; i++) {
                for (int j = 0; j < numbers[i].length; j++) {

                    //check for non-int
                    numbers[i][j] = Integer.parseInt(numberFields[c].getText());

                    c++; //awesome!
                }
            }

            for(int i = 0; i < numbers.length; i++) {
                System.out.print("[");
                for (int j = 0; j < numbers[i].length; j++) {
                    System.out.print(numbers[i][j]+" ");
                }
                System.out.println("]");
            }

            //save this 2-d array

            System.out.println("Saving...");
        }
    }

    public void itemStateChanged(ItemEvent e) {

    }

    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
0

I'm Pretty sure you don't need to extend both - and also you don't need to extend JPanel if you have JPanel GUI = new JPanel(); so if you get rid of extends JPanel you can extend JFrame.

Sam
  • 1
  • 4