I have a JTextArea in a JDialog. JDialog uses a GridLayout.
I would like to have 7 digits on each line of the JTextArea (each line will be a 7 int registration number). For user experience reasons, I would like the JTextArea to either add a new line or stop expanding when it reaches 7 characters on a line.
Things that didn't work :
- Specifying the number of columns in the JTextArea constructor
- matriculesText.setLineWrap(true); and matriculesText.setWrapStyleWord(true);
I'm afraid uploadDialogManager.setHgap(20); might be breaking the code. I'm wondering if the JDialog should rather have a fixed size.
This is how I construct my JDialog :
// initialization
Dialog uploadParent = null;
JDialog uploadDialog = new JDialog(uploadParent);
GridLayout uploadDialogManager = new GridLayout(UPLOAD_DIALOG_ROWS,
UPLOAD_DIALOG_COLUMNS);
// uploadDialog properties
uploadDialog.setSize(new Dimension(UPLOAD_DIALOG_WIDTH, UPLOAD_DIALOG_HEIGHT));
uploadDialog.setLayout(uploadDialogManager);
uploadDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
//Set up the horizontal gap value
uploadDialogManager.setHgap(20);
//Set up the vertical gap value
uploadDialogManager.setVgap(20);
//Set up the layout of the buttons
//uploadDialogManager.layoutContainer();
// components initialization
JLabel exerciceLabel = new JLabel("exercice number : ");
JComboBox<Integer> exerciceNumbers = new JComboBox<Integer>
(EXERCICE_NUMBERS);
JLabel matriculeLabel = new JLabel("please enter your matricules, one per
line : ");
JTextArea matriculesText = new JTextArea(1, 1);
JButton confirm = new JButton("confirm");
JButton cancel = new JButton("cancel");
matriculesText.setLineWrap(true);
matriculesText.setWrapStyleWord(true);
I have made another solution that fills my requirements. Instead of going to a new line when 7 characters are reached, I use MATRICULE_REGEX to check if every line contains 7 digits (1\\d{6}). If it doesn't, I reject the JTextArea content.
private static final String MATRICULE_REGEX = "1\\d{6}(\\n1\\d{6})*";
Pattern matriculePattern = Pattern.compile(MATRICULE_REGEX);
Matcher matriculeMatcher = null;
matriculeMatcher = matriculePattern.matcher(text);
isValidMatricule = matriculeMatcher.matches();
Related
So I am creating a number guessing game. The computer generates a random number, the user inputs a guess, then the computer lets the user know if they've won, or if the guess was less than or more than the random number. This goes on until they've got it right, or press play again (which resets it).
I want to count and display the number of guesses a user makes each round. So I am incrementing 'tallyValue' for each guess. I know it is counting and incrementing the values correctly. However for instance if the user guesses twice in a row values that are less than the random number, then the tally value doesn't update on the .setText output. It will only update when the users guesses alternate from less than the random number to more than the random number.
What am I missing? I've tried removing and then setting the text but I don't understand why this happens.
MyFrame() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //exit out of app
this.setLayout(new FlowLayout());
//add labels, buttons and input fields
button = new JButton("Submit");
button.addActionListener(this); //can just pass in this because we already pass actionlistener above
JLabel instruction = new JLabel();
instruction.setText("Input Your Guess (must be between 1 and 100");
textField = new JTextField();
textField.setPreferredSize(new Dimension(250,40));
tally = new JLabel();
tally.setText("Number of guesses: " + tallyValue);
outputMessage = new JLabel();
outputMessage.setText("Take a guess!");
playAgainButton = new JButton("Play Again");
playAgainButton.addActionListener(this);
this.add(instruction);
this.add(textField);
this.add(button);
this.add(playAgainButton);
this.add(outputMessage);
this.add(tally);
this.setTitle("Number Guessing Game");
this.setVisible(true); //make frame visible
this.pack(); //frame size adjusts to components
ImageIcon icon = new ImageIcon("res/game-icon.png"); //creates an image icon
this.setIconImage(icon.getImage());//changes icon of frame
System.out.println(randomNumber); //for testing purposes
}
//add any unimplemented methods because we are using an interface
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()==button) {
int textFieldValue;
this.remove(outputMessage);
try {
textFieldValue = Integer.parseInt(textField.getText());
//if guess is correct
if(textFieldValue == randomNumber) {
outputMessage.setText("Congratulations you guessed correctly!");
this.add(outputMessage);
tallyValue++;
displayCount(tallyValue);
this.pack();
textFieldValue = 0; //reset text field val
}
//if guess is less than randomNumber
if(textFieldValue < randomNumber) {
outputMessage.setText("Incorrect - the number I am thinking of is more than that");
this.add(outputMessage);
tallyValue++;
displayCount(tallyValue);
this.pack();
textFieldValue = 0; //reset text field val
}
//if guess is more than randomNumber
if(textFieldValue > randomNumber) {
outputMessage.setText("Incorrect - the number I am thinking of is less than that");
this.add(outputMessage);
tallyValue++;
System.out.println(tallyValue);
displayCount(tallyValue);
this.pack();
textFieldValue = 0; //reset text field val
}
}
catch (NumberFormatException ex){
outputMessage.setText("You must insert a valid number");
this.add(outputMessage);
this.pack();
}
}
if(e.getSource()==playAgainButton) {
System.out.println("pa");
this.remove(outputMessage);
randomNumber = rand.nextInt(101);
outputMessage.setText("Take a guess!");
this.add(outputMessage);
tallyValue = 0;
displayCount(tallyValue);
this.pack();
}
}
private void displayCount (int tv) {
this.remove(tally);
tally.setText("Number of guesses:" + tv);
this.add(tally);
this.pack();
}
It will only update when the users guesses alternate from less than the random number to more than the random number.
There is no need to increment the tally in 3 different places. The tally should be incremented right after you Integer.parseInt(...) statement. That is it will be updated every guess, no matter what the guess is.
Then you would just update the text of your tally label with the new count. There is no need to remove/add the label from the frame. There is no need to pack() the frame. Just setting the text will cause the label to repaint. So there is no need for the displayCount() method.
You should also be learning how to use layout manager correctly. Currently you are using a FlowLayout will will just cause the components to display in a row and then wrap to the next line. This is not a very effective layout as all the components will shift if the frame is ever resized.
Read the Swing tutorial on Layout Managers. You can nest panels with different layout managers to achieve a more flexible layout.
textField = new JTextField();
textField.setPreferredSize(new Dimension(250,40));
Don't use magic numbers for the size of a component. Instead use the API properly so the text field can determine its own preferred size:
textField = new JTextField(10);
The "10" will allow the text field to size itself to display 10 "W" characters before scrolling of the text.
Also, you should not use a shared ActionListener for your buttons.
One approach is to use a lamba to separate the functionality:
//playAgainButton.addActionListener(this);
playAgainButton.addActionListener((e) -> playAgain());
Then you create a private method playAgain() in your class. Now the code is separated into methods by function.
I am making a basic soundboard in java and i want it so that the every 2 buttons are on a different line like:
(button) (button)
(button) (button)
This is my code as of now
JPanel p = new JPanel();
JButton one = new JButton(sound1);
JButton two = new JButton(sound2);
JButton three = new JButton(sound3);
JButton four = new JButton(sound4);
JButton five = new JButton(sound5);
p.add(one);
p.add(two);
p.add(three);
p.add(four);
p.add(five);
int n = JOptionPane.showConfirmDialog(null, p, "Test", JOptionPane.OK_CANCEL_OPTION, -1);
What would be the easiest way to do it? If i have to switch to a JFrame let me know i wont mind if that is the only option.
Just use GridLayout in your JPanel:
JPanel p = new JPanel(new GridLayout(0, 2));
First argument is the number of rows, second one is the number of columns. If you specify number of rows as 0 you are telling the layout manager that you just want to have two columns and don't know how many rows you're going to need - the rows will be created dynamically.
You can use the GridLayout, it presents components in a table. like below, 3 is the number of rows, 2 is the number of columns.
p.setLayout(new GridLayout(3, 2));
p.add(one);
p.add(two);
p.add(three);
p.add(four);
p.add(five);
The following is some code which makes multiple fields (items). I know that the parameter after new JTextField is the content of the text box, and I understand how item2, 3, and passwordField work, but do not understand item1. In the line of code:
item1 = new JTextField(10);
What does the (10) mean? I would expect there to be a default number inside that text box, but that is not the case. Any help would be appreciated.
public eventhandling(){
super("The title");
setLayout(new FlowLayout());
item1 = new JTextField(10);
add(item1); //Adds item to window
item2 = new JTextField ("Enter text here"); //Making a text box that has the words "enter text here" in it
add(item2);
item3 = new JTextField ("uneditable", 20);
item3.setEditable(false); //This text field cannot be changed now
add(item3);
passwordField = new JPasswordField ("mypass"); //Setting the password field with a default password : "mypass"
add(passwordField);
This is what i found from the Oracle Site
JTextField(int columns):
Constructs a new empty TextField with the specified number of columns.
First you need to understand that there are different ways to initialize a component. Then you also need to notice that there is a difference between "10" and 10. The first is a string, the second is an integer. That being said, if you want the number 10 to show in the JTextField box then you need to pass "10" in the constructor. If you pass 10 that is telling the constructor to set the 10 columns in the JTextField, that is, it restricts the number of characters that can be entered to 10. Check the API ...
http://docs.oracle.com/javase/7/docs/api/javax/swing/JTextField.html
Here I have a simple buildPanel method for the input area.
I try to use GridLayout(7,1), but the first 4 JTextField seem to fill up the entire space of its block, and that looks quite ugly.
Is there any way to change them back to its normal size?
private void buildInputPenal()
{
dateField = new JTextField(10); //dateField should be changed to something else later
fNameField = new JTextField(15);
lNameField = new JTextField(15);
pledgeField = new JTextField(10);
charityRB1 = new JRadioButton(Charity[0]);
charityRB2 = new JRadioButton(Charity[1]);
charityRB3 = new JRadioButton(Charity[2]);
radioButtonGroup = new ButtonGroup();
radioButtonGroup.add(charityRB1);
radioButtonGroup.add(charityRB2);
radioButtonGroup.add(charityRB3);
charityRB1.addActionListener(new RadioButtonListener());
charityRB2.addActionListener(new RadioButtonListener());
charityRB3.addActionListener(new RadioButtonListener());
inputPanel = new JPanel(new GridLayout(7,1));
inputPanel.add(dateField);
inputPanel.add(fNameField);
inputPanel.add(lNameField);
inputPanel.add(pledgeField);
inputPanel.add(charityRB1);
inputPanel.add(charityRB2);
inputPanel.add(charityRB3);
}
Don't use GridLayout. GridLayout creates an even set of cells for each component (that is they get the same amount of space).
Instead, consider using something GridBagLayout instead
See How to Use GridLayout and How to Use GridBagLayout for more details
So I want to add some text to a window.
I added the text in a ArraList like this:
ArrayList<String> Text = new ArrayList<String>();
Text.add("text1");
Text.add("text2");
...
Text.add("text*n*");
I now want to add these items into a JFrame. Now, I am pretty new to programming, so there is probably a better solution than this. But here is what I tried (I am using a for loop, because I think this is also the easiest way for me to manage the bounds of the labels:
for(int i = 0; i<Text.size();i++){
JLabel jl = new JLabel(names.get(i));
jl.setBounds(50,100+20*i,200,50);
this.add(jl);
}
But only the last element in the ArrayList is added to the JFrame (text*n*). Not all of them.
How can I get every element in the arraylist to show in the jframe? Maybe I shouldn't use JFrame?
It sounds like you want to use a JList, not a grid of JLabel.
i.e.,
DefaultListModel<String> listModel = new DefaultListModel<String>();
JList<String> myJList = new JList<String>(listModel);
// assuming you have an array of String or ArrayList<String> called texts
for (String text : texts) {
listModel.addElement(text);
}
JScrollPane listScrollPane = new JScrollPane(myJList);
// then add the listScrollPane to your GUI
Also:
Please learn and follow Java naming rules. Variable names should begin with a lower case letter, so "text" not Text.
And you should know that every time someone uses a null layout and setBounds(...) a puppy dies. Please don't be cruel to puppies, and don't create rigid hard to maintain and upgrade GUI's. Learn and use the Swing layout managers. You won't regret this, and neither will the puppies.
You need a layout, otherwise they are added on top of each other. Try adding everything to a JPanel and only add the panel to the frame at the end.
JFrame frame = new JFrame("title");
JPanel panel = new JPanel();
// Y_AXIS means each component added will be added vertically
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
for (String str : Text) {
JLabel j1 = new JLabel(str);
panel.add(j1);
}
frame.add(panel);
frame.pack();
frame.setVisible(true);
Try with Replace names.get(i) as Text.get(i)
OR Try,
for(String str : Text){
JLabel jl = new JLabel(str);
}
Try this:
String output = "";
for(int i = 0; i<Text.size();i++)
{
output += Text.get[i] + "\n";
}
JLabel jl = new JLabel(output);
This will create a string named output that will add the text from each index, followed by creating a new line. Then at the end, the full string will be added to the JLabel. The only downside to this method is that one label will contain ALL of the text.
JLabel jl = new JLabel(names.get(i));
Here you always construct a new object for j1, and after the loop you just have the latest object.