JLabel not positioning correctly - java

I am just throwing together a quick and dirty GUI to display some data when I ran into an odd issue. The last label I add to the JFrame doesn't want to be positioned or display the border I put on it, so it looks like this:
Here is my code:
public DisplayData (Connection tConn)
{
ID = tID;
conn = tConn;
setupObjects();
setupFrame();
}
private void setupObjects()
{
JLabel caseLabel = new JLabel ("Case #:");
JLabel dateLabel = new JLabel ("Date:");
JLabel reportLabel = new JLabel ("Report:");
JLabel offenceLabel = new JLabel ("Offence:");
JLabel descriptionLabel = new JLabel ("Description:");
this.add(caseLabel);
this.add(dateLabel);
this.add(reportLabel);
this.add(offenceLabel);
this.add(descriptionLabel);
caseLabel.setBounds(50, 50, 130, 25); //x, y, width, height
dateLabel.setBounds(50, 100, 130, 25);
reportLabel.setBounds(50, 150, 130, 25);
offenceLabel.setBounds(50, 200, 130, 25);
descriptionLabel.setBounds(100, 50, 130, 25);
caseLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
dateLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
reportLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
offenceLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
descriptionLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
}
private void setupFrame()
{
this.setTitle("Data Display");
this.setSize (650, 700); //Width, Height
this.setLocation(300, 10);
this.setResizable(false);
this.setVisible(true);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLayout(null);
}
Yes, I know I should be using a proper layout manager, but like I said i just wanted something quick and dirty. Plus, I will not be beaten by something that should be this simple. Any ideas would be appreciated.
EDIT:
As Compass and Neophyte pointed out, my order of operations was off. Flipped my method calls and all is good again in the world. Thanks for the 2nd pair of eyes.

Contrary to the original poster's strategy, or any of the answers so far, the best approach to this problem is to use layouts.
Here is an example that shows how easy it is to position fields using layouts, and to change the GUI on later updates to the specification.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class CourtDetailsGUI {
private JComponent ui = null;
static final String[] FIELD_NAMES = {
"Case #:",
"Date:",
"Report:",
"Offence:",
"Plaintiff:",
"Defendant:"
};
CourtDetailsGUI(int num) {
initUI(num);
}
public void initUI(int num) {
if (ui != null) {
return;
}
ui = new JPanel(new BorderLayout(4, 4));
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
ui.add(getFieldsPanel(num), BorderLayout.PAGE_START);
JTextArea ta = new JTextArea(5, 40);
JScrollPane sp = new JScrollPane(ta);
JPanel p = new JPanel(new GridLayout());
p.add(sp);
p.setBorder(new TitledBorder("Details"));
ui.add(p);
}
private JPanel getFieldsPanel(int num) {
JPanel outerPanel = new JPanel(new FlowLayout());
JPanel innerPanel = new JPanel(new GridLayout(0, 1, 15, 15));
outerPanel.add(innerPanel);
for (int ii=1; ii<num; ii++) {
JLabel l = new JLabel(FIELD_NAMES[ii]);
l.setBorder(new LineBorder(Color.BLACK));
innerPanel.add(l);
}
return outerPanel;
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
for (int ii=0; ii<FIELD_NAMES.length; ii++) {
CourtDetailsGUI o = new CourtDetailsGUI(ii+1);
JFrame f = new JFrame("Data " + (ii+1));
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
}
};
SwingUtilities.invokeLater(r);
}
}

Your order of operations is incorrect.
You initially call setupObjects();
This plays your objects out onto a JFrame, which has the default LayoutManager of BorderLayout.
By using the default add(Component comp) method, with BorderLayout, you end up putting the component into null for BorderLayout, which is not supposed to be normal. Furthermore, the reason you can't see the border for this object is because the border is actually the size of the frame. If you explicitly set a region for BorderLayout, then you'll see it work, but setting to no region seems to just break BorderLayout.
Additional add calls appear to free the previous item from the BorderLayout null management, allowing the bounds to take over.
Afterwards, you call setupFrame(); which removes the layout manager, but does not refresh what is currently rendered.
This sets the layout to null, which does nothing to how the frame is displayed, but just removes the layout.
To avoid this issue, call setupFrame(); prior to setupObjects();, and then setVisible(true) can be called at the end of setupObjects();

