I have this applet that will add 2 numbers together and display their sum in a third text box.
https://pastebin.com/4ga1brD1
I want the text boxes to be arranged horizontally but more importantly I need the third text box to be uneditable.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class Question extends Applet implements ActionListener
{
TextField firstNum, secondNum, resultNum;
public Question()
{
setLayout(new GridLayout(3, 2, 10, 15));
setBackground(Color.cyan);
firstNum = new TextField(15);
secondNum = new TextField(15);
resultNum = new TextField(15);
secondNum.addActionListener(this);
add(new Label("Enter First Number"));
add(firstNum);
add(new Label("Enter Second Number"));
add(secondNum);
add(new Label("S U M"));
add(resultNum);
}
public void actionPerformed(ActionEvent e)
{
String str1 = firstNum.getText();
double fn = Double.parseDouble(str1);
double sn = Double.parseDouble(secondNum.getText());
resultNum.setText("Sum is " + (fn+sn));
}
}
To arrange your TextField components horizontally, don't add them directly to the Applet. Instead, create a Panel, give it a FlowLayout and add your TextField components to the Panel. Then you can add the Panel directly to your Applet. Make sure your Applet is wide enough to fit all three boxes side by side or the layout will stack the third box under the first one.
Note: I would test this for you, but no browser has supported Applets for at least five years.
To make the third TextField uneditable, you want to use the setEnabled() method. setEditable() would be the way to accomplish the same thing if you were using JTextField, as opposed to the simple AWT TextField that you're using. You should get in the habit of looking at the official documentation, where the answer is readily found.
resultNum.setEnabled(false);
Bear in mind that a disabled box will appear greyed out, which may be visually unappealing. The solution is to convert to Java Swing, which will allow you to use setEditable, which simply prevents your user from clicking into the box without changing the appearance. Swing would also allow you to use layout managers with much more sophistication and flexibility.
Related
How would I add gridbag layout to my code in order for output box to span the length of gui within the border parameters provided in the following code? I have two other classes that go along with this work fine. When the GUI populates it all works except the output text box doesn't span the length of gui so that the text in text box is cut off and I want to fix this, but I don't know how to do it as I never used gridbaglayout.
Below is the image showing how the GUI is supposed to look:
The code in question is given below:
public ATMGui() {
checkingAcc = new Account(1000);
savingAcc = new Account(2000);
currentSelect = new Account(0);
atmFrame = new JFrame("Automated Teller Machine");
output = new JTextField();
panel = new JPanel();
I believe that the problem may be because I didn't completely declare the size of the output box so it only spans one grid so-to-speak whereas I want it to span both. Can someone help me decide whether I declare the grid differently in the code above or if it goes below? Also, I've read about GridBagLayout and other methods but my problem is that I'm not sure how/where to implement it here.
atmWithdraw = new JButton("Withdraw");
atmDeposit = new JButton("Deposit");
transfer = new JButton("Transfer to");
balance = new JButton("Balance");
atmWithdraw.addActionListener(this);
panel.setLayout(new GridLayout(4, 2));
panel.setBorder(BorderFactory.createEmptyBorder(15, 15, 0, 15));
panel.add(atmWithdraw, 0);
panel.add(atmDeposit, 1);
panel.add(transfer, 2);
panel.add(balance, 3);
panel.add(checking, 4);
panel.add(savings, 5);
panel.add(output, BorderLayout.LINE_END);
atmFrame.add(panel);
atmFrame.setSize(300, 175);
atmFrame.setVisible(true);
i have never used gridbaglayout
Start by reading the section from the Swing tutorial on How to Use GridBagLayout for working examples.
The working example shows how to have a button span the entire width of the frame. You need to play with the "grid width" constraint. The tutorial explain how all the constraints are used.
The other option is to nest layout managers. So maybe you use the standard BorderLayout of the frame. Then you create a panel and add some components to the panel using your GridBagLayout and then add the panel to the CENTER. Then you can add your "output box" to the BorderLayout.PAGE_END. By default the component will fill the horizontal space.
The point is read the tutorials and learn the basics of each layout manager. Then use the appropriate combination of layout managers to get the job done.
My advice is not to use GridBagLayout but rather something a bit easier to use (but just as powerful) like TableLayout (http://www.oracle.com/technetwork/java/tablelayout-141489.html). To use include download the library and include in classpath or use the following maven include: -
<dependency>
<groupId>info.clearthought</groupId>
<artifactId>table-layout</artifactId>
<version>4.3.0</version>
</dependency>
(See https://github.com/nerro/table-layout for more details)
Once included, then you can define your table layout as a simple 2 dimensional array of numbers e.g.
import info.clearthought.layout.TableLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
public class Test {
public static void main(String [] args) {
// Create JPanel using TableLayout as layout manager
double PREF = TableLayout.PREFERRED;
double BORDER = 10;
double size[][] = { { BORDER, 0.50, 10, 0.50, 10 }, { 10, PREF, 10, PREF, 10, PREF, 10, PREF, 10 } };
JPanel panel = new JPanel(new TableLayout(size));
panel.add(new JButton("Withdraw"), "1,1");
panel.add(new JButton("Deposit"), "3,1");
panel.add(new JButton("Transfer to"), "1,3");
panel.add(new JButton("Balance"), "3,3");
panel.add(new JRadioButton("Checking"), "1,5");
panel.add(new JRadioButton("Savings"), "3,5");
panel.add(new JTextField(), "1,7,3,7");
// Add to JFrame and Display
JFrame frame = new JFrame("ATM Machine");
frame.setSize(300, 200);
frame.setContentPane(panel);
frame.setVisible(true);
}
}
The previous code produces the following: -
NOTE that the layout is defined as follows: -
double size[][] = { { WIDTH1, WIDTH2, ... }, { HEIGHT1, HEIGHT2, ... } };`
The 2 column widths are specified as 50% or 0.50. All real numbers in the range [0.0..1.0) represents percentages e.g. see the BORDER variable. The constant FILL is allocated 100% of the scalable space and PREFERRED fills to the preferred size of the component. This allows the window to resize nicely.
To add then to this frame it's miles easier than GridBagLayout i.e. simply the cell X/Y positions e.g.
panel.add(new JButton("Withdraw"), "1,1");
panel.add(new JButton("Deposit"), "3,1");
We can span several columns as follows: -
panel.add(new JTextField(), "1,7,3,7");
This spans the JTextField from column 1 to column 3 in row 7.
For more advanced uses see: -
http://www.clearthought.info/sun/products/jfc/tsc/articles/tablelayout/Simple.html
UPDATE: I have received justified criticism for posting non working code. I've taken that to heart and am updating this post with a complete working example. I'm also updating the description accordingly:
I have a very simple java swing GUI whose components take up what looks to be an equal amount of vertical (Y) space as is used by the largest Y extent component, but completely unnecessarily so. I have tried to shrink those components that don't need that much vertical space using preferredSize hints but to no avail.
The basic layout is simple: There's a main window and three vertical panels. The layout is a simple GridLayout (and I would prefer to keep it that way, unless someone shows me what I need cannot be done with GridLayout). All three panels seem to be occupying the same amount of vertical space, even though in the case of the sliders, this is massive waste of space. How can I get each of the sub-panes to only use as much space as they each need? i.e. I would like the two slider windows to be only as tall as the sliders and their description need to be.
The code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class test {
public static void main(String[] arg) {
JFrame mainWindow = new JFrame();
JSlider slider1 = new JSlider(0,100,50);
JSlider slider2 = new JSlider(0,100,50);
JPanel pnlSlider1 = new JPanel();
pnlSlider1.setLayout(new GridLayout(1,1)); // 1 row, 1 column
pnlSlider1.add(new JLabel("Description for slider1"));
pnlSlider1.add(slider1);
JPanel pnlSlider2 = new JPanel();
pnlSlider2.setLayout(new GridLayout(1,1)); // 1 row, 1 column
pnlSlider2.add(new JLabel("Description for slider2"));
pnlSlider2.add(slider2);
// label should now be to the left of slider
String content = "<html>Some rather long winded HTML content</html>";
JEditorPane ep = new JEditorPane("text/html", content);
// this is the main window panel
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(3,1)); // 3 rows, 1 column
panel.add(ep);
panel.add(pnlSlider1);
panel.add(pnlSlider2);
// tie it all together and display the window
mainWindow.setPreferredSize(new Dimension(300, 600));
mainWindow.setLocation(100, 100);
mainWindow.getContentPane().add(panel);
mainWindow.pack();
mainWindow.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
mainWindow.setVisible(true);
}
}
(removed rant about not having seen any GUI coding advances in 30 years as that's not pertinent to the problem and likely won't be solved in this post either)
..components take up what looks to be an equal amount of vertical (Y) space as is used by the largest Y extent component, but completely unnecessarily so.
Yes, that is the way GridLayout is designed to work.
Use a GridBagLayout or BoxLayout or GroupLayout instead, each of which can do a single column or row of components of variable size (width and height).
I'm developing a Java GUI and I need:
A label in first row(only one label).
Starting 2nd row need to add say 100 buttons which extends to multiple lines(width shouldn't go beyond the visible screen)
In a new line one more Label
From next line say 100 buttons which extends to multiple lines(width shouldn't go beyond the visible screen)...
[OPTIONAL] If the components exceeds JFrame height then need a scroll facility to the main window (only vertical)
I have a strange results with flow layout, sometimes it stick to visible width, sometimes it sets even 500 buttons in a single row.
I have tried every layout and also multipanes. Still no luck.
Please guide.. just need an idea, No need of code
Updated with code: Sorry guys, that was my first question to stackoverflow
Thanks for prompt response
Infact i tried many, here is a simple one.
setLayout(new FlowLayout());
setTitle("JAVA GUI");
setSize(500,500);
setVisible(true);
add(new JLabel("row 1"));
JPanel panel1 = new JPanel(new FlowLayout());
for(int i=0;i<200;i++){
panel1.add(new JButton("b"+i));
}
add(panel1);
Here the panel1 is appearing in a sigle row which goes beyond the visible part of the screen.
I think this can be solved by setting maximumsize to Jframe, but no idea how to set its size to FULL SCREEN.
You can try MigLayout.
http://www.miglayout.com/
Also this question is not really a question for stack overflow. A good way to ask your question would be to post your code and tell us what is wrong with it and what it is supposed to do.
While this is not the norm for 'good' stackOverflow questions, I don't have any problem with it myself. Some people cannot deal with anything except code. I would suggest that, if you're going to post code, that you take the trouble to post code that will compile, run, and demonstrate your situation. It really helps those of us out here understand what you're seeing and what you're trying to do.
You talk about "rows"; be aware that rows and columns are terms used with things like GridLayout and GridBagLayout, but I don't think they're appropriate for what you describe.
In your description, you don't say what you want scrolled. It would appear you want the entirety of the UI scrolled, I'll assume that for now.
I would try a JPanel with BoxLayout, oriented vertically, for the overall main UI. You will put some things into that:
The first JPanel.
Another JPanel, set with FlowLayout, holding the first bunch of buttons.
Another JPanel with the next JLabel
And a fourth JPanel, set with FlowLayout, holding the second bunch of buttons.
Now, I would put the top-level panel into a JScrollPane, and then put that into the CENTER section of a Frame (with its default BorderLayout), and see what happens. To tell the truth, I'm not sure, but these are the things I would start with.
I cannot tell, without running code, why you get odd behavior sometimes.
As said in a previous comment, using a ContentPane is the way to go. Here is a working example of what you want:
public class Test {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setTitle("JAVA GUI");
JPanel panel1 = new JPanel();
panel1.setLayout(new BoxLayout(panel1, BoxLayout.Y_AXIS));
int nbLines = 10;
for (int i = 0; i < nbLines; i++) {
JPanel linePanel = new JPanel(new FlowLayout());
linePanel.add(new JLabel("row " + i));
for(int j = 0; j < 50; j++) {
linePanel.add(new JButton("b" + j));
}
panel1.add(linePanel);
}
frame.setContentPane(panel1);
//frame.setSize(500, 500);
frame.setExtendedState(frame.getExtendedState() | JFrame.MAXIMIZED_BOTH);
frame.pack();
frame.setVisible(true);
}
}
And here is what I get:
If you want to have left-aligned buttons you can use:
JPanel linePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
I'm trying to create a very simple window using Java Layouts. I have got three elements to arrange: a button, a progress bar and a label. The button has to be vertically centered, the progress bar has to take full width, and the label has to be left aligned.
Here's some code (just assume pane is the content pane of a JFrame, and button, progressBar and label have been created before):
BoxLayout layout = new BoxLayout(pane, BoxLayout.Y_AXIS);
pane.setLayout(layout);
button.setAlignmentX(Component.CENTER_ALIGNMENT);
pane.add(button);
progressBar.setAlignmentX(Component.CENTER_ALIGNMENT);
pane.add(progressBar);
label.setAlignmentX(Component.LEFT_ALIGNMENT);
pane.add(label);
When I test the application I see everything misaligned and screwed up: the button and the label are randomly indented, and if I resize the window the indentation amount changes in a strange way.
The progress bar looks good (full width).
I just don't understand what's happening. Can you give me a clue?
BoxLayout cannot handle different alignments: see http://download.oracle.com/javase/tutorial/uiswing/layout/box.html
quoting from that article: "In general, all the components controlled by a top-to-bottom BoxLayout object should have the same X alignment. Similarly, all the components controlled by a left-to-right Boxlayout should generally have the same Y alignment."
Sometimes you need to get a little creative and use nested panels. But I like this approach better then trying to learn and memorize all the constraints required when using other layout managers (GridBagLayout, GroupLayout) there where designed to be used by IDE's that generate code for you.
import java.awt.*;
import javax.swing.*;
public class BoxLayoutVertical extends JFrame
{
public BoxLayoutVertical()
{
Box box = Box.createVerticalBox();
JButton button = new JButton("A button");
button.setAlignmentX(Component.CENTER_ALIGNMENT);
box.add(button);
JProgressBar progressBar = new JProgressBar(0, 100);
progressBar.setAlignmentX(Component.CENTER_ALIGNMENT);
box.add(progressBar);
JPanel panel = new JPanel( new BorderLayout() );
JLabel label = new JLabel("A label");
label.setAlignmentX(Component.LEFT_ALIGNMENT);
panel.add(label);
box.add(panel);
add(box, BorderLayout.NORTH);
}
public static void main(String[] args)
{
BoxLayoutVertical frame = new BoxLayoutVertical();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.setSize(300, 200);
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
To complement my comment to the original question, here is a snippet that uses DesignGridLayout:
JButton button = new JButton("Button");
JProgressBar progressBar = new JProgressBar();
JLabel label = new JLabel("Label");
// The interesting stuff is in the next 4 lines
DesignGridLayout layout = new DesignGridLayout(getContentPane());
layout.row().center().add(button).withOwnRowWidth();
layout.row().center().fill().add(progressBar);
layout.row().left().add(label);
pack();
It does exactly what wou describe in your question and doesn't require any specific call of any of the components.
Maybe your code is just a snippet, but I'm missing a call to pack().
Coding swing layout by hand can be very frustrating with the standard Layout managers. I use MiG Layout for that purpose. It is straight forward and you have a nice layout with just a few lines of code. If you're not forced to use BoxLayout I would suggest you give it a try.
Don't use BoxLayout. It works only for very simple cases.
For your case, I would recommend either GridBagLayout or (my favorite) GroupLayout.
For GroupLayout, I created a subclass (LayoutHelper) with some utility methods and useful constructors, which makes writing the Layout much easier.
Of course, usually I align all components in a group the same way, so it is not as short in your case as it would be in the simple case.
LayoutHelper h = new LayoutHelper(pane);
h.setVerticalGroup
( h.sequential( button, progressBar, label));
h.setHorizontalGroup
( ((ParallelGroup)h.parallel())
.addComponent(button, Alignment.CENTER)
.addComponent(progressBar)
.addComponent(label, Alignment.TRAILING));
Here is a screenshot:
For a simple "everything aligned the same way", the horizontal group would look like this:
h.setHorizontalGroup
( h.parallel (button, progressBar, label));
(optionally with a first argument indicating the alignment).
I am given an assignment but I am totally new to Java (I have been programming in C++ and Python for two years).
So we are doing GUI and basically we extended JFrame and added a couple fields.
Say we have a field named "Text 1" and "Text 2". When user presses enter with the cursor in Text 1, move the focus to Text 2. I tried to add
private JTextField textfield1() {
textfield1 = new JTextField();
textfield1.setPreferredSize(new Dimension(200, 20));
textfield1.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
textfield1text = textfield1.getText().trim();
textfield1.setText(textfield1text);
System.out.println(textfield1text);
textfield1.requestFocus();
}
});
return textfield1;
}
But that doesn't work at all.
I noticed that requestFocus is not recommended, and instead one should use requestFocusWindows. But I tried that too. Upon some readings it seems like I have to do keyboard action and listener? But my teacher said it only requires 1 line...
Well, you have textfield1.requestFocus(), but your description would imply you need textfield2.requestFocus(). (that's 2).
Another option might be to use:
textField1.transferFocus();
This way you don't need to know the name of the next component on the form.