I have a single JLabel in my JFrame, initially displayed using pack().
My problem is that whenever I try to resize the window, the JLabel also moves (depending on which side of the window is resized), largely due to the layout of the JFrame.
To be more specific, whenever I resize the window up/down, the JLabel stays centered. I would like that not be the case.
I'm sorry if my question is confusing. I'll gladly provide diagrams if requested.
public class JavaApplication8 {
public static void main(String[] args) throws MalformedURLException {
// TODO code application logic here
JFrame window = new JFrame("test");
URL bgURL = new URL("https://si0.twimg.com/profile_images/3585146044/3b695fa73490227f792fa4e46d4a7a57.jpeg");
ImageIcon bg = new ImageIcon(bgURL);
JLabel label = new JLabel(bg);
window.add(label, BorderLayout.CENTER);
window.pack();
window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
window.setLocationRelativeTo(null);
window.setVisible(true);
}
}
Use a different layout manager:
window.setLayout(new FlowLayout());
would be sufficient for the example.
Another possibility, if you want to keep using BorderLayout, is placing the label to a different position:
window.add(label, BorderLayout.NORTH);
Also note that you should access swing components only from the event dispatch thread.
Related
Code:
public class launcher implements ActionListener {
private static JFrame window;
private static JPanel panel;
private JButton createPassword;
private JButton seePassword;
public launcher() {
window = new JFrame();
panel = new JPanel();
window.setTitle("Password Vault");
window.setSize(400, 260);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setLocationRelativeTo(null);
window.setResizable(false);
window.setVisible(true);
window.getContentPane().add(panel); // Adds panel to JFrame
createPassword = new JButton("Create Password");
createPassword.setBounds(20, 100, 150, 100);
createPassword.addActionListener(this);
seePassword = new JButton("View Password");
seePassword.setLocation(20, 50);
seePassword.addActionListener(this);
panel.add(createPassword);
panel.add(seePassword);
}
public static void main(String[] args) {
new launcher();
}
Why can I not change the location of my JButtons? I have tried the setBounds and setLocation function but my buttons still stay on the top middle part of the JFrame window. I have also tried declaring my buttons inside the launcher() method and declaring them as a static variable.
You should NOT attempt to set the size/location of your buttons.
Swing was designed to be used with layout managers. The layout manager will set the size/location of the button based on the rules of the layout manager.
The default layout manager for a JPanel is the FlowLayout, which is why you see the button centered.
If you want to position the buttons differently, then you need to change the layout manager.
Read the section from the Swing tutorial on Layout Managers for more information and examples.
It looks like you want the buttons displayed vertically, so maybe a BoxLayout or GridLayout can be used depending on your exact requirement.
Other issues with your code:
Class names should start with an upper case character
There is no need to use static variables. That is not how the static keyword should be used
Components should be added to the frame BEFORE the frame is made visible.
You should be invoking pack() on the frame, BEFORE invoking setVisible(...) so the components can be displayed at their preferred size.
While you really shouldn't change the place of your components without a layout manager, there is a way. If you put this line of code into your code, it should work with setBounds:
window.setLayout(null);
I currently have a Jframe that I want to add to a tab instead.
(I used a frame just for testing purposes, to make sure the look and feel is correct, but when trying to add it to a JTabbedPane, the frame starts to look blue (weird top aswell).
I tried copying my settings from my original frame to the new frame but that did not help.
JTabbedPane tabs = new JTabbedPane();
tabs.addTab("1", frame.getContentPane());
JFrame FinalFrame = new JFrame();
FinalFrame.setDefaultLookAndFeelDecorated(true);
FinalFrame.setSize(WIDTH, HEIGTH);
FinalFrame.setLocation(100, 150);
FinalFrame.setTitle("Primal-Pvm Notification center");
FinalFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FinalFrame.add(tabs);
Side by side view of the problem and the frame before adding it to the tab:
Edit: Answer by George Z. helped me out a lot.
Like he said to solve the problem:
Don't add things to your main frame but add them to a Jpanel and add that to a JTabbedPane.
If you have a Jpanel that you are adding to a tab that contains an override in the paintComponent, you have to create that class as the Jpanel so:
JPanel panel = new LineDrawer([Enter parameters]);
panel.setLayout([Enter Layout]);
The way you are approaching this seems to be pretty complex hence this weird behavior. (Looks like a look and feel problem? - show the part of the code that sets it)
However, I suggest you to create only one JFrame (this question explains why you should do that), set the layout of its content pane to BorderLayout and keep it like this. Its a rare situation to mess up with content panes. After that create independent JPanels representing the tab(s) you would like to have. Finally create a JTabbedPane with these panels and add it to the content frame of the JFrame.
A small example would be:
public class TabbedPanelExample extends JFrame {
public TabbedPanelExample() {
super("test");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
JTabbedPane pane = new JTabbedPane();
pane.addTab("FirstTab", createFirstTab());
pane.addTab("SecondTab", createSecondTab());
add(pane);
setSize(400, 400);
setLocationRelativeTo(null);
}
private Component createFirstTab() {
JPanel panel = new JPanel(new FlowLayout());
panel.add(new JLabel("Some Component"));
panel.add(new JTextField("Some Other Component"));
return panel;
}
private Component createSecondTab() {
JPanel panel = new JPanel(new FlowLayout());
panel.add(new JLabel("Some Component"));
panel.add(new JButton("Some Other Component"));
return panel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new TabbedPanelExample().setVisible(true);
});
}
}
Post edit based on this comment:
Well I do have a Jframe with a lot of elements added to it so it kinda
is a hassle to switch it all to panels;
A JFrame cannot have a lot of elements. You take a look on how to use root panes. The container that "has a lot of elements" of a JFrame is its rootpane which is mostly completed by its contentpane. When you frame.add(component), you add the component to its content pane. Guess what? A JFrame's content pane is a JPanel. So are a already to panels.
Now in order to make this work, try to do as i said and frame.setLayout(new BorderLayout(); //changes layout to contentpane. Assuming you have a bunch of components (lets say comp1,comp2) and you are adding them like:
frame.add(comp1);
frame.add(comp2);
You must do the following in order to make it clear. Create a JPanel and instead of frame.add(comp1), do panel.add(comp1). So this JPanel has all the components you added in JFrame. After that create your JTabbedPane:
JTabbedPane pane = new JTabbedPane();
pane.addTab("tab", panel);
and finally add this pane to the content pane of your JFrame:
frame.add(pane);
In conclusion, you will move all the components you have added to your frame into a JPanel, add this JPanel to a JTabbedPane, and finally add this JTabbedPane to the frame (contentpane). Frame has only one component.
I am creating a user system to hold multiple details of multiple users. so i would like to create a button that would be able to create another button. when the second button is pressed a form will open for the user to fill. I have already created the form for the user to fill but i cannot manage to make the button to create more buttons to work. I have coded this but it does not show the button on the Jpanel.
I have created the following code:
private void mainButtonActionPerformed(java.awt.event.ActionEvent evt) {
JButton b=new JButton("Click Here");
b.setBounds(50,100,95,30);
jPanel3.add(b);
b.setVisible(true);
}
This doesn't seem to create a new button within jPanel3. Have I typed up the code incorrectly or is there an alternative correct way of doing this?
I would like 3 buttons in a row and then a new row of buttons.
Your code and question is missing too much information to be answered completely or well. About all I can say is
Always call jPanel3.revalidate() and jPanel3.repaint() on the container after adding or removing components from it as this tells the container's (here jPanel3) layout managers to re-layout all components and then re-draw them.
The container's layout manager is key for this to work well -- we have no idea what it is at the moment, and some layout managers will allow you to do this easily (e.g., FlowLayout, GridLayout) while others won't (e.g., GroupLayout).
There's no need for b.setVisible(true); since your newly created JComponent (JButton here) is already visible by default.
You appear to assume that it's using null layouts since you're calling setBounds(...), and this is a Bad Idea™. While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
When asking such questions, try to create and post with the question a small but complete program that we can test and run, and that illustrates your problem, a minimal example program (please click on the link).
For example, my MCVE that shows how your code can work:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.*;
#SuppressWarnings("serial")
public class AddButton extends JPanel {
private JPanel jPanel3 = new JPanel(); // panel to hold buttons
public AddButton() {
// create JButton that will add new buttons to jPanel3
JButton addMoreButtonsBtn = new JButton("Add More Buttons");
// give it an ActionListener
addMoreButtonsBtn.addActionListener(e -> {
final JButton newButton = new JButton("Click Here");
// when you click it, it removes itself (just for grins)
newButton.addActionListener(e2 -> {
jPanel3.remove(newButton);
// again revalidate and repaint
jPanel3.revalidate();
jPanel3.repaint();
});
// add to jPanel3, the "container"
jPanel3.add(newButton);
// revalidate and repaint the container
jPanel3.revalidate();
jPanel3.repaint();
});
// create a JPanel and put the add more buttons button to it
JPanel bottomPanel = new JPanel();
bottomPanel.add(addMoreButtonsBtn);
// give jPanel3 a layout that can handle new buttons
// a gridlayout with 1 column and any number of rows
jPanel3.setLayout(new GridLayout(0, 1));
// add it to the top of another JPanel that uses BorderLayout
JPanel borderLayoutPanel = new JPanel(new BorderLayout());
borderLayoutPanel.add(jPanel3, BorderLayout.PAGE_START);
// and add that to a JScrollPane, so we can add many buttons and scroll
JScrollPane scrollPane = new JScrollPane(borderLayoutPanel);
// make the vert scrollbar always visible
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
// force GUI to be larger
setPreferredSize(new Dimension(400, 200));
// give the main JPanel a BorderLayout
setLayout(new BorderLayout());
// and add scrollpane to center
add(scrollPane, BorderLayout.CENTER);
// add bottom panel to the bottom
add(bottomPanel, BorderLayout.PAGE_END);
}
private static void createAndShowGui() {
AddButton mainPanel = new AddButton();
JFrame frame = new JFrame("AddButton");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
I have to align a button on my program to the exact middle, the current code I have runs it but displays the button as large as the program, I am wanting a center button that is a specific size, here is what I tried
/**
* Created by Timk9 on 11/04/2016.
*/
import javax.swing.*;
import java.awt.*;
public class Test extends JFrame {
{
JFrame window = new JFrame("Test");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setResizable(true);
window.setSize(600, 600);
window.setVisible(true);
window.setLocationRelativeTo(null);
JPanel p = new JPanel(new GridBagLayout());
//Button does not appear until I resize the program?
JButton b1 = new JButton("Click here");
GridBagConstraints c = new GridBagConstraints();
p.add(b1);
window.add(p);
}
public static void main(String[] args) {
new Test();
}
}
JPanel p = new JPanel(new GridBagLayout());
You create a panel with a GridBagLayout which is a good layout manager to use to center the component.
p.add(b1);
But then you add the button to the panel without using any contraints.
The code should be:
p.add(b1, c);
//Button does not appear until I resize the program?
All components should be added to the frame BEFORE the frame is made visible. The setVisible(...) statement should be the last statement of the constructor.
Also could you point out which part is an instance initializer block, I thought I was using a constructor
See the FrameDemo example from the Swing tutorial on How to Make Frames for a better way to structure your code so you follow Swing conventions. Start with the working code and make the changes to add your panel containing the button, instead of using the JLabel. Note you no longer need to use the getContentPane() method, you can just add the panel directly to the frame.
It is the LayoutManager that defines how components are layed out where and how big. GridLayout which you are using e. g. divides the available space in equal grid fields and makes the components completely fill this space which is why your button is as big as your application. See here for more info about LayoutManagers: https://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
Btw. your code is not compilable: new JButton("he"),JButton.ALIGN_CENTER)
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.