java: how to make srollable panel with radio button and labels inside? - java

I got a JScrollPane in which I want to place a list of radio buttons and labels. My problem is the panel doesn't scroll, I suppose it's because i didn't set a viewport, but how can I set it when I have to many components?
My code looks something like this:
JScrollPane panel = new JScrollPane();
JRadioButton myRadio;
JLabel myLabel;
for(int i = 0; i<100; i++){
myRadio = new JRadioButton();
myLabel = new JLabel("text");
panel.add(myRadio);
panel.add(myLabel);
}
Thanks.

It is better to put your buttons and labels in a wrapper JPanel and then drop that into a JScrollPane.
try this:
JPanel panel = new JPanel(new GridLayout(0,1));
JRadioButton myRadio;
for(int i = 0; i<100; i++){
myRadio = new JRadioButton("text" + i);
panel.add(myRadio);
}
JScrollPane scrollPane = new JScrollPane(panel);
be sure to look into ButtonGroup as well. ButtonGroups allow you to enforce the single selection constraint common to radio buttons.

Related

JComboBox showing only if it has a single item

I have a JPanel with a CardLayout and a JComboBox inside it. They are dinamically filled with data taken from a JTable. If the JComboBox has a single item it shows just fine, but if I fill it with more than one it doesn't show.
JPanel intervalPanel = new JPanel;
CardLayout intervalLayout = new CardLayout();
intervalPanel.setLayout(intervalLayout);
JComboBox intervalComboBox = new JComboBox();
for (int i = 0; i < table.getRowCount(); i++) {
String name = (String) table.getValueAt(i, 0);
intervalComboBox.addItem(name);
JPanel p = new JPanel();
p.setName(name);
p.add(intervalComboBox);
p.add(new JLabel(name));
intervalPanel.add(p, name);
}
A Swing component can only have a single parent.
p.add(intervalComboBox);
The above statement keeps removing the combo box from the previous panel and adds it to the current panel.
but if I fill it with more than one it doesn't show.
So the reason it doesn't show is because it is only visible on the last card, but you current see the first card.
The better solution is to NOT add the combo box to the panel in the CardLayout. Instead your main panel should use a BorderLayout. Then the basic logic would be something like:
JPanel main = new JPanel( new BorderLayout() );
JComboBox comboBox = new JComboBox(...);
main.add(comboBox, BorderLayout.PAGE_START);
JPanel card = new JPanel( intervalLayout );
main.add(card, BorderLayout.CENTER);
frame.add( main );
Then you just add child panels to the "card" panel as required.
Read the section from the Swing tutorial on How to Use CardLayout for a complete working demo that uses the above design concept.

Java Button Action Command

I'm creating a simple Minesweeper game in Java. Size 9x9.
I create an array of JPanels and an array of buttons; I add each button to its respective JPanel. then i add the JPanels to the JFrame.
How do i distinguish between each button on the action event?
Here's some of my code:
int gridx = 9;
int gridy = 9;
JButton[] buttons = new JButton[gridx*gridy];
JPanel[] jpanels = new JPanel[gridx*gridy];
public Minesweeper(){
super("Minesweeper");
setLayout(new GridLayout(9,9));
JPanel panel = new JPanel();
int i = 0;
for(i = 0; i<gridx*gridy; i++){
jpanels[i] = new JPanel();
buttons[i] = new JButton();
buttons[i].addActionListener(buttonEvent);
jpanels[i].setLayout(new GridLayout(1,1));
jpanels[i].add(buttons[i]);
add(jpanels[i]);
}
//buttons[67].setEnabled(false);
setSize(300,300);
setVisible(true);
}
The only way i can think about doing this is adding text to the button like so:
buttons[i] = new JButton(i);
Then calling getActionCommand() but i dont want text to show up on the button. Any other ideas?
You can use AbstractButton#setActionCommand.
In your loop:
buttons[i].setActionCommand(i+"");
Then you'll get i back when you use getActionCommand
Note I did mention in a comment on another answer that I would create a new class Mine which extends JButton which I believe to be a better and more complete solution. This however gets the job done rather quickly.

JScrollPane increases its size