Related

How to make a JPanel that work like JOptionPane?

I'm making a simple POS system on NetBeans that would pop out a JPanel (quantity) asking for the quantity when the photo of the product is clicked. I am using a card layout and putting the panel inside the card layout doesn't seem to work as it is different in size. It's also very hard to position it since moving it makes a bigger panel (buy) absorb it and becomes a part of the panel, messing up the layout of that panel. I want to make the panel initially invisible and pop up only with this code:
public void mouseClicked(MouseEvent e) {
if (e.getSource() == bpie )
{
String name = "Banoffee Pie";
int price = 8;
quantity.setVisible(true);
}
}
I'm currently a beginner and have a hard time customizing JOptionPane dialogs and prefer the use of panels if possible. The problem could be solved with the use of another JFrame, however, the use of multiple frames according to experts, is bad practice.
Here is how I want the option pane to look:
I'm currently a beginner and have a hard time customizing JOptionPanes
The JOptionPane was made for utility rather than customizability. As soon as you start thinking 'How can I change a JOptionPane to..?' abandon the option pane and instead use a modal JDialog.
Here is an example of using a dialog. I've tweaked the layout along these lines:
The food icons centered below the title bar.
Abandoned the simpler button names for more descriptive ones.
Adding the question and answer in the same line with a spinner to choose the number.
Of course, colors need to be adjusted to suit the style seen above, which might (and might not - depending on further factors not immediately evident) best be approached by using a custom Pluggable Look and Feel.
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.util.Random;
public class SweetShop {
private JComponent ui = null;
private static JFrame frame = new JFrame("Sweet Shop");
private final JDialog dialog = new JDialog(frame, "Choose Sweets", true);
Random random = new Random();
SpinnerNumberModel quantityModel = new SpinnerNumberModel(1, 1, 144, 1);
SweetShop() {
initUI();
}
public final void initUI() {
if (ui!=null) return;
ui = new JPanel(new GridBagLayout());
ui.setBorder(new EmptyBorder(40,100,40,100));
JButton button = new JButton("Buy Sweets");
ui.add(button);
ActionListener openChooserListener = (ActionEvent e) -> {
dialog.setLocationRelativeTo(button);
dialog.setVisible(true);
};
button.addActionListener(openChooserListener);
dialog.add(getSweetSelectionPanel());
dialog.pack();
}
private JPanel getSweetSelectionPanel() {
JPanel panel = new JPanel(new BorderLayout());
int pad = 10;
panel.setBorder(new EmptyBorder(pad, pad, pad, pad));
JPanel iconPanel = new JPanel();
for (int ii=0; ii<12; ii++) {
iconPanel.add(new JLabel(new ImageIcon(getSize16Image())));
}
panel.add(iconPanel, BorderLayout.PAGE_START);
JPanel buttonPanel = new JPanel();
JButton okButton = new JButton("Buy Delicious");
buttonPanel.add(okButton);
ActionListener okListener = (ActionEvent e) -> {
System.out.println("Yuuuummmmm.. x " +
quantityModel.getNumber().intValue());
dialog.setVisible(false);
};
okButton.addActionListener(okListener);
JButton cancelButton = new JButton("No Thanks");
buttonPanel.add(cancelButton);
ActionListener cancelListener = (ActionEvent e) -> {
System.out.println("I just like licking them.");
dialog.setVisible(false);
};
cancelButton.addActionListener(cancelListener);
panel.add(buttonPanel, BorderLayout.PAGE_END);
JPanel questionPanel = new JPanel();
questionPanel.setBorder(new EmptyBorder(20, 50, 20, 50));
panel.add(questionPanel); // automatically uses CENTER constraint
JLabel label = new JLabel("How many do you wish to buy?");
Font font = label.getFont();
label.setFont(font.deriveFont(Font.ITALIC));
label.setText("How many do you wish to buy?");
label.setBorder(new EmptyBorder(5, 5, 5, 5));
questionPanel.add(label);
JSpinner spinner = new JSpinner(quantityModel);
questionPanel.add(spinner);
return panel;
}
private Image getSize16Image() {
int w = 16;
int h = 16;
if (random.nextBoolean()) {
w = random.nextInt(12) + 4;
} else {
h = random.nextInt(12) + 4;
}
BufferedImage bi = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
return bi;
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = () -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
SweetShop o = new SweetShop();
frame = new JFrame(o.getClass().getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.setContentPane(o.getUI());
frame.pack();
frame.setMinimumSize(frame.getSize());
frame.setVisible(true);
};
SwingUtilities.invokeLater(r);
}
}

