I have been searching for a while now, but couldnt find a solution so I have decided to ask here.
I am using Java Swing for my gui implementation of calculator. I have custom made layout(which works correctly 100%). I have added all buttons and all buttons are positioned correctly, always. Last component I have inserted is "Inv" and it is checkbox which I cant find a way to center it inside its area. I have tried putting it in panel,in panel with borderlayout.center, setting the horizontal and vertical text alignment, but nothing works.
invert = new JCheckBox("Inv");
invert.setBackground(Color.decode("#8DA336"));
invert.addActionListener(new CommandListener(this,"invert"));
container.add(invert, new RCPosition(5, 7));
This RCPosition is nothing more than object which says in which row and column this component is (nothing wrong with that).
Checkbox is by default left-aligned. Try make it center-aligned:
invert = new JCheckBox("Inv");
invert.setHorizontalAlignment(SwingConstants.CENTER);
// styling and add to container
If it don't help, then you should publish your layout manager.
You could try putting it in a JPanel with BoxLayout, then add horizontal glue on the left and right.
final JFrame frame = new JFrame();
final JPanel jp = new JPanel();
jp.setLayout(new BoxLayout(jp, BoxLayout.X_AXIS));
jp.add(Box.createHorizontalGlue());
final JCheckBox jcb = new JCheckBox("inv");
jp.add(jcb);
jp.add(Box.createHorizontalGlue());
frame.getContentPane().add(jp);
frame.pack();
frame.setLocationRelativeTo(null);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
frame.setVisible(true);
}
});
This is just one way to do it, setHorizontalAlignment should work as well.
Related
I am learning swing from past week, I have some issue with GridBagConstraints to put one button in top left corner but all other buttons in default in GridBagConstraints ?
I am using code that like not original but states the problem
import java.awt.*;
import javax.swing.*;
#SuppressWarnings("serial")
class MyPanel extends JPanel
{
JButton menu = new JButton("Menu"), button = new JButton("Puzzle");
GridBagConstraints gbc1 = new GridBagConstraints(), gbc2 = new GridBagConstraints();
private void setup()
{
gbc1.anchor = GridBagConstraints.FIRST_LINE_START;
gbc2.anchor = GridBagConstraints.CENTER;
gbc2.weightx = 1.0;
gbc2.weighty = 1.0;
}
public MyPanel()
{
this.setLayout(new GridBagLayout());
this.setup();
this.button.setPreferredSize(new Dimension(250, 140));
this.add(menu, gbc1);
this.add(button, gbc2);
}
}
#SuppressWarnings("serial")
public class Test extends JFrame
{
public Test()
{
this.setTitle("Test");
this.setContentPane(new MyPanel());
this.setResizable(false);
this.setSize(800, 600);
this.setVisible(true);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(() -> new Test());
}
}
output
I want menu is top corner.
I read from here but i did not understand this Could you please explain GridBagConstraints for how to do that.
I Hope that problem is clear to understand, if not please let me know in comments.
EDIT:
#camickr suggestion works but a little problem, the Puzzle Button is not in extract center.
Thanks.
By default the GridBagLayout will display all the components centered horizontally and vertically, unless one of the components has a weightx/weighty value not equal to 0. Then that component will fill the extra space in the frame.
So if you want one component at the "top/left" and one in the "center", you need to:
use the "anchor" constraint. It will be different for both components.
the component in the center will need to use the "weightx/weighty" constraints.
However, an easer solution might be to use a combination of panels with different layout managers.
For example:
JPanel menuPanel = new JPanel( new FlowLayout(FlowLayout.LEFT) );
menuPanel.add(menuButton);
JPanel centerPanel = new JPanel( new GridBagLayout() );
centerPanel.add(puzzle, new GridBagConstraints());
frame.add(menuPanel, BorderLayout.PAGE_START);
frame.add(centerPanel, BorderLayout.CENTER);
So now the "top" of the frame will contain a panel with components displayed from the left and the "center" of the frame will contain your puzzle centered in the remaining space of the frame.
Edit:
I solved it but put gridx and gridy to 0 in center component, but i did not completely understand the setttings
Well I mentioned that you would need to use the gridx/gridy constraints. You should always use those constraints as it is very obvious what grid you want to add the component to. The examples from the tutorial always specify those values.
Using gridx/gridy both equal to 0, does not really make sense. The effect is that you have two components trying to share the same grid.
Remove the setResizable(false) statement and shrink the size of the frame to see how the button repositions itself.
It is not normal that two components share the same grid. Normally you would have the menu on the first row and the button on the second row. This will center the button horizontally in the frame and vertically in the space below the menu.
What you are doi
I am almost certain this question was asked before here: Java Swing: How to change GUI dynamically , but I seem to just have some fundamental misunderstanding in how it works.
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
public class JTest extends JFrame
{
public static void main(String[] args)
{
JTest t = new JTest();
}
Container pane;
public JTest()
{
setSize(500,500);
setTitle("JTest");
setDefaultCloseOperation(EXIT_ON_CLOSE);
pane = getContentPane();
pane.setLayout(new GridLayout(1,2));
JButton old = new JButton("old");
old.addActionListener(new OldButton());
pane.add(old);
JScrollPane scroll = new JScrollPane(new JTextArea(50,20));
pane.add(scroll);
setVisible(true);
}
private class OldButton implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
pane.setLayout(new GridLayout(1,2));
JButton old = new JButton("new");
old.addActionListener(new NewButton());
pane.add(old);
JScrollPane scroll = new JScrollPane(new JTextArea(50,20));
pane.add(scroll);
pane.validate();
}
}
private class NewButton implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
pane.setLayout(new GridLayout(1,2));
JButton old = new JButton("old");
old.addActionListener(new OldButton());
pane.add(old);
JScrollPane scroll = new JScrollPane(new JTextArea(50,20));
pane.add(scroll);
pane.validate();
}
}
}
This code should replace the preexisting layout with a new one anytime the button in the corner is pressed, but instead, it just adds the new layout to the frame. Can someone tell me what I'm doing wrong?
EDIT:
Adding some information. A picture for reference:
I'm making a set of components like this inside the scroll pane. whenever I press the "Make new field" button, I want it to add a "field" (the name of the field followed by a textarea or some such) to the set in that scrollpane. This means changing the layout of the area inside the scrollpane to include the new field.
OK -- so it looks like what you want to do (and please correct me if I'm wrong) is to add a new component to a JPanel that is displayed within a JScrollPane. If so, then you do not want to change or swap layouts, and you certainly don't want to keep adding new JScrollPanes. Instead consider doing:
Create one JScrollPane and add to your GUI. Don't re-add this as you'll only need one.
add a JPanel to the JScrollPane's viewport that uses a layout that allows multiple components to be easily added to it. Perhaps a GridLayout or a BoxLayout, depending on what you need.
Also consider not adding the above JPanel directly to the viewport but rather adding it to another JPanel, one that uses BorderLayout, adding the first JPanel to the BorderLayout-using JPanel's BorderLayout.PAGE_START position, and then add this to the JScrollPane's viewport. This way the first JPanel won't stretch to fill the viewport initially.
Then in your button's ActionListener, add your components to the first JPanel by calling .add(...) on it, and then call revalidate() and repaint() on that first JPanel to layout the newly added components and repaint the JPanel and its contents.
Ok, so it turns out this wasn't a layout problem at all. I had failed to realize that setting a new layout doesn't cause the previous layout's components to disappear, you have to remove them before adding the new components. That's why I was getting duplication.
Thanks for pointing me in the right direction, though.
I am new to Java and especially new to GUI and it's super confusing to me right now.
I'm making a program for class that is supposed to have a menu (JComboBox I'm assuming) that opens a new window when an option is selected. I am just working on the first option where you click "The Matrix" and a new window pops up with two buttons called "Red Pill" & "Blue Pill" and thats where I've hit a wall.
I got to the point where I am able to create a new window (not sure if this is even the right route to take for opening the new window) but, When I try to add Buttons to the new pop up window nothing shows up....
Thanks for any help or pointers in the right direction!
public class MultiForm extends JFrame{
private JComboBox menu;
private JButton bluePill;
private JButton redPill;
private static String[] fileName = {"", "The Matrix", "Another Option"};
public MultiForm() {
super("Multi Form Program");
setLayout(new FlowLayout());
menu = new JComboBox(fileName);
add(menu);
TheHandler handler = new TheHandler();
menu.addActionListener(handler);
}
private class TheHandler implements ActionListener{
public void actionPerformed(ActionEvent event) {
********************************************************************
//Create a new window when "The Matrix" is clicked in the JCB
JFrame newFrame = new JFrame();
JPanel panel = new JPanel();
newFrame.setLayout(new FlowLayout());
newFrame.setSize(500, 300);
newFrame.setDefaultCloseOperation(newFrame.EXIT_ON_CLOSE);
Icon bp = new ImageIcon(getClass().getResource("Blue Pill.png"));
bluePill = new JButton("Blue Pill", bp);
newFrame.add(bluePill);
Icon rp = new ImageIcon(getClass().getResource("Red Pill.png"));
redPill = new JButton("Red Pill", rp);
newFrame.add(redPill);
add(panel);
newFrame.setVisible(true);
}
}
public static void main(String[] args) {
MultiForm go = new MultiForm();
go.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
go.setSize(400, 200);
go.setVisible(true);
}
}
I tried doing newFrame.add(BluePill) and it created a button that was the size of the entire window and it would not allow me to add both buttons that way
That's because the frame uses a BorderLayout by default. Unless you specify otherwise, the component's will be added to the CENTER position, BUT, BorderLayout will only allow a single component to be managed at each of the it's five available positions, so you are only seeing the last component you added.
See How to Use BorderLayout for more details
so I figured that wasn't the correct way
It's the right approach, you just need to use a layout manager which can accommodate more components or change the position which you are adding the buttons
In this little example, I've just use a FlowLayout, but you can use what ever is going to give you the effect you desire
JFrame newFrame = new JFrame();
newFrame.setLayout(new FlowLayout());
newFrame.setDefaultCloseOperation(newFrame.EXIT_ON_CLOSE);
bluePill = new JButton("Blue Pill");
newFrame.add(bluePill);
redPill = new JButton("Red Pill");
newFrame.add(redPill);
newFrame.pack();
newFrame.setVisible(true);
As a general rule of thumb, I don't like adding components like this directly to a top level container, I prefer to use a intermediate container, like a JPanel, this gives me more possibilities for re-use, but that's me.
You should also only make the frame visible when it's actually ready, otherwise you may find that some times, the components won't show up
See Laying Out Components Within a Container for more details
You are not using the getContentPane() method from the new JFrame.
You have to actually use getContentPane() first because you're not adding any component to the JFrame itself but to an intermediate "panel".
JFrame newFrame = new JFrame();
JPanel panel = new JPanel();
newFrame.setSize(300, 200);
newFrame.setDefaultCloseOperation(newFrame.EXIT_ON_CLOSE);
bluePill = new JButton("Blue Pill");
panel.add(bluePill);
redPill = new JButton("Red Pill");
panel.add(redPill);
newFrame.getContentPane().add(panel);
newFrame.setVisible(true);
You'll have to add a Layout to the JPanel or/and the JFrame and play with the sizes of the component but with this you're on the right path.
I always put the setVisible method a the end, after adding all the components to the frame.
You made some mistakes.
add(bluePill);
will not do what you want, even if it would, it would still be wrong.
(sounds weird, but I'll explain it)
First the "right" way to do it:
//Create a new window when "The Matrix" is clicked in the JCB
JFrame newFrame = new JFrame();
newFrame.setSize(300, 200);
newFrame.setDefaultCloseOperation(newFrame.EXIT_ON_CLOSE);
bluePill = new JButton("Blue Pill");
newFrame.getContentPane().add(bluePill);
redPill = new JButton("Red Pill");
newFrame.getContentPane().add(redPill);
newFrame.setVisible(true);
Notice I added "newFrame", because you were calling the method of MultiForm.
That's because "add()" is the same as "this.add()" and "this" points to MultiForm. Check it with this line if you want:
System.out.println(this.toString());
The "getContentPane()" is best explained with this image:
You were adding it directly to the JFrame (I don't even know what exactly happens then).
It is also good practice to set the frame visible when it is ready to be visible. Your frame did not contain anything when you made it visible.
Now to the JPanel. A JPanel can hold some elements like JButton,etc. and it can also have a layout. Since you didn't use the JPanel at all, i removed the line from your code. You can still add the JPanel to your ContentPane and add a Layout to the JPanel. (You can also add JPanels to JPanels to create complex layouts)
I hope this was clear for you.
I am trying to use Java Swing to create a simple GUI in which I have a drawing pad and some buttons it all works fine until I add this code for the JTextField:
String text = "hello";
JTextArea textArea = new JTextArea(text);
textArea.setPreferredSize(new Dimension(500, 50));
textArea.setEditable(false);
Before adding this code the drawpad displays on the left of the screen followed by the buttons, when I add this only the drawpad is displayed unless I resize the frame in which case the buttons and text field reappear although the text field is hidden behind the drawpad slightly. Here is the full code:
public class testGUI extends Frame{
public static void main(String[] args) {
JFrame frame = new JFrame("Neural Networks");
frame.setSize(700, 300); //set the size of the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true); //make it visible
Container content = frame.getContentPane();
content.setLayout(new BorderLayout());
JPanel mainPanel = new JPanel();
final PadDraw drawPad = new PadDraw();
drawPad.setSize(100, 100);
content.add(drawPad);
JButton clearButton = new JButton("Clear");
clearButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
drawPad.clear();
}
});
JButton loadButton = new JButton("Load");
loadButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
//Load something here
}
});
JButton testButton = new JButton("Test Draw Pad Image");
testButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
//
}
});
JButton loadImage = new JButton("Test image from file");
loadImage.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
//String filename = textField.getText();
}
});
String text = "hello";
JTextArea textArea = new JTextArea(text);
textArea.setPreferredSize(new Dimension(500, 50));
textArea.setEditable(false);
mainPanel.add(clearButton);
mainPanel.add(loadButton);
mainPanel.add(testButton);
mainPanel.add(loadImage);
mainPanel.add(textArea);
content.add(mainPanel);
}
}
You're adding the drawPad and the mainPanel to the content panel, which uses BorderLayout, without specifying any location. They thus end up both in the center position of the border layout, which is supposed to contain only one component.
See How to use BorderLayout in the Swing tutorial.
Also note that setting the preferred size is not something you should do. Instead, the preferred size is supposed to be automatically computed based on other sttings (the contained components, the number of rows and columns of a text area, etc.)
And a JTextArea should be enclosed into a JScrollPane to be good-looking and allow you to scroll.
JPanel mainPanel = new JPanel();
The default layout for a JPanel is a FlowLayout, so all the components flow on a single row. If there is not enough room on the row then the components wrap to the next row.
So when you add the JTextArea the flow is disturbed. The solution is to use a combination of layout managers to get your desired layout effect. Read the section from the Swing tutorial on Using Layout Managers for more information and examples.
JTextArea textArea = new JTextArea(text);
textArea.setPreferredSize(new Dimension(500, 50));
Also, you should NOT set the preferred size of the text area (or any Swing component for that matter). Instead you should do something like:
JTextArea textArea = new JTextArea(rows, columns);
and let the component determine its own preferred size. Also a text area is typically used with a JScrollPane and then you add the scroll pane to your panel:
JScrollPane scrollPane = new JScrollPane( textArea );
Edit:
Taking a second look at your code you have many more problems.
The point of using a layout manager is to have the layout manager set the size and location of the components. So your code should not have any logic related to the size/location of a component.
When you use the add(...) statement on a BorderLayout without a constraint, the component gets added to the CENTER. However only the last component added is managed by the BorderLayout. So only the "mainPanel" is given a size/location by the layout manager. That is why you need the setSize(...) statement on the drawPad to make the component visible. Although you now have the problem that two components are painted in the same space.
So to see the drawPad on the left you might want to use:
content.add(drawPad.BorderLayout.LINE_START);
However this still probably won't work because I'm guessing you are doing custom painting on the draw pad which means you will also need to override the getPreferredSize() method of the class so the layout manager can use the information to determine the size of the component. Read the section from the Swing tutorial on Custom Painting for more information and working examples.
Finally some other issues:.
The setVisible(...) statement should be invoked AFTER all the components have been added to the frame.
To follow Java standards, class names should start with an upper case character.
You should NOT be extending "Frame". There is no need to extend any class in your example.
Read the tutorial and download the demos for examples of better structured code.
How can I get the scroller around my JList component in the code given below? It doesn't seem to work properly :(
public class JButtonO extends JFrame{
String[] values = {"henry", "Michael","Uche","John","Ullan","Nelly",
"Ime","Lekan","Austine","jussi","Ossi","Imam","Empo","Austine","Becky",
"Scholar","Ruth", "Anny"};
public JButtonO()
{
super("the button");
this.setSize(400,200);
JPanel panel = new JPanel();
JLabel label = new JLabel("Output Items:");
label.setAlignmentX(1);
label.setAlignmentY(1);
JList conList = new JList(values);
conList.setVisibleRowCount(3);
JScrollPane scroller = new JScrollPane(conList);
panel.add(label);
panel.add(scroller);
panel.add(conList);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(panel);
this.setVisible(true);
}
Adding the JScrollPane scroller that includes the JList conList to the JPanel panel is enough.
The mistake is that you are adding the JList a second time.
JScrollPane scroller = new JScrollPane(conList);
panel.add(label);
panel.add(scroller);
panel.add(conList); // <---THIS LINE SHOULD BE DELETED...
Look, I may not answering what you need, because I don´t remember to much of swing layout. I don´t work with it a long time ago...
But removing setting a layout (I remember) on your JPanel it works with this code:
public JButtonO() {
super("the button");
this.setSize(400, 200);
// Create a panel with a borderlayout
JPanel jpanel = new JPanel(new BorderLayout());
JLabel label = new JLabel("Output Items:");
label.setAlignmentX(1);
label.setAlignmentY(1);
// Add Label to top of layout
jpanel.add(label, BorderLayout.NORTH);
JList conList = new JList(values);
conList.setVisibleRowCount(3);
JScrollPane scroller = new JScrollPane(conList);
//AddScroll to center
jpanel.add(scroller);
//Add Panel to JFrame
this.add(jpanel);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
I think the problems is the default layoutmaneger of JPanel. Because of how it works your scroll was not "srink" enough to create scrolls...
Hope it helps, even without too much explanation...
ACTUALLY: After I post the answer I saw your mistake. Now I can explain what is wrong. You already added your JList inside your JScrollPane here:
JScrollPane scroller = new JScrollPane(conList);
But after that you put it inside the JPanel:
panel.add(conList);
this changes where yout JList will be displayed, and let the JScroll empty again. Without components it will be displayed with size 0x0 and will not be draw (even being there).
Now I think I helped =D
The JScrollPane has settings called the scrollbar policies which say when the scrollbars are to be displayed. You can set them using JScrolPane(Component,int,int) constructor, or by calling setVerticalScrollBarPolicy() and setHorizontalScrollBarPolicy(). The default policies are "as needed", meaning the scrollbar is only displayed if the component is too large to display whole. So if your list fits inside the window, the scrolbars will not be visible, but will become visible when you e.g. make the window smaller using the mouse. You can change one or both policies to "always" using corresponding constants in order to make the scrollbar(s) always visible if that's what you need.