I am new to learning Java.
I am creating a JInternalFrame which have 28 labels in matrix forms in it. I want to change label text from - to + on click & vice versa.
I can do it adding EventListeners to each label one by one. But I want some simple solution in which I don't need to add eventlisteners for each label individually. A long ago I have tried same methodology on array of buttons in VisualBasic.
But I want some simple solution in which I don't need to add eventlisteners for each label individually
Why? You can share the MouseListener. Then you just add the listener to the label when you create the label. This is the better approach then trying to search for the clicked label after the fact.
For example:
MouseListener ml = new MouseAdapter()
{
#Override
public void mousePressed(MouseEvent e)
{
JLabel label = (JLabel)e.getComponent();
label.setText( label.getText().equals("-") ? "+" : "-" );
}
}
for (int i = 0; i < 28)
{
JLabel label = new JLabel("-");
label.addMouseListener( ml );
panel.add(label);
}
Related
I'm new in using the DnD in java.I'm trying to drag an drop an image from a label to another. The first label is the source, the second is the destination. My trouble is that I need to drag the image from the source and recognize that i'm dropping on the correct destination; if the destination is correct the image from the source must disappear, else must come back to the source and notify it to the user using a window message or just a System.out.println(). I've tried using TransferHandler, DragSource, but I didn't get a single good result.
How to drag and drop an image from label to label?
The Drag Listener
public class DragMouseAdapter extends MouseAdapter {
public void mousePressed(MouseEvent e) {
JComponent c = (JComponent) e.getSource();
TransferHandler handler = c.getTransferHandler();
handler.exportAsDrag(c, e, TransferHandler.COPY);
}
}
The Source labels that contain the images
public ShipsGUI() {
// setBorder(new EmptyBorder(10,10,10,10));
setLayout(new GridLayout(2, 5));
MouseListener listener = new DragMouseAdapter();
for (int i = 0; i < 10; i++) {
JPanel p = new JPanel(new BorderLayout(5, 0));
JLabel a = new JLabel(ship,JLabel.CENTER);
a.setName("ship");
JLabel n = new JLabel("[" + Integer.toString(i + 1) + "]");
n.setForeground(Color.BLUE);
// a.setBorderPainted(false);
// a.setBackground(Color.white);
// a.setOpaque(true);
//a.setIcon(ship,JLabel.CENTER);
a.setTransferHandler(new TransferHandler("icon"));
a.addMouseListener(listener);
p.add(a);
p.add(n, BorderLayout.LINE_START);
add(p);
}
}
The destination (it's a grid fo labels)
public NewAreaGioco(int r,int c, boolean enable){
this.setLayout(new GridLayout(r,c,1,1));
for(int i=0;i<r;i++){
for(int j=0;j<c;j++){
JLabel l= new JLabel(" ");
l.setSize(30, 30);
l.setBorder(BorderFactory.createLineBorder(Color.BLUE));
if(enable)l.setTransferHandler(new TransferHandler("icon"));
add(l);
}//fine for
}//fine for
}
Well, you can't use the default TransferHandler class. You need to make your own.
I would start by looking at the DropDemo and ListTransferHandler class found on the examples page of the Drag and Drop tutorial.
A couple of change that I think you will need to make:
export an image instead of text. I think the link provided by Sergiy above might help.
The key point is in the exportDone(...) method. Your cleanup code would set the icon of the source component to null.
You will probably need to read the tutorial to understand the concept of these two classes.
I'm trying to make a simple calculator in Java using Swing, and I've created my buttons the following way:
//Our number keypad
public static JPanel numbers(){
//our panel to return
JPanel panel = new JPanel();
//Create and add 3x4 grid layout to panel
GridLayout gl = new GridLayout(3, 4);
panel.setLayout(gl);
//For creating and adding buttons to panel
for(int i = 0; i < 10; i++){
//Create a new button where the name is the value of i
String name = "" + i + "";
JButton button = new JButton(name);
//add action listener
button.addActionListener(handler);
//Add button to panel
panel.add(button);
}
return panel;
}
My question is how do I reference each specific button in my event handler? I can't think of a way to do this without having to manually create each button rather than using a loop.
Thanks.
In your listener, call event.getSource(), and that will return the button which has been pressed. Get the text of the button, and you have its number.
Or create a different instance of your handler for every button, and pass the value of the button (i) to the constructor of the handler. This last solution is cleaner, IMO, because it doesn't depend on the text of the button. If you replaced the text by an image, for example, the first technique wouldn't work anymore.
You can distinguish created buttons by adding the following inside handler:
String buttonText = ((JButton) e.getSource()).getText();
if (<text1>.equals(buttonText)){
//do the stuff
} else if (<text2>.equals(buttonText)){
//do the stuff
} else {
//do the stuff
}
Method #1: go through the child components of the parent JPanel (quite tedious, has to be rebuilt every time you modify the contents of that JPanel). Make sure they're JButtons by using an if . . instanceof clause.
Method #2: as you create them in that loop, add them to a List (or even better, a Map). I prefer a Map personally as it lets me customise the key for that specific JComponent
i.e.
HashMap<String, JComponent> buttonList = new HashMap<String, JComponent>();
for(. .) {
buttonList.put("nameForEachButton", button);
}
I recommend generating the button name based off of the loop counter. Either use your existing name value, or just set it to "button" + i;
Declare your buttons using an array.
JButton[] button = new JButton[9]; //outside the for loop
for (int i = 0; i < 10; i++) {
//put your code
button[i] = new JButton(name);
//your code
}
I'm a beginner in GUI.
Is there a quick way of setting the same JButton/Image to multiple locations within the GUI? For better clarification, if I want to use this JButton 10 times at different locations in my GUI, would I have to create a new JButton(new ImageIcon...) 10 times?
The buttons don't have to lead to anything, this is just for show.
JButton jb = new JButton(new ImageIcon("myImage.png"));
jb.setLocation(10,10);
jb.setSize(40, 40);
getContentPane().add(jb);
The short answer is, yes, you will need multiple instances of JButton.
You can use an Action which can be applied to multiple instance of a button (the same instance of Action). The Action class carries properties which will be used to configure the buttons, such as text and icon properties.
A component (like JButton) can only reside within in a single container, therefore, you will need multiple instances of JButton.
Take a look at How to Use Actions and How to Use Buttons, Check Boxes, and Radio Buttons for more details...
Generally, you should avoid using setLocation and setSize and rely more on the use of layout managers, but you've not provided enough context to say if this useful to you or not.
Yes, you need to create a Jbutton object for each desired instance.
Since you have so many JButton that are all similar, I suggest that you declare an array JButton[] buttons = new JButton[10]; and use a for loop to create each individual button and set their attributes.
If it is just for a show, I would do the following to show the 10 button in a row:
int buttonHeight = 10;
int buttonWidth = 10;
for (int i = 0; i < 10; i++) {
JButton button = new Button("Button " + i);
button.setSize(buttonWidth, buttonHeight);
button.setLocation(10 + i * buttonWidth, 10);
getContentPane().add(button);
}
import java.util.Scanner;
import javax.swing.*;
import java.awt.*;
class PROB4_CHAL1 extends JFrame
{
JButton b[]=new JButton[10];
public PROB4_CHAL1()
{
setLayout(null);
setVisible(true);
setSize(100,100);
for(int i=0;i<10;i++)
{
b[i]=new JButton(""+i);// or b[i]=new JButton(new ImageIcon("path"));
b[i].setBounds(i*10,i*20,50,20);
add(b[i]);
}
}
public static void main(String[] args)
{
new PROB4_CHAL1();
}
}
You can Create array of 'JButton [10]' .
grid=new JButton[width][length];
for(y=0;y<length;y++){
for(x=0;x<width;x++){
final Border border=new LineBorder(Color.red, 5);
grid[x][y]=new JButton(" ");
grid[x][y].addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
((JButton)e.getSource()).setBorder(border);;
System.out.println("Where do you want to move this piece");
}
});
frame.add(grid[x][y]);
}
}
grid[1][1]='R';
I am trying to get the first spot of the grid to say the letter R as in Rook; I am not sure how I can label specific JButton in a grid. Please help me... I am trying to make a GUI chess game.
Use methods instead of = to set component properties in Swing
grid[0][0].setText("R");
This won't compile:
grid[1][1]='R';
Because you're trying to assign a char to a JButton. Instead understand that the grid holds JButtons, and call the JButton methods:
grid[0][0].setText("R");
Also, you don't want to do this:
System.out.println("Where do you want to move this piece");
It's a bad idea to combine println statements and GUI's (unless you're debugging). Rather, show that String in a JLabel.
I am trying to create a simple GUI that simulates a record store. I am still in the beginning stages.
I am running into trouble when I try to add text to describe what the user is expected to enter in the text field.
In addition, I am also having trouble positioning every textfield on its own line. In other words if there is space for two textfields in one line, then it displays in one line, and I am trying to display every text field on its own line.
This is what I tried so far:
item2 = new JTextField("sample text");
However the code above just adds default text within the text field, which is not what I need :/
I appreciate all the help in advance.
public class MyClass extends JFrame{
private JTextField item1;
private JTextField item2;
public MyClass(){
super("Matt's World of Music");
setLayout(new FlowLayout());
item1 = new JTextField();
item2 = new JTextField();
add(item1);
add(item2);
thehandler handler = new thehandler();
item1.addActionListener(handler);
item2.addActionListener(handler);
}
}
For your first problem, you need to use a JLabel to display your text. The constructor is like this:
JLabel label = new JLabel("Your text here");
Works really well in GUI.
As for getting things on their own lines, I recommend a GridLayout. Easy to use.
In your constructor, before adding anything, you do:
setLayout(new GridLayout(rows,columns,x_spacing,y_spacing));
x_spacing and y_spacing are both integers that determine the space between elements horizontally and vertically.
Then add like you have done. Fiddle around with it and you'll get it worked out.
So your final would look like:
setLayout(new GridLayout(2,2,10,10));
add(new JLabel("Text 1"));
add(text1);
add(new JLabel("text 2"));
add(text2);
You could just use a JLabel to label your textfields.
JLabel label1 = new JLabel("Item 1: ");
add(label1);
add(item1);
If you really want text inside the fields, you could set the text in the field with the constructor, and then add a MouseListener to clear the text on click:
item1 = new JTextField("Text");
item1.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (item1.getText().equals("Text")) // User has not entered text yet
item1.setText("");
}
});
Or, (probably better) use a FocusListener:
item1 = new JTextField("Text");
item1.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
if (item1.getText().equals("Text")) // User has not entered text yet
item1.setText("");
}
public void focusLost(FocusEvent e) {
if (item1.getText().equals("")) // User did not enter text
item1.setText("Text");
}
});
As for layout, to force a separate line, you use use a Box.
Box itemBox = Box.createVerticalBox();
itemBox.add(item1);
itemBox.add(item2);
add(itemBox);
Make:
item1 = new JTextField(10);
item2 = new JTextField(10);
that should solve problem with width of JTextField.
For beginning use GridLayout to display JTextField in one line. After that I strongly recomend using of MIG Layout http://www.migcalendar.com/miglayout/whitepaper.html.
put JLabel next to JTextField to describe what the user is expected to enter in the text field.
JLabel lbl = new JLabel("Description");
or you could also consider using of toolTipText:
item1.setToolTipText("This is description");
For making a form in Java Swing, I always recommend the FormLayout of JGoodies, which is designed to ... create forms. The links contains an example code snippet, which I just copy-pasted here to illustrate how easy it is:
public JComponent buildContent() {
FormLayout layout = new FormLayout(
"$label, $label-component-gap, [100dlu, pref]",
"p, $lg, p, $lg, p");
PanelBuilder builder = new PanelBuilder(layout);
builder.addLabel("&Title:", CC.xy(1, 1));
builder.add(titleField, CC.xy(3, 1));
builder.addLabel("&Author:", CC.xy(1, 3));
builder.add(auhtorField, CC.xy(3, 3));
builder.addLabel("&Price:", CC.xy(1, 5));
builder.add(priceField, CC.xy(3, 5));
return builder.getPanel();
}
Now for the description:
Use a label in front of the textfield to give a very short description
You can put a longer description in the textfield as suggested by #Alden. However, if the textfield is for short input, nobody will be able to read the description
You can use a tooltip (JComponent#setTooltipText) to put a longer description. Those tooltips also accept basic html which allows some formatting. Drawback of the tooltips is that the user of your application has to 'discover' that feature as there is no clear indication those are available
You can put a "help-icon" (like e.g. a question mark) after each text field (use a JButton with only an icon) where on click you show a dialog with a description (e.g. by using the JOptionPane class)
You can put one "help-icon" on each form which shows a dialog with a description for all fields.
Note for the dialog suggestion: I wouldn't make it a model one, allowing users to open the dialog and leave it open until they are finished filling in the form