I have a panel which is divided by two parts with BoxLayout.X_AXIS:
public TabsPanel() {
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
add(createLeftPanel());
add(createRightPanel());
}
Each left and right panels have the following structure: an outer panel with BorderLayout, and an inner panel in BorderLayout.CENTER of the outer panel, which in its turn has BoxLayout.Y_AXIS and several components from top to bottom. The right panel has JTextArea with JScrollPane as one of its components:
protected JPanel createRightPanel() {
JPanel pane = new JPanel();
pane.setLayout(new BorderLayout());
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
JTextArea label = createLabel();
JScrollPane scroll = new JScrollPane(label);
scroll.setMaximumSize(new Dimension(500, 200));
panel.add(Box.createRigidArea(new Dimension(0,106)));
panel.add(scroll);
JPanel panel_buttons = new JPanel();
panel_buttons.setLayout(new BoxLayout(panel_buttons, BoxLayout.LINE_AXIS));
panel_buttons.setAlignmentX(Component.CENTER_ALIGNMENT);
Font font_text = new Font("Georgia", Font.PLAIN, 20);
JButton[] buttons = new JButton[2];
buttons[0] = new JButton("Clear");
buttons[1] = new JButton("Exit");
for (int i = 0; i < buttons.length; i++) {
buttons[i].setMaximumSize(new Dimension(120, 40));
buttons[i].setFont(font_text);
panel_buttons.add(buttons[i]);
if (i == 0)
panel_buttons.add(Box.createRigidArea(new Dimension(40, 0)));
buttons[i].addActionListener(new TextActionListener(label));
}
panel.add(Box.createRigidArea(new Dimension(0,20)));
panel.add(panel_buttons);
pane.add(panel, BorderLayout.CENTER);
return pane;
}
When text goes beyond the borders, scroll bars appear and I can move them and read the text. Looks like everything is ok, but when I either click any place outside the scroll pane or even just move the pointer, the scroll pane moves to the left and grows down. It doesn't change its width, but it shifts to the left because the area between it and the right panel's borders increases. Accordingly, size of the left panel shrinks. When I clear the text area and again either click or move the pointer, it is back to its normal size.
What is the reason its height grows and its left and right margins increase? What am I doing wrong?
UPDATE. I've found the problem. The thing is that I didn't create JTextArea correctly. I initialized it without parameters:
JTextArea text = new JTextArea("Some initial text");
Now I have rewritten:
JTextArea text = new JTextArea(5,10);
It is now shifted to the left by about 5 mm and do not changes its height. Still not perfect, but looks like I am on the right track.
Thank you everybody for your help!
BoxLayout accepting Min, Max and PreferredSize override those methods for JPanel
use JSPlitPane, there you can to hide Divider
2 steps to correct:
Set the size of the JTextArea: JTextArea text = new JTextArea(row, col);
Still shifts to the left by the size of the vertical bar:
either add ChangeListener to adjust the size of the JScrollPane
scroll.getViewport().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
if (scroll.getVerticalScrollBar().isVisible())
scroll.setPreferredSize(480, 200);
}
}
});
or add scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

Second row of gridbaglayout scrolling out of container

I am trying to achieve a layout similar to that of a carousel. It needs to have images added horizontally with a checkbox field in the second row. I have a panel within a jscrollpane and individual images are added to the panel as labels. Please see screen shot.
screenshot
When I scroll the pane , the first row containing the images stays well within the panel..but if you notice the second row of checkboxes , it scrolls out of the panel. Here is the code ...
JLabel lab1=new JLabel();
for (int ii=0; ii<imageFiles.length; ii++) {
GridBagConstraints constraint = new GridBagConstraints();
lab1 = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
constraint.gridx = ii;
constraint.gridy =0;
jPanel9.add(lab1,constraint);
}
for (int ii=0; ii<imageFiles.length; ii++) {
GridBagConstraints constraint1 = new GridBagConstraints();
constraint1.anchor = GridBagConstraints.SOUTH;
chkbox = new Checkbox("asdasdada");
constraint1.gridx = ii;
constraint1.gridy =1;
jPanel9.add(chkbox, constraint1);
}
Not sure what is wrong..Any help is much appreciated..Thanks..
The problem is that you are mixing AWT components (heavyweight) with Swing components (lightweight). I have 2 recommendations:
Don't mix heavyweight and lightweight components
Try to use lightweight components as much as possible
So in your code, replace Checkbox by JCheckbox and it should work just fine.

How to get values of dynamically generated components?

I am dynamically generating a list of name boxes, sliders and labels, and am trying to figure out how to access the values of the sliders and change the labels. Other posts suggest using an array, but I have no idea where to begin with that.
My code is as such:
public Tailoring(int n) {
/*initComponents();*/
JPanel containerPanel = new JPanel();
containerPanel.setLayout(new BoxLayout(containerPanel, BoxLayout.PAGE_AXIS));
this.add(containerPanel);
JLabel Title = new JLabel("Tailoring:");
containerPanel.add(Title);
for(int i = 0; i < n; i++){
JPanel rowPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
JTextField NameBox = new JTextField("Guest " + (i+1));
JSlider TipSlider = new JSlider();
JLabel TipCost = new JLabel();
rowPanel.add(NameBox);
rowPanel.add(TipSlider);
rowPanel.add(TipCost);
containerPanel.add(rowPanel);
}
}
You can create a new class YourPanel which extends JPanel.
Instead of the statement
JPanel rowPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
you can use
YourPanel rowPanel = new YourPanel(new FlowLayout(FlowLayout.LEFT));
Define textfield, slider and label as the properties of this YourPanel class.
Provide getters/setters for each field. Then use an array or ArrayList of YourPanel objects in your application. You will be able to reach the nth panel's label with a call like:
panels.get(n).getJLabel();
It appears that you'd like to change the value displayed in the JLabel when the associated JSlider is modified, right? The best way to associate pairs of objects in Java is with a Map structure:
Map<Component, JSlider> sliderToLabel = new HashMap<Component, JSlider>();
for (int i = 0; i < n; i++) {
// after your loop code
sliderToLabel.put(TipSlider, TipCost); // map the slider to its label
}
You will be able to get a reference to the JSlider in the code that listens for changes on that component.
JLabel updateLabel = sliderToLabel.get(targetedSlider);
updateLabel.setText("updated text");
Notes
As a matter of convention, variable names should begin with lower case letters
The event listener I alluded to should also be attached in the loop. See Writing Event ListenersOracle

Categories