Scrollbar JTextarea not working

For some reason my scrollbar is appearing but it is not working. What is suppose to happen is using the scrollbar to scroll through the text of the textarea. Can somebody please explain why this isnt working?
import java.io.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class App extends JFrame{
private JPanel paneel;
public App(){
paneel = new AppPaneel();
setContentPane(paneel);
}
public static void main(String args[]){
JFrame frame = new App();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setTitle("Auto Clicker");
frame.setVisible(true);
}
}
class AppPaneel extends JPanel{
private JTextField delayField, xLocation, yLocation;
private JTextArea listArea;
private JButton addButton, saveButton, runButton;
private JScrollPane scroll;
public AppPaneel(){
setLayout(null);
delayField = new JTextField();
delayField.setBounds(10, 10, 85, 25);
delayField.setText("delay in ms");
xLocation = new JTextField();
xLocation.setBounds(105, 10, 85, 25);
xLocation.setText("X position");
yLocation = new JTextField();
yLocation.setBounds(200, 10, 85, 25);
yLocation.setText("Y position");
addButton = new JButton("Add");
addButton.setBounds(295, 10, 75, 24);
addButton.addActionListener(new AddHandler());
listArea = new JTextArea();
listArea.setBounds(10, 45, 360, 180);
scroll = new JScrollPane(listArea);
scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scroll.setBounds(370, 45, 20, 180);
saveButton = new JButton("Save");
saveButton.setBounds(10, 230, 85, 24);
runButton = new JButton("Run (F1)");
runButton.setBounds(105, 230, 85, 24);
runButton.addActionListener(new RunHandler());
add(delayField);
add(xLocation);
add(yLocation);
add(addButton);
add(listArea);
add(saveButton);
add(runButton);
add(scroll);
}
class AddHandler implements ActionListener{
public void actionPerformed(ActionEvent a){
listArea.setText(listArea.getText() + delayField.getText() + ", " + xLocation.getText() + ", " + yLocation.getText() + ", " + "click;" + "\n");
}
}
class RunHandler implements ActionListener{
private Robot bot;
private String text;
int foo = Integer.parseInt("1234");
public void actionPerformed(ActionEvent b) {
try{
text = listArea.getText();
bot = new Robot();
for(String line : text.split("\\n")){
int delay = Integer.parseInt((line.substring(0, 4)));
int xpos = Integer.parseInt((line.substring(6, 10)));
int ypos = Integer.parseInt((line.substring(12, 16)));
bot.mouseMove(xpos, ypos);
Thread.sleep(delay);
bot.mousePress(InputEvent.BUTTON1_MASK);
bot.mouseRelease(InputEvent.BUTTON1_MASK);
}
}
catch (AWTException | InterruptedException e){
e.printStackTrace();
}
}
}
}
Don't use null layouts and setBounds as it is messing up your program. We tell folks time and time again not to do this for a reason -- by setting the JTextArea's bound you constrain its size so it won't grow when it needs to. The solution, as always -- learn and use the layout managers. Set the JTextArea's column and row properties but not its bounds, its size, or its preferred size.
Next don't do this: Thread.sleep(delay); in your Swing application as it will put the entire application to sleep. Use a Swing Timer instead for any delays. The tutorials can help you use this.
For a non-functional layout example:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.*;
#SuppressWarnings("serial")
public class App2 extends JPanel {
private static final int GAP = 5;
private JTextField textField1 = new JTextField(GAP);
private JTextField textField2 = new JTextField(GAP);
private JTextField textField3 = new JTextField(GAP);
private JTextArea textArea = new JTextArea(15, 30);
public App2() {
JPanel topPanel = new JPanel(new GridLayout(1, 0, GAP, GAP));
topPanel.add(textField1);
topPanel.add(textField2);
topPanel.add(textField3);
topPanel.add(new JButton("Add"));
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JPanel bottomPanel = new JPanel(new GridLayout(1, 0, GAP, GAP));
bottomPanel.add(new JButton("Save"));
bottomPanel.add(new JButton("Run (F1)"));
bottomPanel.add(new JLabel(""));
bottomPanel.add(new JLabel(""));
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
setLayout(new BorderLayout(GAP, GAP));
add(topPanel, BorderLayout.PAGE_START);
add(scrollPane, BorderLayout.CENTER);
add(bottomPanel, BorderLayout.PAGE_END);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Auto Clicker");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new App2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Your whole approach is wrong. You should not be using a null layout. For example:
scroll.setBounds(370, 45, 20, 180);
you are setting the width to 20. Well how to you expect the text area to display in 20 pixels? This is the problem with using setBounds(...), the random numbers you use have no meaning. Let a layout manager do its job. Also:
add(listArea);
The problem is that a component can only have a single parent. You originally created the JScrollPane with the text area which is correct.
But then you add the text area directly to the frame which removes it from the scroll pane so the scroll panel will no longer function.
Get rid of that statement and just add the scroll pane to the frame.
However, I don't recommend you use this as your final solution. I just wanted to mention the current problems so you hopefully understand the benefits of using layout managers and so that you don't try to share components again.
The proper solution is to use layout managers as has been suggested by the "Community Wiki". Then the layout manager will determine the size and location of each component so you don't need to worry about calculating your pixel values correctly.

Assistance With KeyEvent

I am making a platformer game for a class project and so far all I have been able to do is add the chicken character to the game. I need to be able to have him move forward on the press of "D" or right arrow. My code is:
public class Main extends JFrame {
public Main(){
//Creates Title Image
JLabel title = new JLabel(" ");
ImageIcon tl = new ImageIcon("title.gif");
title.setIcon(tl);
//Creates Start Image
final JButton start = new JButton("");
ImageIcon st = new ImageIcon("start.gif");
start.setIcon(st);
//Creates Options Image
JButton options = new JButton("");
ImageIcon opt = new ImageIcon("options.gif");
options.setIcon(opt);
options.setBackground(Color.BLACK);
//Create first frame for "Start" button
final JPanel p1 = new JPanel();
p1.setLayout(new GridLayout(1, 1));
p1.add(start, BorderLayout.CENTER);
//Create second panel for title label
final JPanel p2 = new JPanel(new BorderLayout());
p2.setLayout(new GridLayout(1, 3));
p2.add(title, BorderLayout.WEST);
//Create third panel for "Options" button
final JPanel p3 = new JPanel(new BorderLayout());
p3.setLayout(new GridLayout(1, 1));
p3.add(options, BorderLayout.SOUTH);
//Creates fourth panel to organize all other primary
final JPanel p4 = new JPanel(new BorderLayout());
p4.setLayout(new GridLayout(1, 3));
p4.add(p1, BorderLayout.WEST);
p4.add(p2, BorderLayout.CENTER);
p4.add(p3, BorderLayout.EAST);
//When button is clicked, it changes the level
start.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(start.isEnabled()) {
remove(p4);
setSize(1440, 500);
add(new ContentPanel1());
validate();
}
else {
return;
}
}
});
//Adds fourth panel to frame
add(p4, BorderLayout.CENTER);
}
public static void main(String arg[]) {
Main frame = new Main();
//Finds screen size of monitor
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
//Creates the frame
frame.setTitle("Cockadoodle Duty: Awakening");
frame.setSize(screenSize);
frame.setLocale(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
String background = "#000000";
frame.setBackground(Color.decode(background));
}
}
class coordinate {
public static int x;
public static int y;
}
class ContentPanel1 extends JPanel{
Image back = Toolkit.getDefaultToolkit().getImage("level0.gif");
Image chick = Toolkit.getDefaultToolkit().getImage("chicken.gif");
ContentPanel1() {
MediaTracker mt = new MediaTracker(this);
mt.addImage(back, 0);
try {
mt.waitForAll();
} catch (InterruptedException e){
e.printStackTrace();
}
}
public void paintComponent(Graphics g){
coordinate.x = 20;
coordinate.y = 321;
super.paintComponent(g);
int imwidth = back.getWidth(null);
int imheight = back.getHeight(null);
g.drawImage(back, 1, 1, null);
g.drawImage(chick, coordinate.x, coordinate.y, null);
}
public void MoveDirection(KeyEvent e, Graphics g) {
coordinate.x = 20;
coordinate.y = 321;
super.paintComponent(g);
int key = e.getKeyCode();
if(key == 68) {
coordinate.x += 1;
g.drawImage(chick, coordinate.x, coordinate.y, null);
}
}
}
The main trouble I have been having with my code is the bit at the end with the MoveDirection method. The way I have it going is by adding a new chicken to the frame (This was mainly due to the fact that I was just testing to see if the code worked). Is there a better way to do that too?
Start by taking a look at How to Use Key Bindings
NEVER call super.paintComponent(g); (or paintComponent(g);) directly from outside the context of the paintComponent method, there is a lot more to painting then just painting the component background. See Painting in AWT and Swing and Performing Custom Painting for more details. Instead, simply call repaint when you want to, well, repaint the component.
The use of MediaTracker is out of date and you should be using the ImageIO API instead, which will block automatically while reading the image. See Reading/Loading an Image for more details
Don't use Toolkit.getDefaultToolkit().getScreenSize() in combination with JFrame#setSize, the getScreenSize method does not take into account things like the task bar or dock of some OS's, instead use the JFrame#setExtendedState and pass it JFrame.MAXIMIZED_BOTH
frame.setLocale(null); isn't doing what you think it is

