.
OVERVIEW, SAMPLE
Hello everyone,
I have created a basic Sudoku solver that can solve most problems fairly quickly. I still have a lot of work ahead of me to make it solve even the hardest problems, but I'd like to try to implement a basic JFrame GUI first.
I have worked with internet applets in the past, but never before with JFrames.
I want to create something similar to the image below (for starters):
-------------------------------------------------------------------------------------------------
! Sudoku Solver 1.0 - [] X !
-------------------------------------------------------------------------------------------------
! _____________ _____________ _____________ _____________ _____________ _____________ !
! | _ _ _ | _ _ _ | _ _ _ | | _ _ _ | _ _ _ | _ _ _ | !
! | !5! !_! !_! | !_! !_! !_! | !6! !_! !1! | | !5! !7! !2! | !4! !9! !3! | !6! !8! !1! | !
! | _ _ _ | _ _ _ | _ _ _ | | _ _ _ | _ _ _ | _ _ _ | !
! | !6! !_! !_! | !_! !_! !2! | !4! !_! !_! | | !6! !1! !3! | !8! !5! !2! | !4! !7! !9! | !
! | _ _ _ | _ _ _ | _ _ _ | | _ _ _ | _ _ _ | _ _ _ | !
! | !_! !_! !_! | !7! !_! !1! | !_! !_! !2! | | !8! !4! !9! | !7! !6! !1! | !3! !5! !2! | !
! -_____________-_____________-_____________- -_____________-_____________-_____________- !
! | _ _ _ | _ _ _ | _ _ _ | | _ _ _ | _ _ _ | _ _ _ | !
! | !_! !_! !4! | !_! !2! !_! | !_! !3! !_! | | !1! !6! !4! | !9! !2! !7! | !5! !3! !8! | !
! | _ _ _ | _ _ _ | _ _ _ | .---. | _ _ _ | _ _ _ | _ _ _ | !
! | !_! !3! !_! | !_! !_! !_! | !_! !9! !_! | | > | | !2! !3! !8! | !5! !1! !6! | !7! !9! !4! | !
! | _ _ _ | _ _ _ | _ _ _ | '---' | _ _ _ | _ _ _ | _ _ _ | !
! | !_! !_! !_! | !_! !4! !_! | !_! !_! !_! | | !7! !9! !5! | !3! !4! !8! | !1! !2! !6! | !
! -_____________-_____________-_____________- -_____________-_____________-_____________- !
! | _ _ _ | _ _ _ | _ _ _ | | _ _ _ | _ _ _ | _ _ _ | !
! | !_! !2! !_! | !1! !_! !5! | !9! !_! !_! | | !4! !2! !7! | !1! !8! !5! | !9! !6! !3! | !
! | _ _ _ | _ _ _ | _ _ _ | | _ _ _ | _ _ _ | _ _ _ | !
! | !_! !_! !_! | !6! !_! !_! | !_! !_! !5! | | !3! !8! !1! | !6! !7! !9! | !2! !4! !5! | !
! | _ _ _ | _ _ _ | _ _ _ | | _ _ _ | _ _ _ | _ _ _ | !
! | !_! !_! !6! | !_! !3! !_! | !_! !_! !7! | | !9! !5! !6! | !2! !3! !4! | !8! !1! !7! | !
! -_____________-_____________-_____________- -_____________-_____________-_____________- !
! !
! .-------------------------------------------------------------------------------------------. !
! | | !
! | Solved Puzzle in 9.096ms | Completely Solved: True | !
! | | !
! '-------------------------------------------------------------------------------------------' !
! !
-------------------------------------------------------------------------------------------------
.
SPECIFICS
: Left Puzzle
- 9x9 Sections should be clearly defined (lines in between; seperate boxes)
- Text boxes should only accept numbers/only allow for one number to be entered (if possible)
: Right Puzzle
- 9x9 Sections should be clearly defined (lines in between; seperate boxes)
- Doesn't matter if boxes can/cannot be edited so long as they can display the result
: Button In Center
- Should run [SudokuPuzzle].solve();
: Bottom Text Box
- Should not be editable
.
WHAT I'M LOOKING FOR
I know from past experiences that this can all be done in a JFrame, but because I have never built one myself, I'm not quite sure which components (content items, panels, settings, etc) I need to use to meet my specifications. I have yet to find a way to limit my text boxes to numbers and prevent the user from inserting more than one value at a time. Are text boxes really the best option, or am I missing something that can more specifically suit my needs?
I not only need to know which classes I need, but also how to organize these so that the button stays comfortably between the two puzzles and the text box sits underneath. From what I've read, MigLayout seems like an option to simplify this process.
.
END NOTES
Many, many thanks to anyone who helps. If any part of this question appears a little rude or abrupt, I apologize. I tend to post most of my questions at night, so the community has a few hours to mull it over before I try all the responses (that and the fact that I'm out doing stuff most days).
I will be awake for 1-2 more hours to answer any questions.
Again thanks,
Justian
I can't understand how you could possibly want to abandon that awesome ASCII printout.
You should really take a look at the tutorials given @ http://download.oracle.com/javase/tutorial/uiswing/ and take a look on how the layout managers work.
For the text boxes I would recommend using JTextField. Here is some code you can use to have them only accept one digit at the time:
To make this really useful, you are going to have to customize a lot of stuff.
I suggest you use buttons instead of text fields. When someone clicks on the button it becomes selected, when someone types a number it goes to the selected text field (replacing the number there, if any). This gives you a little more control over how keys are input.
The layout may be tough. It would be nice to take advantage of Swing's ability to scale sizes with the size of the screen, but be sure to scale your fonts as well.
Nearly every hand-done swing GUI should start with a BorderLayout. This gives you "Sides", even if you only use north or south (your example only used south), BorderLayout is great at allocating all unused space to the center.
In the center you probably want to place another container, possibly a grid.
There is one--I think it is "Box" that has an even spacing of a single row. So if you set up a row of 3 horizontally, then added 3 vertically to each box, you could then INSIDE each of those create a box (so that you could differentiate each group of 9) and then inside that box add another 3 horiz, each filled with 3 vertical.
Swing layouts generally come down to a few standard tricks (like always staring with BorderLayout) followed by some guessing, experimenting and some level of cursing.
The Sudoku GUI
Ok, I couldn't help myself... Here is my try. It's all in one package:
I tried my best to make the code as readable as I could. There might be rather unclear parts. Probably the threading part isn't lucid, but if anyone finds this of any use I'd be glad to describe it better.
So my aim was the simplest possible usage. If You look at the interfaces it's really hard to break this stuff (froze UI, get Null Pointer Exc etc.) as an exercise in writing public API's. This may not the best implementation, but It's one of the best I wrote. :)
Hope it helps.
Here's how it looks like: Running example http://a.imageshack.us/img256/754/sudokusolvergui.png
(note: values are random)
Usage
All You have to do is implement the interface:
Just do all computation in this method and store results with
resultAcceptor.setSudokuResult()
Here is how to actually show GUI:
And that's all!
Code
All classes are in default package - refactor as You wish. Here is list of them:
1.SudokuView:
2. SudokuRun:
3. SudokuController:
4. SudokuImplementation:
5. DummySudokuImplementation:
Explanation
I don't claim that the way I did is the best. I'd love to see other answer with, let's say, all view done with MigLayout. It would be very instructive. I was learning Swing GUI when Sun's implementation were only one so it prevailed in my style. That said, I recommend consulting Sun's Swing GUI short course. It also includes a simple study case. After reading it almost whole part of SudokuView should be clear.
I did separate the code to make it more readable. That's why controller is another class, not part of view. The view is only for construction of widgets and layout, but to make it simple (not to create few more classes) I also initialize controller in it.
The real work is in the controller. It contains the hairiest details... Threading also goes there so it's not so obvious what it actually does. I implemented a Thread class from scratch. There is alternative: using SwingWorker. It might be a cliche, but make it clear: I use threading to make GUI responsive at any time. Without proper threading whole GUI would freeze when the computation would take place. I decided to make it as easy as possible from Sudoku's implementation point of view, like non-blocking incremental updates.
As for threading it's crucial to know which code runs in which thread. Every action fired by GUI component runs on EDT (event dispatch thread). If you do any long-running task on it, the GUI won't be responsive. So I just make another thread (see implementation of
goButtonPressed()
) and start it. After that EDT can process any other events without blocking.So Your Sudoku runs in a special, background thread. It can do whatever it wants, unless it has to update the GUI. It almost certain it will, since that's where partial updates go. Here's a catch: if You call any GUI component directly (set some values) than the GUI will freeze. This is a condition called EDT dispatch violation. All interaction with Swing should be done on EDT to avoid any freezes. How to do it? The EDT has special event queue just for that. You post an update event on the queue. On EDT code is constantly watching for incoming events and updates GUI accordingly. So basically, it's a communication between background thread and EDT. To post an event on the queue You could use special utility method designed just for this:
EventQueue.invokeLater(new Runnable() { /* here goes your GUI interaction */ });
. Take a look atSudokuController
methods:That's were the GUI update events are posted.
This should give you enough to get started. Just add the getter logic to pull out the values they entered in the text fields.
Main:
NineSquare:
Board:
So you need to
(1) To limit your textboxes to only number, I think what you could use it a JComboBox that is populated with ints(from 1-9) wrapped in Integer boxes.
(2) This way the user has to select a JComboBox @ each (x,y) grid point on the sudoku board. Then must select the desired number from the dropdown, preventing multiple input at the same time.
Hope this helps,
Goodluck!
EDIT: clarity+1
Netbeans IDE has a great GUI for generating GUIs. However, it helps (a lot) to have a basic understanding of Java GUIs before attempting to generate one with the tool. Especially important is playing with each of the layout managers and getting a feel for which one would help in a given situation. Also note that you can nest panels with different layout managers to get more control over the layout.