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));
Related
This simple Java swing BoxLayout UI apparently results in certain pixels not being drawn (resulting in artifacts/garbage) when my display scaling is set to 125% (Windows 10):
import javax.swing.*;
public class Test {
public static void main(String[] args) {
JPanel container = new JPanel();
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
for(int i = 1; i <= 3; i++) panel.add(new JButton("Button " + i));
JFrame frame = new JFrame();
container.add(panel);
frame.add(container);
frame.pack();
frame.setVisible(true);
}
}
Result:
There is a one pixel gap between Button 2 and Button 3. I'm not greatly concerned with the gap itself, but the pixels in this gap (within the width of the buttons) are filled with garbage. In the screenshot, this appears to be a misaligned piece of a button, but in general this can change whenever this area is repainted (such as after hovering Button 2), often coming from a recently-repainted component (often more obvious in a more complex application). Presumably this is just uninitialized data due to some kind of dimension mismatch triggered by display scaling and particular position values.
Last tested with openjdk-14.0.2. (Presumably this can only happen since JEP 263 added "HiDPI Graphics" support in Java 9.)
Am I doing something wrong? Is there a way to avoid this problem or work around it? Is this a problem in BoxLayout or is it a more fundamental problem? Basically, what's going on?
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).
Basically all I want to do is draw two rows of buttons for a lights out game (homework), but I don't know how to make both panels show up. I've pretty much almost no graphics before, and I don't really understand anything I'm doing.
The panels them selves work, but it just shows whichever I add second (I assume it's overwriting the previous panel)
public static void main(String[] args) {
String nButtonsString = JOptionPane.showInputDialog("How many buttons would you like?");
int nButtons = Integer.parseInt(nButtonsString);
JFrame myFrame = new JFrame();
myFrame.setTitle("Linear Lights Out Game.");
myFrame.setSize(FRAME_SIZE);
JPanel control_buttons = new Linear_Controls();
myFrame.add(control_buttons);
JPanel lights = new LinearLightsPanel(nButtons);
myFrame.add(lights);
myFrame.pack();
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setVisible(true);
myFrame.add(control_buttons);
myFrame.add(lights);
By default a JFrame uses a BorderLayout. Also, by default components get added to the CENTER of the BorderLayout. However the CENTER can only contain a single component so only the last component added is displayed. Try:
myFrame.add(control_buttons, BorderLayout.NORTH);
Now the two components should show up.
Read the section from the Swing tutorial on Using Layout Managers for more information and examples. Also take a look at the Trail/Table of Contents link to see other useful topics for basic Swing usage.
You have to create the 2 panels A and B and add them to another panel C. Then you add C to your frame.
A bit better explained: This is what you have now:
JPanel lights = new LinearLightsPanel(nButtons);
myFrame.add(lights);
But you would like something like:
JPanel lightsA = new LinearLightsPanel(nButtonsA);
JPanel lightsB = new LinearLightsPanel(nButtonsB);
JPanel lightsC = new JPanel();
lightsC.add(lightsA);
lightsC.add(lightsB);
myFrame.add(lightsC);
I was tired but before quitting just stuck in the nearly-last 3 lines in the code snippet below to make a "refresh" button on my tictactoe panel, hoping to get away with it but expecting errors, since it mixes layout managers on a single container.
But it WORKED.
ButtonPanel.setLayout(new GridLayout(3, 3));
guiFrame.add(ButtonPanel);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
button[i][j] = addButton(ButtonPanel, i, j);
}
}
JButton refreshbutton = new JButton("Refresh");
guiFrame.add(refreshbutton, BorderLayout.SOUTH); // ... border layout worked. Hm.
refreshbutton.addActionListener(this);
guiFrame.setVisible(true); }
Should I be surprised? (Keep in mind my newbieness.)
(BOY, did I learn/stumble onto a buncha stuff in writing this silly game's program!!!--for instance, using setActionCommand to "label" each button internally [as 11,12,13,21,...33] so the ONE actionPerformed method could use getActionCommand to correctly label [with X or O] whatever button was pushed by whoever's turn it was.)
guiFrame.add(refreshbutton, BorderLayout.SOUTH); // ... border layout worked. Hm.
Just because you used BorderLayout.SOUTH does not make a panel a BorderLayout. Your code worked because the default layout manager for the content pane of a JFrame (JDialog) is a BorderLayout. So you are just taking advantage of the default layout.
since it mixes layout managers on a single container.
Yes, this is a common practice. In fact it is almost impossible to create a reasonably complex GUI if you don't use different layout managers on different panels that you add to a GUI.
Made it work! Thank you guys! The code follows. I used BoxLayout since I thought it'd be ideal for stacking questions one on top of the other, but now I got issues with the layout... When I stack several questions the question panels start overlapping. Any thoughts?
panels1 = new MultipleChoice[5];
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
for(int i=0; i<4; i++){
panels1[i]= new MultipleChoice();
panels1[i].setAlignmentX(CENTER_ALIGNMENT);
add(panels1[i]);
}
setVisible(true);
I'm working on designing an Online Test applet. A test has multiple choice and true/false questions. To set up a test I created two JPanel classes, one for the multiple choice question and one for the true/false questions. So when a test is created I'll just dynamically add these panels to a JPanel container according to the non-fixed number of questions.
First, how can I dynamically add new panels to a panel? I thought about declaring an array of the JPanel type. I created and then add objects of this panel class using a for loop:
MultitipleChoicePanel[] PanelArray;
for (...){
PanelArray[i] = new MultipleChoicePanel();
containerpanel.add(PanelArray[i]);
}
I don't know if this is technically possible. This is my first time using Swing, and I tried doing this but obviously it didn't work. Does anyone have an idea how correctly dynamically add these panels?
Second, which of the layout managers is best suited for the container panel in order to fit every new panel added right under the previous one? I thought about dynamically setting up a GridLayout of one column and add rows as I add panels. But I've been really struggling modifying swings dynamically.
Any suggestions?
Thank you so much for your help!
JPanel default layout is FlowLayout and add each component by default to the right so it would fit your problem.
You also may interested in swingx they have HorizontalLayout.
Example:
//in some place
JPanel myBigPanel = new JPanel();
myBigPanel.setLayout(new HorizontalLayout()); // swingx api
List<MultitipleChoicePanel> panelList = new ArrayList<>();
// panelList.add(new MultipleChoicePanel()).. .n times
for(MultipleChoicePanel mp : panelList){
myBigPanel.add(mp);
}
myBigPanel.revalidate(); // revalidate should call repaint but who knows
myBigPanel.repaint();
How to use various Layout Managers
how correctly dynamically add these panels?
After adding components to a visible GUI you need to do:
panel.add(...);
panel.revalidate();
panel.repaint();
"and then add objects of this panel class using a for loop:.....I dont know if its technically possible"
As far as an array of panels, I would do it with an arraylist and do it similarly to how you did it.
import java.util.ArrayList;
ArrayList<MultipleChoicePanel> array = new ArrayList<MultipleChoicePanel>();
for(...){
array.add(new MultipleChoicePanel());
containerPanel.add(array.get(i));
}
import java.awt.*;
import javax.swing.*;
public class JavaSwing extends JApplet {
public void init(){
Container content = getContentPane();
JScrollPane pane= new JScrollPane();
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));
panel.add(addPanel("title121"));
panel.add(addPanel("title112"));
panel.add(addPanel("title12"));
panel.add(addPanel("title11"));
pane.getViewport().add(panel);
content.add(pane);
}
public static JPanel addPanel(String title){
JPanel panel = new JPanel();
panel.add(new JButton(title));
return panel;
}
}