How returns XxxSize from JComponent(s) added to the JLabel

how can I correctly returns XxxSize from JComponent(s) added to the JLabel
1st. figure >> lets LayoutManager works like as for JPanel, JLabel returns Size(0, 0)
2nd. figure >> added some PreferredSize to the JLabel
3rd. figure >> calculated PreferredSize from JComponent(s) added to the JLabel
4th. figure >> lets LayoutManager works changed JLabel to JPanel, now LayoutManager correctly calculated Dimension without using any XxxSize
notice sice there is used Nimbus L&F, same output is there for all accesible L&F
import java.awt.*;
import java.awt.event.*;
import java.util.LinkedList;
import java.util.Queue;
import javax.swing.*;
public class NimbusBorderPainterDemo extends JFrame {
private static final long serialVersionUID = 1L;
private JFrame frame = new JFrame();
private JPanel fatherPanel = new JPanel(), titlePanel = new JPanel();
private JLabel buttonPanel = new JLabel();
//figure ---> 4th. switch JLabel with JPanel
//private JPanel buttonPanel = new JPanel();
private Queue<Icon> iconQueue = new LinkedList<Icon>();
public NimbusBorderPainterDemo() {
iconQueue.add(UIManager.getIcon("OptionPane.errorIcon"));
iconQueue.add(UIManager.getIcon("OptionPane.informationIcon"));
iconQueue.add(UIManager.getIcon("OptionPane.warningIcon"));
JButton button0 = createButton();
JButton button1 = createButton();
JButton button2 = createButton();
button2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(1);
}
});
int gap = 5;
buttonPanel.setLayout(new GridLayout(0, 3, gap, 0));
buttonPanel.add(button0);
buttonPanel.add(button1);
buttonPanel.add(button2);
// figure 1st. ---> without PreferredSize
// figure 2nd. --->
//buttonPanel.setPreferredSize(new Dimension(160, 30));
// figure 3rd. --->
/*Dimension dim = button0.getPreferredSize();
int w = dim.width;
int h = dim.height;
w = (w + 5) * 3;
h += 4;
dim = new Dimension(w, h);
buttonPanel.setPreferredSize(dim);*/
titlePanel.setLayout(new BorderLayout());
titlePanel.add(new JLabel(nextIcon()), BorderLayout.WEST);
titlePanel.add(new JLabel("My Frame"), BorderLayout.CENTER);
titlePanel.setBorder(BorderFactory.createLineBorder(Color.GRAY));
titlePanel.add(buttonPanel, BorderLayout.EAST);
fatherPanel.setLayout(new BorderLayout());
fatherPanel.add(titlePanel, BorderLayout.CENTER);
frame.setUndecorated(true);
frame.add(fatherPanel);
frame.setLocation(50, 50);
frame.pack();
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.setVisible(true);
}
private JButton createButton() {
JButton button = new JButton();
button.setBorderPainted(false);
button.setBorder(null);
button.setFocusable(false);
button.setMargin(new Insets(0, 0, 0, 0));
button.setContentAreaFilled(false);
button.setIcon(nextIcon());
//button.setRolloverIcon(nextIcon());
//button.setPressedIcon(nextIcon());
//button.setDisabledIcon(nextIcon());
nextIcon();
return button;
}
private Icon nextIcon() {
Icon icon = iconQueue.peek();
iconQueue.add(iconQueue.remove());
return icon;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (Exception fail) {
}
UIManager.getLookAndFeelDefaults().put("nimbusFocus", Color.RED);
NimbusBorderPainterDemo nimbusBorderPainterDemo = new NimbusBorderPainterDemo();
}
});
}
}
The default preferred size calculation is to use the layout manager to determine the preferred size of a component. This means the layout manager iterates through all the child components to determine the preferred size of each. For a JPanel, which is meant to be used as a Container this calculation is used.
However, for other Swing components, the getPreferredSize() method is always overridden to provide a reasonable size for the given component.
In the case of a JLabel, the preferred size calculation takes into account the text and the icon used. Since you didn't provide either the preferred size is zero. Of course if you manually override this calculation by using the setPreferredSize() method then the component will have a preferred size.
So even though Swing allows you to add components to any component and use a layout manager to layout the child components, these child components are not used in the preferred size calculation.
This is not just a Nimbus issue.

