I try to program a GUI like this. When a button clicked every time a new button is created and placed at specific position but after adding some buttons in jscrollpane, scrollbar not activated, so I unable to see all created buttons.
My code is here:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Test{
private JFrame frame;
private JPanel panel1,panel2;
private JScrollPane pane;
private JButton button;
int i = 1, y = 10;
public Test()
{
panel2 = new JPanel(null);
panel2.setBounds(0,0,280,300);
button = new JButton("Add Button");
button.setBounds(90,10,120,30);
pane = new JScrollPane();
pane.setBounds(10,50,280,300);
panel1 = new JPanel(null);
panel1.setPreferredSize(new Dimension(300,400));
panel1.setBackground(Color.WHITE);
frame = new JFrame("Test");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel1);
frame.pack();
panel1.add(pane);
panel1.add(button);
pane.add(panel2);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
panel2.add(new JButton("Button "+i)).setBounds(80,y,120,30);
i += 1;
y += 35;
}
});
}
public static void main(String[] args) {
new Test();
}
}
Don't use a null layout. Don't use setBounds().
The scrollbars will only appear automatically when the preferred size of the panel is greater that the size of the scroll pane.
It is the job of the layout manager to:
set the location of a component
set the size of a component
calculate the preferred size of the panel.
So the solution is to use the appropriate layout manager on your panel.
So for example you can use a BoxLayout:
//panel2 = new JPanel(null);
panel2 = new JPanel();
panel2.setLayout( new BoxLayout(panel2, BoxLayout.Y_AXIS) );
And then when you add components to a visible frame you need to revalidate() the panel to invoke the layout manager:
//panel2.add(new JButton("Button "+i)).setBounds(80,y,120,30);
panel2.add(new JButton("Button "+i));
panel2.revalidate();
There is no need for panel1. Just add the components to the frame:
//panel1.add(pane);
//panel1.add(button);
frame.add(button, BorderLayout.PAGE_START);
frame.add(pane, BorderLayout.CENTER);
But there are other issues:
pane = new JScrollPane();
You actually need to add the panel to the scroll pane. So the code should be:
pane = new JScrollPane(panel2);
Since a component can only have a single parent, you need to remove:
pane.add(panel2);
Since the panel2 has been added to the scroll pane.
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel1);
frame.pack();
The above logic is wrong.
You should only invoked pack() and setVisible( true ) AFTER all the component have been added to the frame.
So most of the code posted is wrong.
Start by reading the section from the Swing turtorial on Layout Managers. Download the working demo code and learn how to better structure your code. The modify the code for your specific example.
Related
I have a main class:
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame("Hex");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent inputs = new InputPanel();
JComponent hexGrid = new HexGridPanel(10,10,30);
JComponent outputs = new OutputPanel();
JComponent toolbar = new ToolbarPanel(); // This one is having problems
Container pane = frame.getContentPane();
pane.add(inputs, BorderLayout.LINE_START);
pane.add(hexGrid, BorderLayout.CENTER);
pane.add(outputs, BorderLayout.LINE_END);
pane.add(toolbar, BorderLayout.PAGE_END); // This one is having problems
frame.pack();
frame.setVisible(true);
}
}
And all of my other panels work except for ToolbarPanel that for some reason does not show its content:
public ToolbarPanel(){
JPanel content = new JPanel();
content.setLayout(new BoxLayout(content, BoxLayout.X_AXIS));
ButtonGroup buttonGroup = new ButtonGroup();
JRadioButton button = new JRadioButton("Test");
buttonGroup.add(button );
content.add(button );
JScrollPane scroll = new JScrollPane(content);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
content.setBorder(new LineBorder(Color.RED));
scroll.setBorder(new LineBorder(Color.GREEN));
this.add(scroll);
this.setPreferredSize(new Dimension(900, 200));
this.setBorder(new LineBorder(Color.BLACK)); // Only this is showing up in the UI
}
The ToolbarPanel itself shows up, but not the scroll pane or the radio buttons. It should show up inside of the black rectangle at the bottom of this image:
Well, you didn't include a MRE and I don't see the declaration of your class but I'm guessing you are using:
public class ToolbarPanel extends JComponent
The problem is that by default a JComponent doesn't have a layout manager so you won't see your components.
If you use:
public class ToolbarPanel extends JPanel
It will be a little better, but all the components will be displayed in a small square.
So you will also want to add
setLayout( new BorderLayout() );
to your constructor.
Note:
This is why a minimal reproducible example should be included with every question. We should not have to spend time guessing what you may or may not be doing.
As you see the code, I would like to implement the 2nd tab with a text area, scrolling, and a button down there. This (JScrollPane scr = new JScrollPane(secondTab(panel2));) code was in the function, private static JTextArea secondTab(JPanel panel) before but I took it out of the function and put that back to MainFrame. Because the scroll and text area didn't show up. Now that I moved the code to mainframe the tex tarea and scroll are visible, but I'm struggling with making the button showing up in the 2nd tab. Do you guys have any idea?
public MainFrame(String username)
{
JTabbedPane tab = new JTabbedPane();
mainFrame.add(tab, BorderLayout.CENTER);
JPanel panel1 = new JPanel();
firstTab(panel1);
tab.add("babababa", panel1);
JPanel panel2 = new JPanel();
JScrollPane scr = new JScrollPane(secondTab(panel2));
JButton saveButton = new JButton("Save");
panel2.add(saveButton);
saveButton.setBounds(190, 280, 80, 40);
tab.add("hahaha", panel2.add(scr));
mainFrame.setBounds(200,200,500,400);
mainFrame.setVisible(true);
}
private static JTextArea secondTab(JPanel panel) {
panel.setLayout(null);
final JTextArea nameTextArea=new JTextArea();
nameTextArea.setBounds(10,10,440,270);
nameTextArea.setLineWrap(true);
return nameTextArea;
}
}
You should avoid use of null layout as this makes for very inflexible GUI's that while they might look good on one platform look terrible on most other platforms or screen resolutions and that are very difficult to update and maintain. Not only that, JScrollPanes do not work well when the viewport view (the component that you display inside of the JScrollPane) uses null layout. Not only that, if you set the bounds or even the preferred size of a JTextArea, it will not expand inside the JScrollPane and you won't see scrollbars.
Solution:
Avoid using null layouts like the plague.
Learn and use the layout managers: The Swing Layout Manager Tutorials
Never set a JTextArea's size or preferredSize. Instead consider setting its columns and rows.
For example:
import java.awt.BorderLayout;
import javax.swing.*;
public class MainFrame2 extends JPanel {
private JTabbedPane tabbedPane = new JTabbedPane();
private JTextArea textArea = new JTextArea(20, 40);
public MainFrame2() {
tabbedPane.add("Bahahahaha", new JPanel());
tabbedPane.add("TextArea Info", createTextAreaPane());
setLayout(new BorderLayout());
add(tabbedPane, BorderLayout.CENTER);
}
private JComponent createTextAreaPane() {
JPanel btnPanel = new JPanel();
btnPanel.add(new JButton("Save"));
JPanel textAreaPane = new JPanel(new BorderLayout());
textAreaPane.add(new JScrollPane(textArea), BorderLayout.CENTER);
textAreaPane.add(btnPanel, BorderLayout.SOUTH);
return textAreaPane;
}
private static void createAndShowGui() {
MainFrame2 mainPanel = new MainFrame2();
JFrame frame = new JFrame("Main Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_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();
}
});
}
}
It's better to build each tab panel in each method.
private JPanel buildFirstTab() {
// create new panel
// add components to the panel
// return the panel
}
private JPanel buildSecondTab() {
// create new panel
// create JScrollPane
// create JTextArea
// add text area to scrollpane by calling scrollpane.setViewPort method
// add scrollpane to the panel
// create button
// add button to the panel
// return the panel
}
public MainFrame(String username) {
JTabbedPane tab = new JTabbedPane();
mainFrame.add(tab, BorderLayout.CENTER);
tab.add("1st tab", buildFirstTab());
tab.add("2nd tab", buildSecondTab());
mainFrame.setBounds(200,200,500,400);
mainFrame.setVisible(true);
}
Adding to the previous answer, try to use the simple layout like BoxLayout (adds components on top of each other), or FlowLayout (adds components next to previous component), then learn more complex layout like GridBagLayout (so far, this is the best layout for me, most of the time).
Since im a beginner and i don't want to get involved with the layout managers, i was simply adding a JPanel into my main JFrame and giving spesific location to each component in the panel. But somehow the output appears way too wrong..
frame = new JFrame(email + " (Offline)");
frame.setSize(400, 400);
frame.setLocation(0, 0);
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.setLayout(new FlowLayout());
frame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
// out.println("BYE");
// out.flush();
frame.dispose();
thread.stop();
}
});
panel = new JPanel();
frame.add(panel);
chat = new JTextArea();
chat.setSize(400, 200);
chat.setLocation(0, 0);
chat.setEditable(false);
panel.add(chat);
panel.validate();
JLabel you = new JLabel("You:");
you.setSize(you.getPreferredSize());
you.setLocation(0, 210);
panel.add(you);
panel.validate();
input = new JTextArea();
input.setSize(200, 200);
input.setLocation(0, 220 + chat.getSize().height);
panel.add(input);
panel.validate();
send = new JButton("Send");
send.setSize(send.getPreferredSize());
send.setLocation(210, 220 + chat.getSize().height);
panel.add(send);
panel.validate();
frame.setVisible(true);
The outcome of this frame is that text areas are invisible, a You: label in the middle and next to the right of it the button.. What am i missing here?
Again, don't use null layout since it makes updating and maintaining your GUI much more difficult than it should be, and can lead to ugly GUI's if you plan on having them run on multiple platforms. Instead
Use several JPanels, each one holding a core group of components and each using its best layout manager
Nest these JPanels in other JPanels that use the best layout manager to display them
and that will allow your GUI to be resizeable without need of extra code.
Put your JTextAreas in JScrollPanes so that you can see all text even if it goes beyond the text area.
Never set the size of the JTextArea as that will not allow it to scroll. Instead set its columns and rows.
As a very simple example, run this to see what I mean:
import java.awt.*;
import javax.swing.*;
public class FooSwing2 {
public static void main(String[] args) {
JTextArea chatArea = new JTextArea(8, 40);
chatArea.setEditable(false);
chatArea.setFocusable(false);
JScrollPane chatScroll = new JScrollPane(chatArea);
JPanel chatPanel = new JPanel(new BorderLayout());
chatPanel.add(new JLabel("Chat:", SwingConstants.LEFT), BorderLayout.PAGE_START);
chatPanel.add(chatScroll);
JTextField inputField = new JTextField(40);
JButton sendBtn = new JButton("Send");
JPanel inputPanel = new JPanel();
inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.LINE_AXIS));
inputPanel.add(inputField);
inputPanel.add(sendBtn);
JPanel youLabelPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
youLabelPanel.add(new JLabel("You:"));
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS));
mainPanel.add(chatPanel);
mainPanel.add(Box.createVerticalStrut(10));
mainPanel.add(youLabelPanel);
mainPanel.add(inputPanel);
JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
This would result in a simple (non-functioning) GUI that looked like this:
Now say you want to change this and add another button, an "exit" JButton to the right of the send JButton. If you used null layout, you'd have to resize your GUI, you'd have to move the send button over to the left and make sure that your math was without error, etc. If you used layout managers, you'd need just two new lines of code (to change the display, not the functionality of course):
JTextField inputField = new JTextField(40);
JButton sendBtn = new JButton("Send");
JButton exitBtn = new JButton("Exit"); // ***** added
JPanel inputPanel = new JPanel();
inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.LINE_AXIS));
inputPanel.add(inputField);
inputPanel.add(sendBtn);
inputPanel.add(exitBtn); // ***** added
That's it, and this would display:
I have a code in java.
package interfaces;
import javax.swing.JPanel;
public class TabbedPaneDemo extends JPanel {
public TabbedPaneDemo() {
JTabbedPane pane = new JTabbedPane();
JPanel dashboardPanel = new JPanel();
dashboardPanel.add(new JLabel("Dashboard"));
// Add Dashboard Tab
pane.addTab("Dashboard", dashboardPanel);
JPanel transactionPanel = new JPanel();
transactionPanel.add(new JLabel("Transactions"));
// Add Transactions Tab
pane.addTab("Transactions", transactionPanel);
JPanel accountPanel = new JPanel();
accountPanel.add(new JLabel("Account"));
// Add Account Tab
pane.addTab("Account", accountPanel);
this.setLayout(new BorderLayout());
this.setPreferredSize(new Dimension(400, 200));
this.add(pane, BorderLayout.CENTER);
}
public static void main(String[] args) {
JPanel panel = new TabbedPaneDemo();
panel.setOpaque(true);
// panel.setBounds(12, 12, 45, 98);
JFrame frame = new JFrame("JTabbedPane Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
}}
and the output it's !
I want to change in this code to be like this.
I want to use an absolute layout (null).
I want to add menu, buttons and labels with these tabs ...
How can I do??
You should NOT use absolute layout. There is not reason to use absolute layout.
Instead you should use layout managers.
Maybe create a panel and add buttons to the panel. Then add the panel to the NORTH of the content pane. The tabbed pane would be added to the CENTER.
Read the Swing tutorial on Using Layout Managers.
I'd like to use a JScrollPane for a panel which has an arbitrary list of labels in it using box layout. I'm trying to get it so that the scrollbar would appear if there were too many items (labels) to display.
I tried adding a JScrollPane to the panel and then add the labels but then I don't see any scroll bar.
Any ideas?
TIA
For this kind of thing, you'd normally use a JList or JTable (if you need custom rendering).
Make sure that you call validate() or revalidate() on the JScrollPane after adding an item, to force the preferred size of the panel to be recalculated.
Here's how I did it.
JPanel midPanel = new JPanel();
midPanel.setLayout(new BoxLayout(midPanel, BoxLayout.Y_AXIS));
midPanel.add(new JLabel("<html><u>Label</u>"));
Box box = Box.createVerticalBox();
for (Item item : data.getInventory()) {
inventory.add(box.add(new JLabel(item.getName())));
}
JScrollPane jscrlpBox = new JScrollPane(box);
midPanel.add(jscrlpBox);
add(midPanel, BorderLayout.CENTER);
From:
http://www.java2s.com/Code/Java/Swing-JFC/JScrollPanetoholdscrollablecomponent.htm
Did you remember to set the preferred size of the content panel?
final JFrame frame = new JFrame("Scroll Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
final Box textArea = Box.createVerticalBox();
final JScrollPane textAreaScroll = new JScrollPane(textArea);
textAreaScroll.setPreferredSize(new Dimension(80,150)); /* essential! */
JButton addButton = new JButton("ADD");
addButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
textArea.add(new JLabel("abc"));
textArea.revalidate();
}
});
frame.getContentPane().add(textAreaScroll, BorderLayout.SOUTH);
frame.getContentPane().add(Box.createRigidArea(new Dimension(10,10)), BorderLayout.CENTER);
frame.getContentPane().add(addButton, BorderLayout.NORTH);
frame.pack();
frame.setVisible(true);
In this example, the scroll bar works correctly, but if you remove the line marked as "essential", it will not work anymore.