I am currently writing a sudoku solver in Java. What I need now is some kind of Swing GUI to input the known numbers. I created a JFrame, but manually adding 81 text fields from the toolbox seems like a bad solution. I am also able to add with code like this:
this.setLayout(new GridLayout(9, 9));
for (int i = 0; i < 81; i++)
{
this.add(new JTextField("Field"));
}
However, I do not know how to address these text fields afterwards to collect the user input into a two-dimensional array. How can I do that?
A different solution would be to use a JTable. You could allow for the TableModel to maintain the full data solution, as well as a copy of the user's attempts. The CellRenderers and CellEditors could handle the user experience. See this tutorial.
Struggled a bit with this for my own sudoku solver, but ended up going for painting on a JPanel, and adding a mouse listener to that.. Than determine the current field using mouse position with his function:
addMouseListener(new MouseAdapter() {
private int t(int z) {
return Math.min(z / factor, 8);
};
#Override
public void mouseMoved(MouseEvent e) {
setToolTipPossibilities(t(e.getX()), t(e.getY()));
}
#Override
public void mousePressed(MouseEvent e) {
clickColumn = t(e.getX());
clickRow = t(e.getY());
}
});
First you need to declare array of JTextFields.
So just like your array to store user input you do:
private JTextField[] textFields;
After that you can use some math to map your one-dimensional array to your two dimensions.
something like this should work:
floor(index / 9), index % 9
for x,y
Yes that will work to display the array. To read from the array you just need to call the getText method for each element.
JTable is your friend. Use a DefaultTableModel with editable String values.
String[] columnNames = new String[9];
for(int i=0; i<9; i++){columnNames[i]="";}
String[][] data = new String[9][9];
JTable tab = new JTable(columnNames,data);
When they fill it in, check that each string is an appropriate number and prompt for error.
1st way:
You could put the text fields into an array that mirrors the array that your cell values are in.
The problem with this method tho is that when you need to bind a mouseListener or ActionListener to the TextField you will have a hard time figuring out which cell number it corrisponds to.
2nd way:
You could extend the JTextField into a custom class with new instance variables that store cell number in it.
Using this method you can also implement MouseListener or ActionListener on the extended class too and get whatever information about the field you need, without searching through your array. And combining with the first to put them into an array organizes them for quick access.
Just want to post a little update.
I added an array of textfields as a field on my form:
private JTextField[] fields;
Initialized it:
fields = new JTextField[81];
And finally I am adding the fields to my form like this:
private void addComponents()
{
this.setLayout(new GridLayout(9, 9));
for (int i = 0; i < fields.length; i++)
{
fields[i] = new JTextField("" + i);
this.add(fields[i]);
}
}
The result as of now can be seen here:
Image of my textfields
Related
Let's suppose I've a list of String like this
List<String> button_names={"Button1","Button2","Button3","Button4"};
I've to insert JButtons with those texts in a JPanel so I do
for (int i=0; i<button_names.length; i++)
myJPanel.add(new JButton(button_name[i]));
My question is... If my model (in this case, my List button_names) changes for any reasons, how can I refresh my JPanel in order to show that change?
Should I do
myJPanel.removeAll()
and insert again my JButtons()? Thank you in adance
Yes removeAll and then reinserting new buttons is the easiest and generally the best way to go. Otherwise, you have to start figuring out which buttons have been removed, which have been added, and where in the list these new buttons are. Also, buttons in the list should change position I guess, so you'd have to cover that case to.
You can write a method like this that you could use in initial creation, and when you want to reload the list
void addButtonsToPanel(JPanel p) {
p.removeAll();
for (int i=0; i<button_names.length; i++)
myJPanel.add(new JButton(button_name[i]));
validate();
repaint();
}
So I have this 2d array of buttons and I have an array of images. I want to get the images on the buttons but I want the images to be on random buttons every time the program starts. Like this:What I want it to look like. Right now I can only get one color to be on all of the buttons by changing the value of icons when I make the new JButton. What I think I need to do is have Math.Random() set to a variable and to get a random value from the array of images and then put the variable in icons[] when i declare the new JButton but I don't know if this is right and don't know how to do it. I did some searching and tried using this:
var randomValue = icons[Math.floor(Math.random() * icons.length)];
but I get an error saying
possible loss of precision, required int, found double.
Help would be greatly appreciated. If you want me to post the entire code let me know.
// 2D Array of buttons
buttons = new JButton[8][8];
for(int row=0; row<8; row++)
{
for (int col=0; col<8; col++)
{
buttons[row][col] = new JButton(icons[0]);
buttons[row][col].setLocation(6+col*70, 6+row*70);
buttons[row][col].setSize(69,69);
getContentPane().add(buttons[row][col]);
}
}
// Array of images
public static ImageIcon[] icons = {new ImageIcon("RedButton.png"),
new ImageIcon("OrangeButton.png"),
new ImageIcon("YellowButton.png"),
new ImageIcon("GreenButton.png"),
new ImageIcon("BlueButton.png"),
new ImageIcon("LightGrayButton.png"),
new ImageIcon("DarkGrayButton.png")};
I'd simplify this greatly by putting all my ImageIcons in an ArrayList, calling java.util.Collections.shuffle(...) on the ArrayList, and then passing out the ImageIcons from the shuffled ArrayList in order. Or if your buttons allow for repeated icons, then use a java.util.Random variable, say called random and simply call random.nextInt(icons.length) to get a random index for my array.
As an aside, please for your own sake, don't use null layout and absolute positioning. Your grid of JButtons is begging to be held in a GridLayout-using JPanel. Begging.
As an aside, why are you posting questions on the same project but using different names? You've similar posts but different user names in both of your other posts here:
JButtons won't update on button click
My New Game JButton is not working?
Before you set the icons on the JButton use this shuffle function...
public ImageIcon[] shuffle(ImageIcon[] icons)
{
int index = 0;
ImageIcon temp = 0;
for(int i = icons.length -1; i > 0; i--)
{
index = r.nextInt(i + 1);
temp = icons[index];
icons[index] = icons[i];
icons[i] = temp;
}
return icons;
}
I have a GUI setup with with buttons on them and a JTextArea.
I also have an array of Strings with say size of 3.
What I want to do is use an action listener in a way that when the button called "next" is pressed, the JTextArea will then show the next cell in the array. The only problem is it displays the array at the same time. I need it to display the next cell when the button is hit
Can anyone help me with the code? Please and thank you.
final ActionListener m2 = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e)
{
arr = new String[3];
arr[0]= "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
arr[1]= "sssssssssssssssssssssss";
arr[2]= "xxxxxxxxxxxxxxxxxxxxx";
for (int i = 0; i<arr.length; i++){
text.append(arr[i]);
}
}
};
next.addActionListener(m2);
So the basic concept is. You need a index value to maintain the current index of the array that is being displayed.
From there, each time the user clicks next, you would increment the index and display the next value in the String
public void actionPerformed(ActionEvent e) {
currentIndex++;
// You need to decide what to do when we reach the end of the array...
String value = myStrings[currentIndex];
textArea.setText(value);
}
To create the button, use the JButton class. To respond to events, use the JButton#addActionListener() method. If you are having trouble, post what you have tried. Good luck!
I'm having more "I'm hopeless at programming" problems.
I have a piece of code which uses StringBuilder to display elements of an array in a text panel of a GUI when the program starts. Here's the StringBuilder code:
// memory tab
StringBuilder mList = new StringBuilder();
memLocList = new Memory[MEM_LOCATIONS];
mem = new Memory();
for (int i = 0; i < memLocList.length; i++) {
memLocList[i] = mem;
memLocList[i].setOpCode(00);
mList.append(String.format("%10s %04x %10s %6s", "Address: ", i,
"Value: ", memLocList[i].getOpCode()));
mList.append("\n");
}
JComponent memTab = makeTextPanel(mList.toString());
tabs.addTab("Memory", new JScrollPane(memTab));
}
protected JComponent makeTextPanel(String t) {
text = t;
JPanel panel = new JPanel(false);
JTextPane filler = new JTextPane();
filler.setFont(new Font("Courier", Font.PLAIN, 14));
filler.setText(text);
filler.setAlignmentX(LEFT_ALIGNMENT);
panel.setLayout(new GridLayout(1, 1));
panel.add(filler);
return panel;
}
The GUI also has a text entry panel where a String of hex values can be entered.
On clicking a button, the user is prompted for another value, which corresponds to the position in the array where the first hex value should be inserted.
Once these values have been entered, I'd like the display to be updated / refreshed to reflect this but am unsure of how to go about it.
I found this question here, which is similar but I'm not sure if implementing Observer/Observable pattern is the right way to proceed, and even if it is, how I'd go about it:
Best Way to Constantly Update GUI Elements
My initial approach was to add an "updateDisplay()" method, which I could call after processing the button click and re-call the makeTextPanel method:
public void updateDisplay() {
makeTextPanel(text);
}
I thought this might refresh it but it has no effect of the display.
Any help appreciated.
You hold your array in a model class, and you allow other classes to "listen" to this by giving this class a SwingPropertyChangeSupport object as well as an addPropertyChangeListener(...) method. Then give the array a setXXX(...) method, and in that method fire the SwingPropertyChangeSupport object after updating the array. There are examples of just this sort of thing on this site, some written by me.
For example: here, here, here, ...
By the way, I'm not surprised that your call to makeTextPanel(text) doesn't work. It creates a JPanel, but you don't appear to do anything with the JPanel that is returned from the method. But nor should you. I don't think that creating new JPanels is the solution you want, but rather updating the Strings displayed by a component of some sort such as a JList or JTextArea using the listener framework that I've described above.
If any of this is confusing, please ask for clarification.
I'm trying to work to display a number of jtextfield according to one of the given values in a combobox.
So, I will have a drop down menu with let's say 1 to 4. If the user selects number 3, 3 textfields will be displayed. I've created the jcombobox with a selection of numbers. But I'm not sure how to implement this. If I'm not mistaken I need to use
ItemEvent.SELECTED
I think I need to create a reference to the JTextField object that will be available to the JComboBox's itemListener object.
Any help would be greatly appreciated.
I've added this to my class :
// aOption is the combobox I declared
aOptionComboBox.setModel(new DefaultComboBoxModel(new String[]{"1","2","3"}));
public void itemStateChanged(ItemEvent event) {
String num = (String)aOptionComboBox.getSelectedItem();
int num1 = Integer.parseInt(num);
JTextField[] textfields = new JTextField[num1];
for (int i = 0; i < num1; i++)
{
textfields[i] = new JTextField("Field");
getContentPane().add(textfields[i]);
textfields[i].setBounds(200, 90, 100, 25);
}
}
am I on a right track?
use the getSelectedItem() on the combobox. This will either yield a string or an integer (depending on how you implemented it). Next use a for-loop to determine the amount of JTextField's and store them in an array.
int amount = myJComboBox.getSelectedItem();
JTextField[] textfields = new JTextField[amount];
for (int i = 0; i < amount; i++) {
textfields[i] = new JTextField("awesome");
this.add(textfields[i]);
}
this way you can easily store the textfields and add them to your panel.
Some added information.
The textfield-array must be accesible outside the eventListener, so you must implement it in your class. that way the whole class can use it.