I am having some difficulty getting a JDesktopPane (that contains a JInternalFrame) to add to a JPanel. What is the proper way to do this? What am I doing wrong?
Here is my bare bones example:
import javax.swing.*;
import java.awt.*;
public class MainPanel extends JPanel {
JDesktopPane jDesktopPane = new JDesktopPane();
JInternalFrame jInternalFrame = new JInternalFrame();
public MainPanel() {
jDesktopPane.add(jInternalFrame);
add(jDesktopPane);
setSize(400,400);
setVisible(true);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("This isn't working...");
MainPanel mainPanel = new MainPanel();
frame.setLayout(new BorderLayout());
frame.add(mainPanel, BorderLayout.CENTER);
frame.setContentPane(mainPanel);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLocationByPlatform(false);
frame.setSize(500, 500);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
JDesktop doesn't use a layout manager, so it's default/preferred size is 0x0
JPanel uses FlowLayout by default, which honours the preferredSize of it's child components when it lays them out
So, in your constructor, you could try changing the default layout manager to BorderLayout instead...
public MainPanel() {
setLayout(new BorderLayout());
jDesktopPane.add(jInternalFrame);
add(jDesktopPane);
// pointless
//setSize(400,400);
// pointless
//setVisible(true);
}
Now, you because nothing is actually defining a preferred size for anything, you should provide your own...
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
Then when you create the UI you can simply pack the frame...
private static void createAndShowGui() {
JFrame frame = new JFrame("This should be working now...");
MainPanel mainPanel = new MainPanel();
frame.setLayout(new BorderLayout());
// pointless considering the setContentPane call
//frame.add(mainPanel, BorderLayout.CENTER);
frame.setContentPane(mainPanel);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
frame.setLocationByPlatform(false);
//frame.setSize(500, 500);
frame.setVisible(true);
}
Now because JDesktopPane doesn't use any layout manager, you become responsible for ensuring that anything your add to it is positioned and size
jInternalFrame.setBounds(10, 10, 200, 200);
// Just like any frame, it's not visible when it's first created
jInternalFrame.setVisible(true);
Related
I am having a hard time understanding how to write my program with out having it extend from JFrame.
I have tried removing the extends JFrame clause and and adding it into both my methods, replacing the CalculatorWhichUsesAInterface frame = new CalculatorWhichUsesAInterface(); section with JFrame frame = new JFrame(); and a few other things and nothing has worked.
How should I go about using JFrame frame = new JFrame() in my program instead of using extends JFrame?
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
class CalculatorWhichUsesAInterface extends JFrame{
JFrame frame = new JFrame();
public CalculatorWhichUsesAInterface(){
JPanel jPanelOne = new JPanel();
jPanelOne.setLayout(new GridLayout(1, 1);
jPanelOne.add(new JButton("x"));
JPanel jPanelTwo = new JPanel(new BorderLayout());
JTextField field = new JTextField();
field.setText("2141987.01235");
jPanelTwo.add(field, BorderLayout.NORTH);
jPanelTwo.add(jPanelOne, BorderLayout.CENTER);
add(jPanelTwo, BorderLayout.CENTER);
}
public static void main(String[] args){
CalculatorWhichUsesAInterface frame = new CalculatorWhichUsesAInterface();
frame.setTitle("Calculator");
frame.setSize(500, 200);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
This is actually relativly easy (sorry, but it is).
Start by extending your class from JPanel, this provides you a basic container onto which to build your interface.
Remove the JFrame frame = new JFrame(); as you're not really using it and in your main method, create a new instance of JFrame and add you component to it
class CalculatorWhichUsesAInterface extends JPanel {
public CalculatorWhichUsesAInterface(){
JPanel jPanelOne = new JPanel();
jPanelOne.setLayout(new GridLayout(1, 1);
jPanelOne.add(new JButton("x"));
JPanel jPanelTwo = new JPanel(new BorderLayout());
JTextField field = new JTextField();
field.setText("2141987.01235");
jPanelTwo.add(field, BorderLayout.NORTH);
jPanelTwo.add(jPanelOne, BorderLayout.CENTER);
add(jPanelTwo, BorderLayout.CENTER);
}
public static void main(String[] args){
EventQueue.invokeLater(new Runnable() {
public void run() {
CalculatorWhichUsesAInterface calc = new CalculatorWhichUsesAInterface();
JFrame frame = new JFrame()
frame.setTitle("Calculator");
frame.add(calc);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
This concept provides you with a flexible and re-usable component. This means that you can decide how and where the component is to be displayed. Displayed on it's own in it's own frame (as the above example does) or added to another container (such as another JPanel or even an applet)
You may also want to take a look at Initial Threads
Example two - not extending anything
class CalculatorWhichUsesAInterface {
public static void main(String[] args){
EventQueue.invokeLater(new Runnable() {
public void run() {
JPanel jPanelOne = new JPanel();
jPanelOne.setLayout(new GridLayout(1, 1);
jPanelOne.add(new JButton("x"));
JPanel jPanelTwo = new JPanel(new BorderLayout());
JTextField field = new JTextField();
field.setText("2141987.01235");
jPanelTwo.add(field, BorderLayout.NORTH);
jPanelTwo.add(jPanelOne, BorderLayout.CENTER);
JFrame frame = new JFrame()
frame.setTitle("Calculator");
frame.add(jPanelTwo);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
Updated with "builder" example
This is a (very basic) example of a builder pattern, basically, you have a separate class which simply builds the UI and returns a JPanel (in this example)
More complex builders would allow you to add additional properties to adjust the outcome.
class CalculatorWhichUsesAInterface {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.setTitle("Calculator");
frame.add(CalculatorBuilder.build());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
public static class CalculatorBuilder {
public static JPanel build() {
JPanel jPanelOne = new JPanel();
jPanelOne.setLayout(new GridLayout(1, 1));
jPanelOne.add(new JButton("x"));
JPanel jPanelTwo = new JPanel(new BorderLayout());
JTextField field = new JTextField();
field.setText("2141987.01235");
jPanelTwo.add(field, BorderLayout.NORTH);
jPanelTwo.add(jPanelOne, BorderLayout.CENTER);
return jPanelTwo;
}
}
}
to not extend JFrame you have the right idea, but on your code above you'd need to first remove the extends JFrame but the way you declare your frame is fine:
JFrame frame = new JFrame("Title");
Then from there you just have to reference the object of it from then on, so for example:
frame.add(jPanelTwo,BorderLayout.CENTER)
Looks like everything you do in main (setTitle, setSize etc) you do for JFrame object that "comes" from inheritance (extends JFrame). So actually you are doing nothing with:
JFrame frame = new JFrame();
If you want not to use inheritance, you should invoke methods of JFrame object, not the CalculatorWhichUsesAInterface(). So the constructor should look like this (in main leave only creating the object):
class CalculatorWhichUsesAInterface{
JFrame frame = new JFrame();
public CalculatorWhichUsesAInterface(){
JPanel jPanelOne = new JPanel();
jPanelOne.setLayout(new GridLayout(1, 1);
jPanelOne.add(new JButton("x"));
JPanel jPanelTwo = new JPanel(new BorderLayout());
JTextField field = new JTextField();
field.setText("2141987.01235");
jPanelTwo.add(field, BorderLayout.NORTH);
jPanelTwo.add(jPanelOne, BorderLayout.CENTER);
frame.add(jPanelTwo, BorderLayout.CENTER); //DIFFERENCE
frame.setTitle("Calculator");
frame.setSize(500, 200);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
As you can see, I copied almost everyting from main to constructor, but it is invoked on different object (JFrame actually, not the CalculatorWhichUsesAInterface). But doing JFrame through inheritance is common way.
The assignment is simple, all we need to do is have the code create a window with a red panel with a single button and label. Here is the code thus far as well as the tester class.
I got the label to display on the window, but its in a weird place. I cant get the button to display at all as well getting the background to display as red.
This is where I'm having trouble with the most:
import java.awt.Color;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class MyCustomFrame extends JFrame
{
public MyCustomFrame()
{
createComponents();
setSize(FRAME_WIDTH, FRAME_HEIGHT);
}
private void createComponents()
{
JPanel panel=new createPanel();
button=new JButton("Push Me");
label=new JLabel("This is a label");
add(button);
add(label);
}
private JButton button;
private JLabel label;
final int FRAME_WIDTH = 800;
final int FRAME_HEIGHT = 800;
public void createPanel()
{
JPanel panel=new JPanel();
panel.setBackground(Color.RED);
//button=new JButton("Push Me");
//label=new JLabel("This is a label");
}
public void createFrame()
{
JFrame frame=new JFrame();
add(frame);
frame.setVisible(true);
}
}
And this is the tester class:
import javax.swing.JFrame;
public class MyCustomFrameViewer
{
public static void main(String[] args)
{
MyCustomFrame frame = new MyCustomFrame();
frame.setTitle("My first frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
You create the JPanel, panel, but add nothing to it, and then never add the panel to your JFrame. You should add your components to the JPanel, panel, and then add the panel object to your JFrame.
Note that a JPanel uses FlowLayout by default, and so it will more easily accept multiple other components without special add methods. The JFrame's contentPane uses BorderLayout which is slightly more complicated to use.
Add the panel to the frame instead of the label and button, and add the label and button to the panel...
private void createComponents()
{
JPanel panel=new createPanel();
add(panel);
button=new JButton("Push Me");
label=new JLabel("This is a label");
panel.add(button);
panel.add(label);
}
You may also want to take a look at Initial Threads and make sure you are creating your UI from within the context of the Event Dispatching Thread
Some side notes...
This scares me...
public void createFrame()
{
JFrame frame=new JFrame();
add(frame);
frame.setVisible(true);
}
You're trying to add a frame to a frame, which is an illegal operation in Swing, but thankfully, you're not actually calling it from what I can see.
Instead of using setSize(FRAME_WIDTH, FRAME_HEIGHT);, you may wish to use pack instead.
See also the tips in comments in this example:
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
// Don't extend frame, just use an instance
//public class MyCustomFrame extends JFrame {
public class MyCustomFrame {
private JFrame frame;
private JButton button;
private JLabel label;
private JPanel panel;
// better to override the preferred size of the component of interest
final int GAME_WIDTH = 300;
final int GAME_HEIGHT = 100;
public MyCustomFrame() {
createComponents();
// better to override the preferred size of the component of interest
//setSize(GAME_WIDTH, GAME_HEIGHT);
}
private void createComponents() {
// compilation error! createPanel() does not return anything..
//JPanel panel = new createPanel();
createPanel();
// create the frame!
createFrame();
}
private void createPanel() {
// creates a local instance
//JPanel panel = new JPanel();
panel = new JPanel() {
/* override the preferred size of the component of interest */
#Override
public Dimension getPreferredSize() {
return new Dimension(GAME_WIDTH, GAME_HEIGHT);
}
};
panel.setBackground(Color.RED);
button = new JButton("Push Me");
label = new JLabel("This is a label");
panel.add(button);
panel.add(label);
}
private void createFrame() {
// create a local instance of a JFrame that goes out of scope at end
// of method..
//JFrame frame = new JFrame();
frame = new JFrame("My first frame");
// add the panel to the frame!
frame.add(panel);
// better to use DISPOSE_ON_CLOSE
//frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// a good way to position a GUI
frame.setLocationByPlatform(true);
// this was trying to add a JFrame to another JFrame
//add(frame);
frame.pack();
}
public final JFrame getFrame() {
return frame;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
MyCustomFrame myFrame = new MyCustomFrame();
JFrame frame = myFrame.getFrame();
frame.setVisible(true);
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency
SwingUtilities.invokeLater(r);
}
}
I'm working on a program but my JLabel doesn't show up. My JButton works perfectly (it appears) but for some reason the JLabel does not appear. I have checked on internet but I Haven't found anything.
package com.hinx.client;
import java.awt.Color;
import javax.swing.*;
public class Main {
public static void main(String [] args)
{
createWindow();
}
static void createWindow()
{
//Create panel
JPanel content = new JPanel();
content.setLayout(null);
//Build the frame
JFrame frame = new JFrame("Hinx - A marketplace for apps - Client ALPHA_0.0.1");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(700, 400);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.add(content);
frame.setVisible(true);
//Add the login button
JButton login = new JButton("Login");
login.setBounds(0, 342, 150, 30);
//Create login label
JLabel loginlabel = new JLabel("Login Area");
//Create login panel
JPanel loginpanel = new JPanel();
loginpanel.setLayout(null);
loginpanel.setBounds(0, 0, 150, 400);
loginpanel.setBackground(Color.gray);
loginpanel.add(login);
loginpanel.add(loginlabel);
content.add(loginpanel);
}
}
I have checked on internet but I Haven't found anything.
JFrame is visible before JComponents (frame.add(content);) are added / created
move code line frame.setVisible(true); (better everything about JFrame) to the end of constuctor
Set a layout for your panel. Per example :
loginpanel.setLayout(new BorderLayout());
You can learn more about layouts here.
Here's what I get :
Use layouts. FlowLayout should be fine in this case. Do not call setBounds() and do not set layout as a null.
Add label and button on JPanel
Then add JPanel on JFrame
Call pack() instead of setSize()
Call setVisible(true) in the end.
Good luck!
You are making setLayout null.
JPanel loginpanel = new JPanel();
loginpanel.setLayout(null);
Use this,
JPanel loginpanel = new JPanel();
loginpanel.setLayout(new BorderLayout());
Run the UI on the EDT instead of running on the main thread. Read this post.
Example:
public static void main(String [] args)
{
Runnable r = new Runnable() {
#Override
public void run() {
createWindow();
}
};
EventQueue.invokeLater(r);
}
I have a JPanel containing JButtons and a few other things, and I want the entire panel to have a tool-tip. When I call setToolTipText on the JPanel, the tool-tip only appears in empty spaces within the JPanel.
Is there a way to set a tool-tip on the JPanel such that it applies to the JPanel and its children, or am I stuck with calling setToolTipText on all the children as well?
Create a recursive method:
public static void setToolTipRecursively(JComponent c, String text) {
c.setToolTipText(text);
for (Component cc : c.getComponents())
if (cc instanceof JComponent)
setToolTipRecursively((JComponent) cc, text);
}
Full example:
public static void main(String[] args) {
final JFrame frame = new JFrame("Test");
frame.add(new JLabel("Testing (no tooltip here)"), BorderLayout.NORTH);
final JPanel panel = new JPanel(new GridLayout(2, 1));
panel.setBackground(Color.RED);
panel.add(new JLabel("Hello"));
panel.add(new JTextField("World!"));
setToolTipRecursively(panel, "Hello World!");
frame.add(panel, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setVisible(true);
}
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?