I want to know how to place JButtons at a particular coordinate in the JFrame. All day I have seen layouts. This does not suit my purpose. I would prefer something like setBounds. Rumour has it that it does not work but setLocation does. I tried it but, the program disregards the setLocation line and sets it to a Layout.
CODE
import javax.swing.JButton;
import javax.swing.JFrame;
import java.awt.BorderLayout;
public class SwingUI extends JFrame {
public SwingUI() {
JFrame frm = new JFrame("OmegaZ");
JButton btn = new JButton("ClickMe");
frm.getContentPane().add(btn, BorderLayout.NORTH);
frm.setSize(400, 400);
frm.setVisible(true);
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
btn.setLocation(100, 200);
}
public static void main(String[] args) {
new SwingUI();
}
}
Any help is appreciated.
Many Thanks
You can do absolute positioning with a null layout. You do all the work in that case.
Related
I have a JFrame, and within it, a JLabel that is filled by an image of a Map. I want to have clickable square “Tiles” in a grid over the image of the map. To do this, I made a large grid of JButtons that I have added to the JLabel containing the Map. However, the Map cannot be seen, so I have made the JButtons completely transparent. However, when they are Transparent, I can’t see where one JButton ends, and where another one starts. I want to create a JButton that is totally transparent on the inside, but still has a visible border around it. I have tried setOpaque(false) and then setBorderPainted(true) but that makes them opaque again. I have tried everything I could find, but nothing happens. Any suggestions?
Once again, all I want is a Transparent JButton with Visible Borders
You should be able to replace border with you own...
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setBackground(Color.RED);
setLayout(new GridBagLayout());
JButton btn = new JButton("Hello");
btn.setOpaque(false);
btn.setContentAreaFilled(false);
btn.setBorderPainted(true);
btn.setBorder(new LineBorder(Color.BLUE));
add(btn);
}
}
}
You might need to use a CompoundBorder with a EmptyBorder on the inside to provide some padding (I tried using setMargins but it didn't seem to work)
First of all, this is a more specific question than it seems to be. To start off: I am currently doing a small application with a rather small GUI, so I decided to make a GUI class, and initialize my whole GUI in this constructor.
This would look like this:
public class GUI extends JFrame{
public GUI{
//Initialize GUI here, including its Frames, Panels, Buttons etc.
}
}
How can I now access the GUIs frame etc. from an external class? If I would create an object of the GUI class, I would simply duplicate my GUI window. I did not come across any other ideas than making the frame, panel and so on static.
I'm somewhat lost right now. Also I'm pretty sure that I am not thinking the right way into this case, but I need someone to point me to the right direction. If someone could help me out, I would be very thankful.
First of all, using static is the worst solution possible, even if your GUI class is a singleton (buf if it is, at least it will work fine).
Why don't you simply create getters and/or setters ? And finally, it is usually not normal that external classes need to access the components of another graphic class. You should wonder if your design is the most fitted for your needs.
Here's a simple GUI to change the background color of a JPanel with a JButton. Generally, this is how you construct a Swing GUI.
package com.ggl.testing;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ChangeDemo implements Runnable {
private boolean isYellow;
private JFrame frame;
public static void main(String[] args) {
SwingUtilities.invokeLater(new ChangeDemo());
}
#Override
public void run() {
frame = new JFrame("Change Background Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS));
JPanel namePanel = new JPanel();
JLabel nameLabel = new JLabel(
"Click the button to change the background color");
nameLabel.setAlignmentX(JLabel.CENTER_ALIGNMENT);
namePanel.add(nameLabel);
mainPanel.add(namePanel);
final JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout());
buttonPanel.setBackground(Color.YELLOW);
isYellow = true;
JButton changeButton = new JButton("Change Color");
changeButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
isYellow = !isYellow;
if (isYellow) buttonPanel.setBackground(Color.YELLOW);
else buttonPanel.setBackground(Color.RED);
}
});
buttonPanel.add(changeButton);
mainPanel.add(buttonPanel);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
You don't access the Swing components of the GUI from other classes. You create other classes to hold the values of the GUI.
Generally, you use the model / view / controller pattern to construct a Swing GUI. That way, you can focus on one part of the GUI at a time.
Take a look at my article, Java Swing File Browser, to see how the MVC pattern works with a typical Swing GUI.
You don't need to make it static or to create a new JFrame object every time.
Have a look at this simple code :
class UseJFrame {
public static void main(String...args) {
Scanner sc = new Scanner(System.in);
JFrame frame = new GUI();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
System.out.println("Press E to exit");
String ip;
while(true) {
System.out.println("Show GUI (Y/N/E)? : ");
ip = sc.nextLine();
if(ip.equalsIgnoreCase("y") {
frame.setVisible(true);
} else if(ip.equalsIgnoreCase("n") {
frame.setVisible(false);
} else { // E or any other input
frame.dispose();
}
}
}
}
Note : Don't make GUI visible through constructor or it will show window at the very starting of creation of JFrame object.
If you want to use the same JFrame object at other places too then pool architecture would be better approach.
I am trying to create a simple JFrame menu where there is a nice background, which works, along with some text. The text is a bit buggy. Here is how it looks (http://imgur.com/nRpzA30)
As you can see, only one line of the text appears not the second line.
Along with that. Two GUI's appear when I run the program. One is completley empty, and one looks like the picture above.
Finally I can't use the method logo.setHorizontalAlignment(JLabel.NORTH); without getting an error, same with a few others. The two I tested and worked were only .CENTER, and .LEFT.
Any help would be great!
Oh and almost forgot, here's my code :)
package character;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
/**
* Created by Niknea on 6/28/14.
*/
public class characterSelector extends JFrame{
JPanel cselectorText;
JFrame cselectorButtons;
JLabel logo, characterName, label;
JButton previous, next;
public characterSelector(String title){
super(title);
this.createCharacterSelector();
this.setSize(1920, 1033);
this.setResizable(true);
this.setVisible(true);
}
public void createCharacterSelector(){
try {
label = new JLabel(new ImageIcon(ImageIO.read(getClass().getResource("/resources/Grass_Background.jpg"))));
cselectorButtons = new JFrame();
logo = new JLabel("SoccerKidz [REPLACE W/ COOL LOGO]");
characterName = new JLabel("<Character Name>");
logo.setPreferredSize(new Dimension(50, 50));
logo.setFont(new Font(logo.getFont().getName(), Font.HANGING_BASELINE, 50));
characterName.setFont(new Font(characterName.getFont().getName(), Font.HANGING_BASELINE, 50));
cselectorButtons.add(logo);
cselectorButtons.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
cselectorButtons.setContentPane(label);
cselectorButtons.setLayout(new BorderLayout());
characterName.setForeground(Color.CYAN);
characterName.setHorizontalAlignment(JLabel.CENTER);
cselectorButtons.add(characterName);
logo.setForeground(Color.CYAN);
logo.setHorizontalAlignment(JLabel.LEFT);
cselectorButtons.add(logo);
cselectorButtons.pack();
cselectorButtons.setLocationRelativeTo(null);
cselectorButtons.setVisible(true);
} catch (IOException exp) {
exp.printStackTrace();
}
}
}
Thanks again! :)
As you can see, only one line of the text appears not the second line.
You set the layout of cselectorButtons to BorderLayout. Then you add JLabel("<Character Name>");, which is fine. But then you add JLabel("SoccerKidz [REPLACE W/ COOL LOGO]");. Here's what's happening. With BorderLayout, when you just add(component), generally you want to specify a BorderLayout.[POSITION] as the second argument to the add. If you don't, every component that you add, without the position specified, will be added the the BorderLayout.CENTER implicitly by default. The problem with this is each position can only have one component. So in your case, the first label gets kicked out the center, only showing the second one you added.
Two GUI's appear when I run the program. One is completley empty, and one looks like the picture above.
When look at your code. Your class is a JFrame in which you add nothing to, and this.setVisible(true). And also you a JFrame cselectorButtons; in which you do add components and also cselectorButtons.setVisible(true);. Can you guess which one is the one you're seeing that's not empty. Don't extends JFrame. Just use the instance one you currently are using.
Finally I can't use the method logo.setHorizontalAlignment(JLabel.NORTH); without getting an error.
It doesn't take much to take a look at the API for JLabel. That being said, what makes you think aligning something horizontally, should include an option to position to the north. Doesn't make sense
public void setHorizontalAlignment(int alignment)
Sets the alignment of the label's contents along the X axis.
Parameters:
alignment - One of the following constants defined in SwingConstants: LEFT, CENTER (the default for image-only labels), RIGHT, LEADING (the default for text-only labels) or TRAILING.
I suggest you take a look at Layout out Components Within a Container and A Visual Guide to Layout Managers for other possibly layout managers you can use, if BorderLayout doesn't suit you. Also keep in mind you can nest different panels with different layout managers to get your desired result. But first you need to learn how they work.
UPDATE
I made some changes, which works. I'm also looking at your pastebin code, and can't really see any difference. You may want to investigate my code to try and look for differences
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
/**
* Created by Niknea on 6/28/14.
*/
public class CharacterSelector {
JPanel cselectorText;
JFrame cselectorButtons;
JLabel logo, characterName, label;
JButton previous, next;
public CharacterSelector() {
createCharacterSelector();
}
public void createCharacterSelector() {
try {
label = new JLabel(new ImageIcon(ImageIO.read(getClass()
.getResource("/resources/Grass_Background.jpg"))));
cselectorButtons = new JFrame();
logo = new JLabel("SoccerKidz [REPLACE W/ COOL LOGO]");
characterName = new JLabel("<Character Name>");
logo.setPreferredSize(new Dimension(50, 50));
logo.setFont(new Font(logo.getFont().getName(),
Font.HANGING_BASELINE, 50));
characterName.setFont(new Font(characterName.getFont().getName(),
Font.HANGING_BASELINE, 50));
cselectorButtons.add(logo);
cselectorButtons.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
cselectorButtons.setContentPane(label);
cselectorButtons.setLayout(new BorderLayout());
characterName.setForeground(Color.CYAN);
characterName.setHorizontalAlignment(JLabel.CENTER);
cselectorButtons.add(characterName);
logo.setForeground(Color.CYAN);
logo.setHorizontalAlignment(JLabel.LEFT);
cselectorButtons.add(logo, BorderLayout.NORTH);
cselectorButtons.pack();
cselectorButtons.setLocationRelativeTo(null);
cselectorButtons.setVisible(true);
} catch (IOException exp) {
exp.printStackTrace();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
new CharacterSelector();
}
});
}
}
I want to put FlowLayout with lets say 5 labels inside BorderLayout as north panel (BorderLayout.NORTH), and when I resize my window/frame I want the labels to not disappear but instead move to new line.
I have been reading about min, max values and preferredLayoutSize methods. However they do not seem to help and I am still confused.
Also, I would not like to use other layout like a wrapper or something.
One of the annoying things about FlowLayout is that it doesn't "wrap" it's contents when the available horizontal space is to small.
Instead, take a look at WrapLayout, it's FlowLayout with wrapping...
The following code does exactly what you asked.
The program has a frame whose contentPane is set for BorderLayout. It contains another panel flowPanel that has a flow layout and is added to the BorderLayout.NORTH.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class PanelFun extends JFrame {
final JPanel flowPanel;
public PanelFun() {
setPreferredSize(new Dimension(300,300));
getContentPane().setLayout(new BorderLayout());
flowPanel = new JPanel(new FlowLayout());
addLabels();
getContentPane().add(flowPanel, BorderLayout.NORTH);
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
PanelFun.this.getContentPane().remove(flowPanel); //this statement is really optional.
PanelFun.this.getContentPane().add(flowPanel);
}
});
}
void addLabels(){
flowPanel.add(new JLabel("One"));
flowPanel.add(new JLabel("Two"));
flowPanel.add(new JLabel("Three"));
flowPanel.add(new JLabel("Four"));
flowPanel.add(new JLabel("Five"));
}
public static void main(String[] args) {
final PanelFun frame = new PanelFun();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
frame.setVisible(true);
}
});
}
}
So, how does it work?
The key to having the components inside flowPanel realign when the frame is resized is this piece of code
PS: Let me know if you are new to Swing and do not understand some part of the code.
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
PanelFun.this.getContentPane().remove(flowPanel);
PanelFun.this.getContentPane().add(flowPanel);
}
});
Without this code the flowPanel will not realign its components as it is not its normal behaviour to reposition components when the containing frame is resized.
However, it is also its behaviour that when flowPanel is added to a panel, it would position components as per the available space. So, if we add the flowPanel everytime the frame resizes, the inner elements will be repositioned to use the available space.
Update:
As camickr pointed out correctly, this method will not work in case you add anything to the center (BorderLayout.CENTER)
I'm working on a project, there are JInternalFrames in the mainframe. Now, we need to let them to be JFrame. I'm considering using a JFrame to hold on JInternalFrame. The problem is that the titlebar of Internalframe is there, and user can drag it around.
Is there any way to make the Internal frame work like a pane in the JFrame?
After searching on the Internet, I found somebody removes the titlepane.
Do you have any good idea on this?
Thanks you!
update:
Maybe I was on the wrong track. The real problem is the JInternal frame can not get out of the main Frame, or any way to make it look like it's out side of the frame?
Is there any way to make the Internal frame work like a pane in the
JFrame
Im not sure by what you mean by pane, but I guess like a JPanel? Of course you can but why, would be my question, unless you want some sort of quick floating panel, but than you say you dont want it draggable? So Im bit unsure of your motives and makes me weary to answer....
The problem is that the titlebar of Internalframe is there
Well Here is code to remove the titlepane (found it here):
//remove title pane http://www.coderanch.com/t/505683/GUI/java/JInternalframe-decoration
BasicInternalFrameTitlePane titlePane =(BasicInternalFrameTitlePane)((BasicInternalFrameUI)jInternalFrame.getUI()).getNorthPane();
jInternalFrame.remove(titlePane);
and user can drag it around.
And I found this to make JInternalFrame unmovable by removing the MouseListeners which make it movable, but it is important to note its not necessary to remove the MouseListeners as the method used to make it undraggable will remove the NorthPane which the MouseListener is added too thus its unnecessary for us to remove it ourselves.:
//remove the listeners from UI which make the frame move
BasicInternalFrameUI basicInternalFrameUI = ((javax.swing.plaf.basic.BasicInternalFrameUI) jInternalFrame.getUI());
for (MouseListener listener : basicInternalFrameUI.getNorthPane().getMouseListeners()) {
basicInternalFrameUI.getNorthPane().removeMouseListener(listener);
}
And as per your title:
how to make JInternalFrame fill the Container
Simply call setSize(int width,int height) on JInternalFrame with parameters of the JDesktopPanes width and height (JDesktopPane will be sized via overriding getPreferredSize()).
Which will give us this:
import java.awt.Dimension;
import java.awt.HeadlessException;
import java.awt.event.MouseListener;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.SwingUtilities;
import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
import javax.swing.plaf.basic.BasicInternalFrameUI;
/**
*
* #author David
*/
public class Test {
public Test() {
createAndShowGUI();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
private void createAndShowGUI() throws HeadlessException {
JFrame frame = new JFrame();
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
final JDesktopPane jdp = new JDesktopPane() {
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
};
frame.setContentPane(jdp);
frame.pack();
createAndAddInternalFrame(jdp);
frame.setVisible(true);
}
private void createAndAddInternalFrame(final JDesktopPane jdp) {
JInternalFrame jInternalFrame = new JInternalFrame("Test", false, false, false, false);
jInternalFrame.setLocation(0, 0);
jInternalFrame.setSize(jdp.getWidth(), jdp.getHeight());
//remove title pane http://www.coderanch.com/t/505683/GUI/java/JInternalframe-decoration
BasicInternalFrameTitlePane titlePane = (BasicInternalFrameTitlePane) ((BasicInternalFrameUI) jInternalFrame.getUI()).getNorthPane();
jInternalFrame.remove(titlePane);
/*
//remove the listeners from UI which make the frame move
BasicInternalFrameUI basicInternalFrameUI = ((javax.swing.plaf.basic.BasicInternalFrameUI) jInternalFrame.getUI());
for (MouseListener listener : basicInternalFrameUI.getNorthPane().getMouseListeners()) {
basicInternalFrameUI.getNorthPane().removeMouseListener(listener);
}
*/
jInternalFrame.setVisible(true);
jdp.add(jInternalFrame);
}
}
Given your requirements, I suggest you just use a simple JPanel inside your JFrame content pane.