I've been trying for hours, different things and searching everywhere for a solution, but I can not get my table in addScoreCardUpper() to show up. I get an horizontal scrollbar, but no content, just 2 pixels worth of border.
import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class YahtzeeGUI extends JFrame{
/**
*
*/
private static final long serialVersionUID = 3255683022699487295L;
private JFrame frame;
private JPanel panel;
private JPanel dicePanel;
private JScrollPane scrollPane;
private JButton btnRoll;
private JButton[] btnDice = new JButton[5];
private JTable table;
private Yahtzee y = new Yahtzee();
public YahtzeeGUI(){
createWindow();
addButtonRoll();
addButtonDice();
addScoreCardUpper();
//addScoreCardLower();
frame.add(panel);
frame.setVisible(true);
}
public void createWindow(){
frame = new JFrame();
frame.setTitle("Yahtzee");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1000,700);
frame.setVisible(true);
panel = new JPanel(new BorderLayout());
dicePanel = new JPanel();
scrollPane = new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
}
public void addButtonRoll(){
btnRoll = new JButton ("Roll the Dice");
btnRoll.addActionListener(new RollHandler());
dicePanel.add (btnRoll);
panel.add(dicePanel, BorderLayout.SOUTH);
}
public void addButtonDice(){
for (int i = 0; i < btnDice.length; i++){
btnDice[i] = new JButton(String.valueOf(y.dice[i].getFaceValue()));
btnDice[i].addActionListener(new HoldHandler());
dicePanel.add (btnDice[i]);
}
panel.add(dicePanel, BorderLayout.SOUTH);
}
public void addScoreCardUpper(){
String tableHeader[] = {"Upper Section", "How to score", "Score" };
String tableValues[][] = {
{"ONES", "Total of all Ones",""},
{"TWOS", "Total of all Twos",""},
{"THREES", "Total of all Threes",""},
{"FOURS", "Total of all Fours",""},
{"FIVES", "Total of all Fives",""},
{"SIXES", "Total of all Sixes",""},
{"TOTAL SCORE", "",""},
{"BONUS", "",""},
{"TOTAL + BONUS", "",""}
};
table = new JTable(tableValues, tableHeader);
table.setEnabled(false);
setColumnWidths();
scrollPane.add(table); // Here is the offender
panel.add(scrollPane, BorderLayout.EAST);
}
/*public void addScoreCardLower(){
String tableHeader[] = {"Lower S", "How to score", "Score" };
String tableValues[][] = {
{"ONES", "Total of all Ones",""},
{"TWOS", "Total of all Twos",""},
{"THREES", "Total of all Threes",""},
{"FOURS", "Total of all Fours",""},
{"FIVES", "Total of all Fives",""},
{"SIXES", "Total of all Sixes",""},
{"TOTAL SCORE", "",""},
{"BONUS", "",""},
{"TOTAL + BONUS", "",""}
};
table = new JTable(tableValues, tableHeader);
table.setEnabled(false);
setColumnWidths();
scoreSubPanel.add(table);
panel.add(scoreSubPanel, BorderLayout.WEST);
}*/
public void setColumnWidths(){
TableColumn a = table.getColumnModel().getColumn(0);
TableColumn b = table.getColumnModel().getColumn(1);
a.setPreferredWidth(100);
b.setPreferredWidth(100);
}
class RollHandler implements ActionListener {
public void actionPerformed(ActionEvent event) {
for(int i = 0; i < y.dice.length; i++){
if (y.dice[i].getHoldState() != true){
y.dice[i].roll();
btnDice[i].setText(String.valueOf(y.dice[i].getFaceValue()));
}
}
}
}
class HoldHandler implements ActionListener {
public void actionPerformed(ActionEvent event) {
for (int i = 0; i < btnDice.length; i++){
if (event.getSource()== btnDice[i]){ // Picks the pressed button after running through them all.
if (y.dice[i].getHoldState() == false){
y.dice[i].setHoldState(true);
} else if (y.dice[i].getHoldState() == true){
y.dice[i].setHoldState(false);
}
}
}
}
}
}
This is your problem:
scrollPane.add(table);
This does not add the JTable to the JScrollPane's viewport's view which is where you want it, but rather completely replaces the JScrollPane's viewport with the JTable, making the JScrollPane completely nonfunctional. Instead set the table as the JScrollPane's viewportview:
scrollPane.setViewportView(table);
Do either this or pass the table into the JScrollPane's constructor which does pretty much the same thing:
JScrollPane scrollPane = new JScrollPane(table,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
This is all well explained in the JScrollPane API, and you will want to give it a look for the important details.
Edit
Your code also calls setVisible(true) on the JFrame before adding all components which can lead to trouble. You'll want to avoid doing this.
Try any one
scrollPane = new JScrollPane(table);
or
scrollPane = new JScrollPane(table,ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
or
scrollPane.getViewport().add(table);
Related
I created a JScrollPane with a JTable on it. When the table's height is larger than the height of the scroll pane, a scroll bar appears. If minimize the JFrame although I didn't change the size of it, the scroll bar vanishes and the scroll pane extends downwards.
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class Main {
static String columns[] = {"Date", "Price", "URL", "Expired"};
static String data[][] = new String[8][4];
/*
* The data that should be provided to the JTable is
* replaced with some example data because the method
* of getting this data is complicated and doesn't
* change anything at the outcome.
*/
public static void main(String[] args) {
loadGui();
}
public static void loadGui() {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 4; j++) {
data[i][j] = "Example data " + i + " " + j;
}
}
JFrame mainFrame = new JFrame();
mainFrame.setSize(800, 300);
mainFrame.setResizable(false);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setVisible(true);
JTable table = new JTable(data, columns);;
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane pane = new JScrollPane(table);
pane.setViewportView(table);
pane.setSize(785, 100);
mainFrame.add(pane);
table.getTableHeader().setReorderingAllowed(false);
table.setDefaultEditor(Object.class, null);
table.setFocusable(false);
table.setRowSelectionAllowed(false);
}
}
I search for a way to stop the scroll pane to extend downwards and keeping it in its size.
You can use BorderLayout layout manager to make your scroll pane stick to the top
You can use setPreffered size to suggest to the layout manager what dimensions element should have if possible
Use setVisible when all components are already added
public class Main {
static String columns[] = {"Date", "Price", "URL", "Expired"};
static String data[][] = new String[8][4];
/*
* The data that should be provided to the JTable is
* replaced with some example data because the method
* of getting this data is complicated and doesn't
* change anything at the outcome.
*/
public static void main(String[] args) {
loadGui();
}
public static void loadGui() {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 4; j++) {
data[i][j] = "Example data " + i + " " + j;
}
}
JFrame mainFrame = new JFrame();
mainFrame.setSize(800, 300);
mainFrame.setResizable(false);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//set our layour manager
mainFrame.setLayout(new BorderLayout());
JTable table = new JTable(data, columns);;
table.setPreferredScrollableViewportSize(table.getPreferredSize());
table.getTableHeader().setReorderingAllowed(false);
table.setDefaultEditor(Object.class, null);
table.setFocusable(false);
table.setRowSelectionAllowed(false);
JScrollPane pane = new JScrollPane(table);
pane.setViewportView(table);
// we would like to have its height at 100px, width does not matter thus 0
pane.setPreferredSize(new Dimension(0,100));
//using NORTH will "stick" the component to the top
mainFrame.add(pane,BorderLayout.NORTH);
//all the calculation will be done now. The same happens when you minimize/restore the frame.
mainFrame.setVisible(true);
}
}
i have 10 jcheckbox and only 5 should be selected. i already did all the coding for this one, but i don't know how to display the selected 5 into a jlabel. i tried doing it by this code:
JCheckBox check;
JPanel panel=new JPanel();
for(int i=0; i<10; i++){
check=new JCheckBox();
check.addActionListener(listener);
check.setName("Select"+i);
panel.add(check);
}
this is the listener
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
check = (JCheckBox) e.getSource();
name=check.getName();
}
};
and this is the panel where it should be displayed into jlabel
panel2=new JPanel(new GridLayout(5,1));
for(int i=0; i<5; i++){
txtVote=new JLabel(name);
panel2.add(txtVote);
}
but using this code, it doesn't display anything on the jlabel. if i change the listener into this:
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
check = (JCheckBox) e.getSource();
txtVote.setText(check.getName());
}
};
it will only display into the last label. other jlabels would be blank. please help thank you so much
EDIT
here is the code that is runnable
public class JCheckBoxtoLabel{
JCheckBox check;
String name;
JLabel txtVote;
public JCheckBoxtoLabel() {
JFrame frame = new JFrame();
JPanel panel = createPanel();
JPanel panel2 = panel2();
frame.setLayout(new GridLayout(1,2));
frame.add(panel); frame.add(panel2);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JPanel createPanel() {
JPanel panel=new JPanel(new GridLayout(10,1));
for(int i=0; i<10; i++){
check=new JCheckBox();
check.addActionListener(listener);
check.setName("Select"+i);
panel.add(check);
}
return panel;
}
private JPanel panel2(){
JPanel panel2=new JPanel(new GridLayout(5,1));
for(int i=0; i<5; i++){
txtVote=new JLabel();
txtVote.setBorder(BorderFactory.createLineBorder(Color.RED));
panel2.add(txtVote);
}
return panel2;
}
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
check = (JCheckBox) e.getSource();
txtVote.setText(check.getName());
}
};
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new JCheckBoxtoLabel();
}
});
}
}
Consider changing what you're doing and displaying the text in a JList and not in JLabels. This can help you consolidate your information. You can also give your JCheckBoxes or JRadioButtons and ItemListener that only allows 5 of the buttons to be selected at a time -- unselecting the oldest one currently selected. For instance:
import java.awt.GridLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class FiveNames extends JPanel {
private static final String[] ALL_NAMES = {"Bob", "Bill", "Frank", "Helen",
"Erica", "Mickey", "Donald", "Hillary", "Michael", "Peter", "Roger"};
private static final int ALLOWED_SELECTIONS_COUNT = 5;
private DefaultListModel<String> displayListModel = new DefaultListModel<>();
private JList<String> list = new JList<>(displayListModel);
public FiveNames() {
JPanel namePanel = new JPanel(new GridLayout(0, 1, 0, 5));
RButtonItemListener rButtonListener = new RButtonItemListener();
for (String name : ALL_NAMES) {
JRadioButton rButton = new JRadioButton(name);
rButton.setActionCommand(name);
rButton.addItemListener(rButtonListener);
namePanel.add(rButton);
}
list.setVisibleRowCount(ALLOWED_SELECTIONS_COUNT);
list.setPrototypeCellValue(" ");
list.setBackground(null);
setLayout(new GridLayout(1, 0));
add(namePanel);
add(list);
}
// listener to only allow the last 5 radiobuttons to be selected
private class RButtonItemListener implements ItemListener {
private List<ButtonModel> buttonModelList = new ArrayList<>();
#Override
public void itemStateChanged(ItemEvent e) {
JRadioButton rBtn = (JRadioButton) e.getSource();
ButtonModel model = rBtn.getModel();
if (e.getStateChange() == ItemEvent.SELECTED) {
buttonModelList.add(model);
if (buttonModelList.size() > ALLOWED_SELECTIONS_COUNT) {
for (int i = 0; i < buttonModelList.size() - ALLOWED_SELECTIONS_COUNT; i++) {
ButtonModel removedModel = buttonModelList.remove(0);
removedModel.setSelected(false);
}
}
} else {
buttonModelList.remove(model);
}
displayListModel.clear();
for (ButtonModel buttonModel : buttonModelList) {
displayListModel.addElement(buttonModel.getActionCommand());
}
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("FiveNames");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new FiveNames());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
The problem is that txtVote is only a single Jlabel and you are trying to use it for all 5. Since the fifth jlabel was the last to be created it is the one being used. My suggestion is that you create an arraylist field and inside panel12 add each label to the arraylist. Then inside the listener it would iterate through each jlabel in the arraylist check if has text set to it, if so check the next one until it finds one with no text, then sets the text to that. The problem with this at the moment is that in your code you are never defining what happens when they uncheck the box.
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class JCheckBoxtoLabel{
JCheckBox check;
String name;
JLabel txtVote;
ArrayList<JLabel> boxLabels;
public JCheckBoxtoLabel() {
boxLabels = new ArrayList<JLabel>();
JFrame frame = new JFrame();
JPanel panel = createPanel();
JPanel panel2 = panel2();
frame.setLayout(new GridLayout(1,2));
frame.add(panel); frame.add(panel2);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JPanel createPanel() {
JPanel panel=new JPanel(new GridLayout(10,1));
for(int i=0; i<10; i++){
check=new JCheckBox();
check.addActionListener(listener);
check.setName("Select"+i);
panel.add(check);
}
return panel;
}
private JPanel panel2(){
JPanel panel2=new JPanel(new GridLayout(5,1));
for(int i=0; i<5; i++){
txtVote=new JLabel();
txtVote.setBorder(BorderFactory.createLineBorder(Color.RED));
panel2.add(txtVote);
boxLabels.add(txtVote);
}
return panel2;
}
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
check = (JCheckBox) e.getSource();
if(!check.isSelected()){
for(JLabel label: boxLabels){
if(label.getText().equals(check.getName())) label.setText("");
}
}else{
for(JLabel label: boxLabels){
if(label.getText().isEmpty()){
label.setText(check.getName());
return;
}
}
}
}
};
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new JCheckBoxtoLabel();
}
});
}
}
Your variable JLabel txtVote is a single JLabel object, not an array.
In your panel2() function you assign 5 new JLabels to txtVote. Since you assign 5 in a row, it gets overriden each time so it only ever contains the final JLabel.
private JPanel panel2(){
JPanel panel2=new JPanel(new GridLayout(5,1));
for(int i=0; i<5; i++){
txtVote=new JLabel();
txtVote.setBorder(BorderFactory.createLineBorder(Color.RED));
panel2.add(txtVote);
}
return panel2;
}
So when you call getText on voteTxt in the action listener, you are only getting the last labels text.
To fix this, you need to make txtVote an array of JLabels, and in your action listener iterate a second time through your JLabels and call get text on each in turn.
ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
check = (JCheckBox) e.getSource();
for (int i = 0; i < txtVotes.length; i++) {
txtVotes[i].getText(check.getName());
}
}
};
I don't know if you realise or want to, but each label is being set to the same value, if you don't want this you will need to store an array of check names somewhere and iterate through these as well.
in this code the first three buttons appear on the text area, how can I make these buttons start from below the header? before adding the button the buttonarea started below the header, but once I added the button it appeared on the header
public Design ()
{
header = new JPanel ();
header.setBounds(0, 0, 300, 100);
header.setBackground(Color.WHITE);
header.setLayout (null);
buttonarea = new JPanel ();
buttonarea.setBounds (0,0, 300, 300);
buttonarea.setBackground(Color.BLACK);
buttonarea.setLayout(new GridLayout (6,3));
add (header);
add (buttonarea);
zero = new JButton ("0");
zero.setBackground(Color.PINK);
one = new JButton ("1");
one.setBackground(Color.PINK);
two = new JButton ("2");
two.setBackground(Color.PINK);
three = new JButton ("3");
three.setBackground(Color.PINK);
four = new JButton ("4");
four.setBackground(Color.PINK);
five = new JButton ("5");
five.setBackground(Color.PINK);
six = new JButton ("6");
six.setBackground(Color.PINK);
seven = new JButton ("7");
seven.setBackground(Color.PINK);
eight = new JButton ("8");
eight.setBackground(Color.PINK);
nine = new JButton ("9");
nine.setBackground(Color.PINK);
add = new JButton ("+");
add.setBackground(Color.PINK);
subtract = new JButton ("-");
subtract.setBackground(Color.PINK);
divide = new JButton ("*");
divide.setBackground(Color.PINK);
multiply = new JButton ("/");
multiply.setBackground(Color.PINK);
square = new JButton ("x^2");
square.setBackground(Color.PINK);
equal = new JButton ("=");
equal.setBackground(Color.PINK);
c = new JButton ("C");
c.setBackground(Color.PINK);
clear = new JButton ("delete");
clear.setBackground(Color.PINK);
dot = new JButton (".");
dot.setBackground(Color.PINK);
written = new JTextArea ();
written.setBackground(Color.WHITE);
header.add (written);
buttonarea.add (c);
buttonarea.add (clear);
buttonarea.add (equal);
buttonarea.add (zero);
buttonarea.add (one);
buttonarea.add (add);
buttonarea.add (two);
buttonarea.add (three);
buttonarea.add (subtract);
buttonarea.add (four);
buttonarea.add (five);
buttonarea.add (multiply);
buttonarea.add (six);
buttonarea.add (seven);
buttonarea.add (square);
buttonarea.add (eight);
buttonarea.add (nine);
buttonarea.add (dot);
}
While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
Use a BorderLayout for the main GUI, placing the JTextField BorderLayout.PAGE_START. Place the JButtons within a GridLayout using JPanel, and place this JPanel in the BorderLayout.CENTER position of the main GUI.
For example this GUI:
Can be made with this GUI:
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class SimpleCalc extends JPanel {
private static final String[][] BTN_TEXTS = {
{"C", "Del", "X^2", "+"},
{"7", "8", "9", "-"},
{"4", "5", "6", "*"},
{"1", "2", "3", "/"},
{"0", ".", "", "="}
};
private static final int COLS = 12;
private static final int GAP = 3;
private static final char[] NUMBER_ARRAY = "0123456789".toCharArray();
private static final List<Character> NUMBER_LIST = new ArrayList<>();
private static final float FONT_SIZE = 36f;
private JTextField display = new JTextField(COLS);
static {
for (char c : NUMBER_ARRAY) {
NUMBER_LIST.add(c);
}
}
public SimpleCalc() {
display.setFont(display.getFont().deriveFont(FONT_SIZE));
display.setFocusable(false);
int rows = BTN_TEXTS.length;
int cols = BTN_TEXTS[0].length;
JPanel buttonPanel = new JPanel(new GridLayout(rows, cols, GAP, GAP));
for (String[] btnTextRow : BTN_TEXTS) {
for (String btnText : btnTextRow) {
if (btnText.isEmpty()) {
buttonPanel.add(new JLabel());
} else {
Action action = null;
if (NUMBER_LIST.contains(btnText.charAt(0))) {
action = new NumericAction(btnText);
} else if (".".equals(btnText)) {
action = new DotAction(btnText);
} else {
action = new OperationAction(btnText);
}
JButton button = new JButton(action);
button.setFont(button.getFont().deriveFont(Font.BOLD, FONT_SIZE));
buttonPanel.add(button);
}
}
}
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
setLayout(new BorderLayout(GAP, GAP));
add(display, BorderLayout.PAGE_START);
add(buttonPanel, BorderLayout.CENTER);
}
private class NumericAction extends AbstractAction {
public NumericAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
String text = display.getText();
text += e.getActionCommand();
display.setText(text);
}
}
private class DotAction extends AbstractAction {
public DotAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
String text = display.getText();
if (text.contains(".")) {
return; // only one dot allowed
}
text += e.getActionCommand();
display.setText(text);
}
}
private class OperationAction extends AbstractAction {
public OperationAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO write code for operations buttons
}
}
private static void createAndShowGui() {
SimpleCalc mainPanel = new SimpleCalc();
JFrame frame = new JFrame("SimpleCalc");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
add (header);
add (buttonarea);
I'm guess you are using a JFrame which uses a BorderLayout. The above code is adding two compenents to the CENTER of the BorderLayout which is not allowed.
Instead you should specify the appropriate constraint:
add (header, BorderLayout.PAGE_NORTH);
add (buttonarea, BorderLayout.CENTER);
And if you are not using a BorderLayout on your frame then you should. Read the section from the Swing tutorial on How to Use BorderLayout for more information and examples.
Also, when creating a JTextAra you should use:
written = new JTextArea (row, columns);
to give the text area an appropriate size. In this case you can probably just add the text area directly to the frame:
//add (header, BorderLayout.PAGE_NORTH);
add (written, BorderLayout.PAGE_NORTH);
There is no need for the wrapper panel.
I have declared an array:
private javax.swing.JPanel[] panelArray = new javax.swing.JPanel[3];
I also have 3 panels: panel0, panel1 and panel2. Can I add these panels to the array? i.e
panelArray[0] = panel0;
panelArray[1] = panel1;
panelArray[2] = panel2;
And then manipulate the arrays like this?
boolean[] myBools; .... then set them as true/false
for(int i=0; i<3; i++)
{
if(myBools[i])
panelArray[i].setVisible(true)
}
Because that does not work for me
On my side it's working fine, in this program :
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class MyPanel
{
private JPanel[] panelArray = new JPanel[3];
private boolean[] myBools = new boolean[]{false, false, false};
private int counter = 0;
private int prvPanelCounter = 0;
private Timer timer;
private ActionListener timerAction = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
counter++;
if (counter > 2)
counter = 0;
myBools[counter] = true;
for (int i = 0; i < 3; i++)
{
if (myBools[i])
{
panelArray[i].setVisible(myBools[i]);
panelArray[prvPanelCounter].setVisible(myBools[prvPanelCounter]);
myBools[i] = false;
prvPanelCounter = i;
break;
}
}
}
};
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("Locate Mouse Position");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel panel0 = new JPanel();
panel0.setOpaque(true);
panel0.setBackground(Color.BLUE);
JPanel panel1 = new JPanel();
panel1.setOpaque(true);
panel1.setBackground(Color.RED);
JPanel panel2 = new JPanel();
panel2.setOpaque(true);
panel2.setBackground(Color.DARK_GRAY);
panelArray[0] = panel0;
panelArray[1] = panel1;
panelArray[2] = panel2;
JComponent contentPane = (JComponent) frame.getContentPane();
contentPane.setLayout(new GridLayout(0, 1));
frame.add(panel0);
frame.add(panel1);
frame.add(panel2);
panel0.setVisible(myBools[counter]);
panel1.setVisible(myBools[counter]);
panel2.setVisible(myBools[counter]);
frame.setSize(300, 300);
frame.setLocationByPlatform(true);
frame.setVisible(true);
timer = new Timer(1000, timerAction);
timer.start();
}
public static void main(String\u005B\u005D args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new MyPanel().createAndDisplayGUI();
}
});
}
}
What you want to do can be done, but here's a few points to bear in mind:
Make sure you initialise the JPanels before referencing them.
The statement "panelArray[i].setVisible(true)" needs a semicolon after it.
None of these panels will be visible unless you add them to another component, such as a JFrame.
Rather than state javax.swing.JPanel, you could just import the JPanel at the top of the page and refer to it as simply JPanel.
Your "if" statement is unnecessary. Just do .setVisible(myBools[i]);
Hope these were of some help to you.
Yes, you can. Did you really not initialize the myBools array with new ?
I'm trying to do as the title says.
I've got an efficient way for posting several of the same swing objects to a frame by storing them in an array and adding them using a for loop like so:
JLabel[] contrllabels= new JLabel[8];
contrllabels[0] = new JLabel("SCF Type: ");
contrllabels[1] = new JLabel("Units: ");
contrllabels[2] = new JLabel("Spherical Harmonics: ");
contrllabels[3] = new JLabel("Molecular Charge: ");
contrllabels[4] = new JLabel("PP: ");
contrllabels[5] = new JLabel("DFT Type: ");
contrllabels[6] = new JLabel("Max Iterations: ");
contrllabels[7] = new JLabel("Mult: ");
for(int i = 0;i<contrllabels.length;i++){
c.gridy = i;
frame.add(contrllabels[i],c);
}
But what if there are several swing objects of different types? I've got several combo boxes and textfields which I'd like to be added to the frame in a similar manner. I use gridbaglayout so if I don't use a for loop, I end up with lots of unnecessary code due to giving the constraints new values every time I want a different object added.
Is there such thing as an array of references which point to these different objects which I can then iterate through to add to the frame? Something like
JTextField tf = new JTextField(5);
JComboBox cb = new JComboBox("example");
Swing[] array = {tf,cb}
for(int i = 0;i<array.length;i++){
c.gridy = i;
frame.add(array[i],c);
}
I know such an array doesn't exist, but is there some way of implementing such a thing? It would greatly reduce the number of lines in my code and make it less confusing.
Thank you
You could use an array or collection of a common super type such as an array or ArrayList of JComponent. I'm curious if you're using a parallel array of GridBagConstraints to go with each component that is being added -- ugh. I often use arrays of components but usually if they are like components such as JLabel/JTextField pairs or a cluster of JRadioButtons.
As an aside, for my money, I try to avoid GridBagLayout as much as possible and instead nest containers that use the more coder-friendly layouts.
For instance this small GUI was made with a combination of FlowLayout, BoxLayout, BorderLayout and GridLayout:
The large JPanel that holds the whole GUI uses BorderLayout, The JTextArea in the center is placed BorderLayout.CENTER, the Provider JLabel and JTextField at the top are in a FlowLayout JPanel that is placed overall BorderLayout.NORTH, the bottom buttons are in a JPanel that uses GridLayout(1, 0, 5, 0) which is held in another JPanel that uses FlowLayout which is placed in the GUI BorderLayout.SOUTH, and the stuff on the right are in a BoxLayout using JPanel.
For example:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.UnsupportedLookAndFeelException;
#SuppressWarnings("serial")
public class GetLetterTextGui extends JPanel {
private static final int TA_ROWS = 20;
private static final int TA_COLS = 35;
private static final int PROVIDER_FIELD_COLS = 10;
private static final String GUI_TITLE = "Get Letter Text";
private JList letterList;
private JTextArea textarea = new JTextArea(TA_ROWS, TA_COLS);
private JTextField providerField = new JTextField(PROVIDER_FIELD_COLS);
private JCheckBox addValedictionChkBox = new JCheckBox("Add Valediction", true);
public GetLetterTextGui() {
letterList = new JList(new String[]{"Fe", "Fi", "Fo", "Fum"});
providerField.setText("John Smith, MD");
textarea.setWrapStyleWord(true);
textarea.setLineWrap(true);
JPanel northPanel = new JPanel();
northPanel.add(new JLabel("Provider:"));
northPanel.add(providerField);
JPanel southPanel = new JPanel();
JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 0));
btnPanel.add(new JButton("Copy to Clipboard"));
btnPanel.add(new JButton("Clear"));
btnPanel.add(new JButton(new ExitAction()));
southPanel.add(btnPanel);
JPanel eastPanel = new JPanel();
eastPanel.setLayout(new BoxLayout(eastPanel, BoxLayout.PAGE_AXIS));
eastPanel.add(new JScrollPane(letterList));
eastPanel.add(new JPanel() {{add(addValedictionChkBox);}});
int eb = 0;
setBorder(BorderFactory.createEmptyBorder(eb, eb, eb, eb));
setLayout(new BorderLayout(eb, eb));
add(northPanel, BorderLayout.PAGE_START);
add(eastPanel, BorderLayout.LINE_END);
add(new JScrollPane(textarea), BorderLayout.CENTER);
add(southPanel, BorderLayout.PAGE_END);
}
private class ExitAction extends AbstractAction {
private final Object MNEMONIC = new Integer(KeyEvent.VK_X);
public ExitAction() {
super("Exit");
putValue(MNEMONIC_KEY, MNEMONIC);
}
#Override
public void actionPerformed(ActionEvent evt) {
Window win = SwingUtilities.getWindowAncestor(GetLetterTextGui.this);
win.dispose();
}
}
private static void createAndShowGui() {
GetLetterTextGui mainPanel = new GetLetterTextGui();
JFrame frame = new JFrame(GUI_TITLE);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
}
}
All GUI components are JComponent objects. ArrayList<JComponent> can hold references to all of them. Give it a try:
JFrame frame = new JFrame("test");
ArrayList<JComponent> cps = new ArrayList<JComponent>();
cps.add(new JLabel("Hello"));
cps.add(new JPanel());
cps.add(new JButton("OK"));
for (JComponent widget : cps) {
frame.add(widget);
}