I've been tasked to make a GUI in Java by using "swing" which is an exact replica of the image below. It doesn't have to have any functionality, it's just for looks. However, there's this one part of this image I can't find or make, which is the top right corner "gender" box. How do I make that transparent-looking box that has an outline? Please help me out, and thank you!
That is called a TitledBorder.
Example:
public class SwingTester {
public static void main(String[] args) {
createWindow();
}
private static void createWindow() {
JFrame frame = new JFrame("Swing Tester");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
createUI(frame);
frame.setSize(560, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static void createUI(JFrame frame){
//Create a border
Border blackline = BorderFactory.createTitledBorder("Title");
JPanel panel = new JPanel();
LayoutManager layout = new FlowLayout();
panel.setLayout(layout);
JPanel panel1 = new JPanel();
String spaces = " ";
panel1.add(new JLabel(spaces + "Title border to JPanel" + spaces));
panel1.setBorder(blackline);
panel.add(panel1);
frame.getContentPane().add(panel, BorderLayout.CENTER);
}
}
For your case, update this line with your own title:
Border blackline = BorderFactory.createTitledBorder("Title"); //change to gender
Source: https://www.tutorialspoint.com/swingexamples/add_title_to_border_panel.htm
Related
Is there a way such that a component that is added to the BorderLayout.PAGE_START area will become scrollable if (and only if) there's not enough space?
I have attached a minimal example. If you resize the complete frame the label in the center will become scrollable, the label at the top won't.
Unfortunately, I can't change the BorderLayout.PAGE_START positioning, as this is given by a framework. However I do have full control over the creation of myComponent.
public static void main(String[] args){
JPanel panel = new JPanel(new BorderLayout());
JComponent myComponent = new JScrollPane(new JLabel("<html>START-START<br><br>START-START</html>"));
panel.add(myComponent, BorderLayout.PAGE_START);
panel.add(new JScrollPane(new JLabel("<html>CENTER-CENTER<br><br>CENTER-CENTER</html>")), BorderLayout.CENTER);
final JFrame mainframe = new JFrame("Test");
mainframe.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
mainframe.getContentPane().add(panel);
javax.swing.SwingUtilities.invokeLater(() -> {
mainframe.pack();
mainframe.setVisible(true);});
}
Is there a way such that a component that is added to the BorderLayout.PAGE_START area will become scrollable if there's not enough space?
Yes there is. Make its preferred height less than its actual height. BorderLayout respects the preferred height of the component contained at PAGE_START, so it doesn't matter how many lines you put in your JLabel, it will be displayed at its preferred height – without scrollbars.
Try the following.
public static void main(String[] args) {
JPanel panel = new JPanel(new BorderLayout());
JComponent myComponent = new JScrollPane(new JLabel("<html>START-START<br><br>START-START</html>"));
myComponent.setPreferredSize(new Dimension(100, 20));
panel.add(myComponent, BorderLayout.PAGE_START);
panel.add(new JScrollPane(new JLabel("<html>CENTER-CENTER<br><br>CENTER-CENTER</html>")),
BorderLayout.CENTER);
final JFrame mainframe = new JFrame("Test");
mainframe.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
mainframe.getContentPane().add(panel);
javax.swing.SwingUtilities.invokeLater(() -> {
mainframe.pack();
mainframe.setVisible(true);
});
}
EDIT
The below code doesn't give the best result but I think it is the way to go. You just need to play around with the different sizes of the different components.
I added a ComponentListener to the content pane of the JFrame. When the JFrame is resized, you need to recalculate the heights of the top component and the center component according to your needs and then update the relevant component sizes. Note that the below code is not a complete solution but hopefully enough to allow you to arrive at a complete solution.
public static void main(String[] args) {
final JFrame mainframe = new JFrame("Test");
JLabel topLabel = new JLabel("<html>START-START<br><br>START-START");
JScrollPane topPane = new JScrollPane(topLabel);
mainframe.add(topPane, BorderLayout.PAGE_START);
JLabel centerLabel = new JLabel("<html>CENTER-CENTER<br><br>CENTER-CENTER");
centerLabel.setMinimumSize(centerLabel.getPreferredSize());
JPanel centerPane = new JPanel();
centerPane.add(centerLabel);
mainframe.add(centerPane, BorderLayout.CENTER);
javax.swing.SwingUtilities.invokeLater(() -> {
mainframe.pack();
mainframe.setVisible(true);
final Dimension centerPaneDim = centerPane.getPreferredSize();
final Dimension topLabelDim = topLabel.getPreferredSize();
mainframe.getContentPane().addComponentListener(new ComponentListener() {
#Override
public void componentShown(ComponentEvent e) {
// Do nothing.
}
#Override
public void componentResized(ComponentEvent e) {
Dimension size = e.getComponent().getSize();
if (size.height < centerPaneDim.height + topLabelDim.height + 10) {
topPane.setPreferredSize(new Dimension(topLabelDim.width, 10 + size.height - centerPaneDim.height));
}
else {
topPane.setPreferredSize(new Dimension(topLabelDim.width, topLabelDim.height + 10));
}
e.getComponent().revalidate();
e.getComponent().repaint();
}
#Override
public void componentMoved(ComponentEvent e) {
// Do nothing.
}
#Override
public void componentHidden(ComponentEvent e) {
// Do nothing.
}
});
});
}
I have a strange white stripe (see below) appearing on top of my background image. The code is quite simple. How to get rid of the white stripe?
//Graphics side of the game
public class GUI extends JFrame {
private final int larghezza = 1280;
private final int altezza = 720;
private final String name = "Sette e Mezzo";
private final ImageIcon backgroundImage;
private JLabel bgImageLabel;
private JPanel backgroundPanel, borderLayoutPanel, topGridLayout, botGridLayout;
public GUI () {
backgroundImage = new ImageIcon ("assets/background.png");
bgImageLabel = new JLabel (backgroundImage);
//Panels
borderLayoutPanel = new JPanel (new BorderLayout ());
topGridLayout = new JPanel (new GridLayout (1, 3));
botGridLayout = new JPanel (new GridLayout (1, 3));
backgroundPanel = new JPanel ();
backgroundPanel.add (bgImageLabel);
//Frame
this.setName (name);
this.setPreferredSize (new Dimension(larghezza, altezza));
this.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
//Adding to frame and panels
borderLayoutPanel.add (topGridLayout, BorderLayout.NORTH);
borderLayoutPanel.add (botGridLayout, BorderLayout.SOUTH);
this.add (borderLayoutPanel);
this.add (backgroundPanel);
this.pack ();
this.setLocationRelativeTo (null);
this.setVisible (true);
}
}
Don't use setPreferredSize() when you really mean to override getPreferredSize(). In this case, the specified Dimension probably doesn't quite match the size of "assets/background.png". This allows some portion of another panel to show, perhaps backgroundPanel.
In the example below,
The default layout of JPanel is FlowLayout, which has a "default 5-unit horizontal and vertical gap." A touch of Color.blue makes the gap stand out; resize the enclosing frame to see the behavior.
As the default layout of JFrame is BorderLayout, you may not need borderLayoutPanel at all.
Because the two GridLayout panels have no content, they remain invisible. Add content to each or override getPreferredSize() in each to see the effect.
Construct and manipulate Swing GUI objects only on the event dispatch thread.
import java.awt.*;
import java.net.URL;
import javax.swing.*;
public class GUI {
private static final String TITLE = "Title";
private static ImageIcon IMAGE_ICON;
private void display() {
//Panels
JPanel topGridLayout = new JPanel(new GridLayout(1, 3));
JPanel botGridLayout = new JPanel(new GridLayout(1, 3));
JPanel backgroundPanel = new JPanel();
backgroundPanel.setBackground(Color.blue);
backgroundPanel.add(new JLabel(IMAGE_ICON));
//Frame
JFrame f = new JFrame(TITLE);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add components
f.add(topGridLayout, BorderLayout.NORTH);
f.add(backgroundPanel);
f.add(botGridLayout, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) throws Exception {
IMAGE_ICON = new ImageIcon(new URL("http://i.imgur.com/mowekvC.jpg"));
EventQueue.invokeLater(new GUI()::display);
}
}
I'm trying to get a JTextArea with a "save" JButton centered underneath it, maybe with a small bit of padding between the components as well as the components to the frame if possible. I've tried messing around with layout managers, panels, etc. and can't seem to get the result i want. Just looking for the simplest way to do this. Thanks.
Suggestions:
The overall layout of the GUI container could be BorderLayout.
Add the JScrollPane that holds your JTextArea BorderLayout.CENTER.
Create a JPanel just to hold the JButton and don't give it a specific layout manager. It will now use JPanel's default FlowLayout and will center components in the horizontal direction.
Add your JButton to this last JPanel.
Add that same JPanel to the GUI in the BorderLayout.PAGE_END (bottom) position.
For example:
import java.awt.BorderLayout;
import javax.swing.*;
public class SimpleLayout extends JPanel {
private static final int ROWS = 20;
private static final int COLS = 60;
private JTextArea textArea = new JTextArea(ROWS, COLS);
private JButton button = new JButton("Button");
public SimpleLayout() {
JPanel buttonPanel = new JPanel();
buttonPanel.add(button);
setLayout(new BorderLayout());
add(new JScrollPane(textArea), BorderLayout.CENTER);
add(buttonPanel, BorderLayout.PAGE_END);
}
private static void createAndShowGui() {
SimpleLayout mainPanel = new SimpleLayout();
JFrame frame = new JFrame("SimpleLayout");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
});
}
}
Hey guys I wanted to create a JScrollPane but it won't work... and I don't know why... here's my code...
public class test extends JFrame{
public test(){
setSize(1000,600);
}
private static JButton[] remove;
private static JPanel p = new JPanel();
public static void main(String[]args){
p.setLayout(null);
JFrame t=new test();
remove = new JButton[25];
for(int i=0;i<25;i++){
remove[i]=new JButton("Remove");
remove[i].setBounds(243,92+35*i,85,25);
p.add(remove[i]);
}
JScrollPane scrollPane = new JScrollPane(p);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
t.add(scrollPane);
t.setVisible(true);
}
Umm and Im pretty sure the frame isn't big enough for these 25 buttons... But if i delete that p.setLayout(null); A horizontal scroll bar will be created automatically... I don't really know what is wrong with my code... Pls help thank you very much!
You need to set p's preferredSize for this to work.
p.setPreferredSize(new Dimension(800, 2000));
Or you could have p extend JPanel and then override the getPreferredSize() method to return the proper dimension.
And I agree -- get rid of your null layouts. Learn about and use the layout managers if you want to use Swing correctly and have robust Swing GUI's.
e.g.,
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Foo extends JFrame {
private static final int BUTTON_COUNT = 25;
public static void main(String[] args) {
JPanel btnPanel = new JPanel(new GridLayout(0, 1, 0, 20));
btnPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
AbstractAction removeAction = new AbstractAction("Remove") {
#Override
public void actionPerformed(ActionEvent evt) {
JButton src = (JButton) evt.getSource();
JPanel container = (JPanel) src.getParent();
container.remove(src);
container.revalidate();
container.repaint();
}
};
for (int i = 0; i < BUTTON_COUNT; i++) {
JButton removeBtn = new JButton(removeAction);
btnPanel.add(removeBtn);
}
JPanel borderPanel = new JPanel(new BorderLayout());
borderPanel.add(btnPanel, BorderLayout.NORTH);
JScrollPane scrollpane = new JScrollPane(borderPanel,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollpane.setPreferredSize(new Dimension(400, 800));
JFrame frame = new JFrame("Foo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(scrollpane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
The issue is that a scroll pane checks the component inside it for a "preferred size" so a pane with a null layout has a preferred size of (0,0). Which it ignores.
You should do something along the lines of:
p.setPreferredSize(1000,600);
And you should see some scroll bars appear, I'm not sure how accurate they will be though.
I have a class that extends a JPanel called Row. I have a bunch of Row added to a JLabel, the code is the following:
JFrame f=new JFrame();
JPanel rowPanel = new JPanel();
//southReviewPanel.setPreferredSize(new Dimension(400,130));
rowPanel.setLayout(new BoxLayout(rowPanel, BoxLayout.Y_AXIS));
rowPanel.add(test1);
rowPanel.add(test1);
rowPanel.add(test2);
rowPanel.add(test3);
rowPanel.add(test4);
rowPanel.setPreferredSize(new Dimension(600, 400));
rowPanel.setMaximumSize(rowPanel.getPreferredSize());
rowPanel.setMinimumSize(rowPanel.getPreferredSize());
f.setSize(new Dimension(300,600));
JScrollPane sp = new JScrollPane(rowPanel);
sp.setSize(new Dimension(300,600));
f.add(sp);
f.setVisible(true);
where test1...etc is a Row. However when I resize the window the layout of the Row somehow becomes messy (it resizes as well)... how can I prevent this from happening?
Read the Swing tutorial on Using Layout Managers. Each layout manager has its own rules about what happens when the container is resized. Experiment and play.
In the case of a BoxLayout it should respect the maximum size of the components added to the panel so you can do:
childPanel.setMaximumSize( childPanel.getPreferredSize() );
If you need more help post your SSCCE demonstrating the problem.
I took the code in http://download.oracle.com/javase/tutorial/uiswing/examples/layout/BoxLayoutDemoProject/src/layout/BoxLayoutDemo.java and adapted it with what you are trying to do, only using buttons instead of custom JPanels:
public class BoxLayoutDemo {
public static void addComponentsToPane(Container pane) {
JPanel rowPanel = new JPanel();
pane.add(rowPanel);
rowPanel.setLayout(new BoxLayout(rowPanel, BoxLayout.Y_AXIS));
rowPanel.add(addAButton("Button 1"));
rowPanel.add(addAButton("Button 2"));
rowPanel.add(addAButton("Button 3"));
rowPanel.add(addAButton("Button 4"));
rowPanel.add(addAButton("5"));
rowPanel.setPreferredSize(new Dimension(600, 400));
rowPanel.setMaximumSize(rowPanel.getPreferredSize());
rowPanel.setMinimumSize(rowPanel.getPreferredSize());
}
private static JButton addAButton(String text) {
JButton button = new JButton(text);
button.setAlignmentX(Component.CENTER_ALIGNMENT);
return button;
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("BoxLayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set up the content pane.
addComponentsToPane(frame.getContentPane());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
The end result is this:
As you can see, the button row is perfectly aligned. If you resize the JFrame, they stay aligned. Is that what you are looking for?