Whenever I add my jbutton to my container it's really huge. I thought using the label.setBounds() function would work but it didn't
public Liability_Calculator(String s)
{
super(s);
setSize(325,200);
Color customColor = Color.WHITE;
c = getContentPane();
c.setLayout(new BorderLayout());
//the button
ok = new JButton("OK");
//ok.setSize(50, 50);
//HERE IS WHERE I TRY AND RESIZE!
ok.setBounds(30,30,50,50);
c.add(ok, BorderLayout.SOUTH);
setVisible(true);
}
Suggestions:
You will want to read up on the layout managers to
understand why your GUI is behaving this way
and to see how to use the layout managers to your advantage to create better looking GUI's in an easy way.
You'll also want to avoid setting bounds on any gui components.
For instance, a JPanel uses FlowLayout(FlowLayout.CENTER)) by default, and you can use that to your advantage by placing your ok JButton into a JPanel and then the JPanel into the contentPane:
ok = new JButton("OK");
// ok.setBounds(30, 30, 50, 50);
JPanel southPanel = new JPanel();
southPanel.add(ok);
c.add(southPanel, BorderLayout.SOUTH);
This will change the first image to the second:
Related
I'm using the NetBeans GUI builder to handle my layout (I'm terrible with LayoutManagers) and am trying to place a simple JLabel so that it is always centered (horizontally) inside its parent JPanel. Ideally, this would maintain true even if the JPanel was resized, but if that's a crazy amount of coding than it is sufficient to just be centered when the JPanel is first created.
I'm bad enough trying to handle layouts myself, but since the NetBeans GUI Builder autogenerates immutable code, it's been impossible for me to figure out how to do this centering, and I haven't been able to find anything online to help me.
Thanks to anybody who can steer me in the right direction!
Here are four ways to center a component:
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
class CenterComponent {
public static JLabel getLabel(String text) {
return getLabel(text, SwingConstants.LEFT);
}
public static JLabel getLabel(String text, int alignment) {
JLabel l = new JLabel(text, alignment);
l.setBorder(new LineBorder(Color.RED, 2));
return l;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JPanel p = new JPanel(new GridLayout(2,2,4,4));
p.setBackground(Color.black);
p.setBorder(new EmptyBorder(4,4,4,4));
JPanel border = new JPanel(new BorderLayout());
border.add(getLabel(
"Border", SwingConstants.CENTER), BorderLayout.CENTER);
p.add(border);
JPanel gridbag = new JPanel(new GridBagLayout());
gridbag.add(getLabel("GridBag"));
p.add(gridbag);
JPanel grid = new JPanel(new GridLayout());
grid.add(getLabel("Grid", SwingConstants.CENTER));
p.add(grid);
// from #0verbose
JPanel box = new JPanel();
box.setLayout(new BoxLayout(box, BoxLayout.X_AXIS ));
box.add(Box.createHorizontalGlue());
box.add(getLabel("Box"));
box.add(Box.createHorizontalGlue());
p.add(box);
JFrame f = new JFrame("Streeeetch me..");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(p);
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
}
});
}
}
By using Borderlayout, you can put any of JComponents to the CENTER area. For an example, see an answer to Stack Overflow question Get rid of the gap between JPanels. This should work.
Even with BoxLayout you can achieve that:
JPanel listPane = new JPanel();
listPane.setLayout(new BoxLayout(listPane, BoxLayout.X_AXIS ));
JLabel label = new JLabel();
listPane.add(Box.createHorizontalGlue());
listPane.add(label);
listPane.add(Box.createHorizontalGlue());
mKorbel's solution is perfect for your goal. Anyway I always like to suggest BoxLayout because it's very flexible.
Mara: "thanks for your response, however the NetBeans GUI Build uses GroupLayout and this is not overridable."
Not true! Right click anywhere inside JFrame (or any other GUI container) in NetBeans GUI builder and select "Set Layout". By default is selected "Free Design", which is Group layout, but you can select any other layout including Border layout as advised by mKorbel.
There's many ways to do this, depending on the layout manager(s) you use. I suggest you read the Laying Out Components Within a Container tutorial.
I believe the following will work, regardless of layout manager:
JLabel.setHorizontalAlignment(SwingConstants.CENTER)
Okay so before you ask, yes I'm not using any Layout Manager. No, that doesn't make this bad design (as I've seen people in here saying because someone simply didn't use one). The thing is i want the label to always (and I mean always) show over the two buttons (over the gap left by them which makes it impossible to put it as an Icon or a text on the JButton).
JFrame frame = new JFrame("ColorTap");
private void init() {
JButton jb1 = new JButton(""), jb2 = new JButton("-");
JLabel label = new JLabel("TEXT HERE");
label.setForeground(Color.white);
label.setFont(new Font("Arial Bold",Font.ITALIC,30));
label.setBounds(60,249,200,100);
frame.setLayout(null);
jb1.setBounds(0, 0, 300,298);
jb2.setBounds(0, 302, 300, 300);
jb1.setBackground(Color.black);
jb2.setBackground(Color.black);
jb1.setBorderPainted(false);
jb2.setBorderPainted(false);
frame.add(label);
frame.add(jb1);
frame.add(jb2);
frame.setResizable(false);
frame.setSize(300, 628);
frame.setLocation(550, 50);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
After this what's stranger to me is that the button on the bottom stays under the label and not the one on the top... HELP! Thanks
Swing is optimized to paint components in two dimensions. That is it assumes components will never overlap. Overlapping JButtons cause a problem because of the rollover effects which only cause the buttons to be painted, not the label, so the button is painted over the top of the label.
So you need to tell Swing that components do overlap so Swing can make sure components are painted in the proper ZOrder:
JPanel panel = new JPanel()
{
#Override
public boolean isOptimizedDrawingEnabled()
{
return false;
}
};
Now you can set the layout manager of the panel and add your components to the panel and they will be painted properly.
See: How to put a JButton with an image on top of another JButton with an image? for a working example that DOES use layout managers.
Here is my code. The button is the same size as the FlowLayout. How can I make the button smaller?
public class javalearning extends JFrame{{
FlowLayout f = new FlowLayout();
this.setSize(600,600);
JFrame j = new JFrame();
this.setTitle("this is a tittle");
JButton button = new JButton();
button.setText("Button");
this.add(button);
button.setBounds(10, 10, 10, 10);
this.setVisible(true);
}
}
I think you forget to setLayout, it works fine when I do. Don't use setBounds and put it in a javalearning constructor and I also suggest you setDefaultCloseOperation like
public javalearning() {
FlowLayout f = new FlowLayout();
this.setLayout(f);
this.setSize(600, 600);
this.setTitle("this is a tittle");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton();
button.setText("Button");
this.add(button);
// button.setBounds(10, 10, 10, 10);
this.setVisible(true);
}
public static void main(String[] args) {
javalearning m = new javalearning();
}
Finally, by convention, Java class names start with a capital letter and are camel case. Something like JavaLearning would follow that convention.
You never set the layout manager (FlowLayout) to the frame, therefore the JFrame is still using it's default layout manager of BorderLayout...
Try using something more like...
FlowLayout f = new FlowLayout();
setLayout(f);
this.setTitle("this is a tittle");
JButton button = new JButton();
button.setText("Button");
this.add(button);
this.pack();
this.setVisible(true);
instead...
Take a closer look at Laying Out Components Within a Container for more details
FlowLayout will lay out Components left-to-right (or right-to-left) wrapping them if required. If you wish to explicitly set the size of each JButton you should use setPreferredSize rather than setSize or setBounds as layout managers typically make use of the minimum, preferred and maximum sizes when performing a layout.
button.setBounds(x, y, height, width);
you can give height and width less than 10!
also you can use GridLayout for smaller buttons in one button with for loop
I have a JPanel with a vertical BoxLayout, for one element i want to be able to use another BoxLayout which places elements horisontally.
The code will explain what i'm trying to do:
private void prepareGUI() {
setBorder(new EmptyBorder(20, 0, 20, 0));
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JLabel lblTitle = new JLabel("Downloading");
lblTitle.setFont(new Font("Arial", Font.PLAIN, 20));
lblTitle.setAlignmentX(Component.CENTER_ALIGNMENT);
add(lblTitle);
Component verticalStrut = Box.createVerticalStrut(20);
add(verticalStrut);
JProgressBar progressBar = new JProgressBar();
progressBar.setStringPainted(true);
progressBar.setBorder(null);
progressBar.setValue(50);
Dimension size = new Dimension(300, 25);
progressBar.setMinimumSize(size);
progressBar.setMaximumSize(size);
progressBar.setPreferredSize(size);
add(progressBar);
BoxLayout textLayout = new BoxLayout(this, BoxLayout.Y_AXIS);
JLabel lblTest_1 = new JLabel("Test 1!");
textLayout.add(lblTest_1);
JLabel lblTest_2 = new JLabel("Test 2!");
textLayout.add(lblTest_2);
add(textLayout);
}
Now obviously this isn't possible as BoxLayout isn't a Container (It even asks for the container to be linked to on construction.
My question is what is the best way to achieve what i want? Should i create another JPanel and put that inside the first JPanel? I was thinking that but it seems a little too complicated, there must be a simpler way?
BoxLayout is not a container, it's a LayoutManager, so, components can't be added to BoxLayout since box layout is not inheriting anything from abstract class Component, it's will add to some container like JPanel or frame's container....
So, it's wrong to say:
textLayout.add(lblTest_1);
Or even
add(textLayout);
Because this method addes a component to the frame's container, and BoxLayout is not a component.
Should i create another JPanel and put that inside the first JPanel?
Except what you did and avoiding null layout, you're free to do anything, as, design is upon to you, as far as I am preferring multiple panels if wanted.
I'm having some troubles with Java Swing.
I'm trying to make a frame with a control panel at the top with some buttons in it.
and below that i want a JTable to show
I've been trying but the table is not showing.
If I remove the controlPanel at the top, it sometimes shows and sometimes not.
The code that I use inside my constructor of my JTable is provided in the same application,
so it's no network error
public ServerMainFrame(GuiController gc){
this.gc = gc;
initGUI();
}
private void initGUI() {
System.out.println("initiating GUI");
createFrame();
addContentPanel();
addControls();
//openPopUpServerSettings();
addSongTable();
}
private void createFrame()
{
this.setTitle("AudioBuddy 0.1");
this.setVisible(true);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setSize(800, 600);
this.setResizable(false);
this.setLocationRelativeTo(null);
}
private void addContentPanel()
{
JPanel p = new JPanel();
p.setLayout(new FlowLayout());
p.setSize(new Dimension(800, 600));
this.setContentPane(p);
}
private void addControls()
{
JPanel controlPanel = new JPanel();
controlPanel.setLayout(new FlowLayout());
controlPanel.setBorder(BorderFactory.createLineBorder(Color.black));
controlPanel.setSize(700,100);
// Buttons
JButton play = new JButton("Play");
JButton pause = new JButton("Pause");
JButton stop = new JButton ("Stop");
JButton next = new JButton("Next");
JButton prev = new JButton("Previous");
controlPanel.add(play);
controlPanel.add(pause);
controlPanel.add(stop);
controlPanel.add(next);
controlPanel.add(prev);
// Currently playing
JLabel playing = new JLabel("Currently playing:");
controlPanel.add(playing);
JLabel current = new JLabel("Johnny Cash - Mean as Hell");
controlPanel.add(current);
this.getContentPane().add(controlPanel);
}
private void addSongTable()
{
JTable songTable = new JTable(Server.getSongTableModel());
songTable.setVisible(true);
JPanel tablePanel = new JPanel();
tablePanel.setVisible(true);
tablePanel.add(songTable);
songTable.repaint();
this.getContentPane().add(tablePanel);
JButton btnMulticastList = new JButton("send list to clients");
btnMulticastList.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
Server.MulticastPlaylist();
}
});
getContentPane().add(btnMulticastList);
}
if I remove the controlPanel at the top, it sometimes shows and
sometimes not.
everything is hidden in Server.getSongTableModel(), nobody knows without posting an SSCCE with hardcoded value returns from
GUI has issue with Concurency in Swing
XxxModel loading data continiously with building GUi, then exception caused described problems
The code that I use inside my constructor of my JTable is provided in
the same application, so it's no network error
no idea what you talking about
have to create an empty GUI, see InitialTread
showing GUI, then to start loading data to JTable
then starting Workers Thread (Backgroung Task) from SwingWorker or (descr. Network issue) better Runnable#Thread (confortable for catching an exceptions and processing separate threads)
output from Runnable to the Swing GUI must be wrapped into invokeLater()
If you want controls at the top of your window, and the table filling the majority of the window, then I'd suggest you try using BorderLayout instead of FlowLayout. Create it like this...
private void addContentPanel()
{
JPanel p = new JPanel();
p.setLayout(new BorderLayout());
p.setSize(new Dimension(800, 600));
this.setContentPane(p);
}
And add the components by specifying the location in the BorderLayout. In this case, the controls should be added to the top in their minimal size...
this.getContentPane().add(controlPanel,BorderLayout.NORTH);
And the table should be in the center, filling the remaining window space...
this.getContentPane().add(tablePanel,BorderLayout.CENTER);
In your case, you also have a button at the bottom...
getContentPane().add(btnMulticastList,BorderLayout.SOUTH);
For the layout you're after, BorderLayout is much more appropriate. The benefit of using BorderLayout here is that the components should be automatically resized to the size of the window, and you're explicitly stating where each component resides, so panels shouldn't not appear.
It would also be my recommendation that you find an alternative to calling getContentPane() in all your methods. Maybe consider keeping a global variable for the main panel, like this...
private mainPanel;
private void addContentPanel()
{
mainPanel = new JPanel(new BorderLayout());
mainPanel.setSize(new Dimension(800, 600));
this.setContentPane(mainPanel);
}
Then you can reference the panel directly when you want to add() components to it.
Finally, I'd also suggest using GridLayout for your controls, as it will allow you to place all your buttons in it, and they'll be the same size for consistency. Define it like this to allow 5 buttons in a horizontal alignment...
JPanel controlPanel = new JPanel(new GridLayout(5,1));
then you just add the buttons normally using controlPanel.add(button) and they'll be added to the next slot in the grid.
For more information, read about GridLayout or BorderLayout, or just see the Java Tutorial for a Visual Guide to Layout Managers to see what alternatives you have and the best one for your situation. In general, I try to avoid FlowLayout, as I find that there are other LayoutManagers that are more suitable in the majority of instances.