JRadioButton Will not appear until Mouse over

import java.awt.Frame;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.*;
public class IndicatorWindow implements ItemListener {
JRadioButton RMA, EMA, SMA, Williams, Stochastic;
JPanel IndPan, RadioPanel, title;
JLabel Lab;
JButton OK;
public JPanel createContentPane() {
JPanel GUI = new JPanel();
GUI.setLayout(null);
title = new JPanel();
title.setLayout(null);
title.setLocation(0, 0);
title.setSize(500, 145);
GUI.add(title);
Lab = new JLabel("Please Select Indicator Type");
Lab.setLocation(5, 0);
Lab.setSize(200, 30);
title.add(Lab);
ButtonGroup bg1 = new ButtonGroup();
RadioPanel = new JPanel();
RadioPanel.setLayout(null);
RadioPanel.setLocation(10, 30);
RadioPanel.setSize(190, 220);
GUI.add(RadioPanel);
RMA = new JRadioButton("RMA");
RMA.setLocation(0, 0);
RMA.addItemListener(this);
RMA.setSize(110, 20);
bg1.add(RMA);
RadioPanel.add(RMA);
EMA = new JRadioButton("EMA");
EMA.setLocation(0, 30);
EMA.addItemListener(this);
EMA.setSize(110, 20);
bg1.add(EMA);
RadioPanel.add(EMA);
SMA = new JRadioButton("SMA");
SMA.setLocation(0, 60);
SMA.addItemListener(this);
SMA.setSize(110, 20);
bg1.add(SMA);
RadioPanel.add(SMA);
Stochastic = new JRadioButton("Stochastic");
Stochastic.setLocation(0, 90);
Stochastic.addItemListener(this);
Stochastic.setSize(110, 20);
bg1.add(Stochastic);
RadioPanel.add(Stochastic);
Williams = new JRadioButton("Williams");
Williams.setLocation(0, 120);
Williams.addItemListener(this);
Williams.setSize(110, 20);
bg1.add(Williams);
RadioPanel.add(Williams);
OK = new JButton();
OK.setText("Confirm");
OK.setLocation(45, 150);
OK.addItemListener(this);
OK.setSize(90, 30);
RadioPanel.add(OK);
//GUI.setOpaque(true);
return GUI;
}
public void itemStateChanged(ItemEvent e) {
Object source = e.getItemSelectable();
if (source == RMA) {
System.out.print("Browse");
} else if (source == EMA) {
System.out.print("EMA");
} else if (source == SMA) {
System.out.print("SMA");
} else if (source == Williams) {
System.out.print("Williams");
} else if (source == Stochastic) {
System.out.print("Stochastic");
}
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("Indicators");
IndicatorWindow ind = new IndicatorWindow();
frame.setContentPane(ind.createContentPane());
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(200, 250);
frame.setLayout(null);
frame.setResizable(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setAlwaysOnTop(true);
frame.setState(Frame.NORMAL);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
My problem is that when i compile and run this code, the jFrame appears but there is only one problem, 3 JRadioButtons dont appear until you put your mouse over them. The RMA and Williams radiobuttons appear, the 3 in the middle do not though, any thoughts on why this is?
http://i.stack.imgur.com/gNnIb.jpg
You should be using layout managers. People think using a "null layout" is easier, but it is not and you are more prone to having errors with your code. Layout managers will position and size components properly to make sure all components are displayed. Sometimes you even use multiple different layout managers to achieve the layout you desire.
Your problem in this case is that you have two components occupying the same space in your container. So one component gets painted over top of the other. After you mouse over your radio button, the button is repainted because of the rollover effect of the button. However, now try resizing the frame and the radio buttons will disappear because all the components are repainted and the component is painted over top of the buttons again.
The following line of code is the problem:
// title.setSize(500, 145);
title.setSize(500, 20);
But the real solution is to rewrite the code and use layout managers. While you are at it use proper Java naming conventions. Variable names do NOT start with an uppercase letter. You got "title" and "bg1" correct. So fix "EMA", "RMA" etc...
#camickr is correct. Note how using layout managers (and a little re-factoring) can actually simplify your code. Also, the relevant tutorial suggests using an action listener, rather than an item listener.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/** #see http://stackoverflow.com/questions/5255337 */
public class IndicatorWindow implements ActionListener {
JPanel radioPanel = new JPanel(new GridLayout(0, 1));
JRadioButton rma, ema, sma, stochastic, williams;
ButtonGroup bg = new ButtonGroup();
public JPanel createContentPane() {
JPanel gui = new JPanel(new BorderLayout());
JPanel title = new JPanel();
JLabel lab = new JLabel("Please Select Indicator Type");
title.add(lab);
gui.add(title, BorderLayout.NORTH);
createRadioButton(rma, "RMA");
createRadioButton(ema, "EMA");
createRadioButton(sma, "SMA");
createRadioButton(stochastic, "Stochastic");
createRadioButton(williams, "Williams");
gui.add(radioPanel, BorderLayout.CENTER);
JButton ok = new JButton();
ok.setText("Confirm");
ok.addActionListener(this);
radioPanel.add(ok);
return gui;
}
private void createRadioButton(JRadioButton jrb, String name) {
jrb = new JRadioButton(name);
bg.add(jrb);
jrb.addActionListener(this);
radioPanel.add(jrb);
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(e.getActionCommand());
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("Indicators");
frame.add(new IndicatorWindow().createContentPane());
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setAlwaysOnTop(true);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
}
You should add your JRadioButtons with a method:
private void bgAdd (String name, int y)
{
JRadioButton rb = new JRadioButton (name);
rb.setLocation (0, y);
rb.addItemListener (this);
rb.setSize (110, 19);
bg1.add (rb);
radioPanel.add (rb);
}
Calling code:
bgAdd ("RMA", 0);
bgAdd ("EMA", 30);
bgAdd ("SMA", 60);
bgAdd ("Stochastic", 90);
bgAdd ("Williams", 120);
Action:
public void itemStateChanged (ItemEvent e) {
Object button = e.getItemSelectable ();
String source = ((JRadioButton) button).getText ();
System.out.print (source + " ");
}
Then add BoxLayout to the page, for example.

Categories