I want to make an object I can add to my java swing application.
The object when instantiated would contain an image and 2 labels - is there a way to do this using java swing?
If there is - can you point me at an example.
I.e i want
Myobj icon = new MyObj(pic, label , label);
window.addComponent(icon);
Cheers
Andy
Create a class MyObj and let it extend JPanel. In the constructor of MyObj you call setLayout(new BorderLayout()) or whatever layout you prefer. Then do for instance add(pic, BorderLayout.NORTH); add(label1, BorderLayout.WEST); add(label2, BorderLayout.EAST);.
Then you should be able to do window.add(new MyObj(pic, label1, label2)).
import java.awt.*;
class MyObj extends JPanel {
public MyComponent(ImageIcon pic, String label1, String label2) {
setLayout(new BorderLayout());
add(new JLabel(label1), BorderLayout.NORTH);
add(new JLabel(pic), BorderLayout.CENTER);
add(new JLabel(label2), BorderLayout.SOUTH);
}
}
public class FrameTest {
public static void main(String[] args) {
JFrame jf = new JFrame("Demo");
jf.add(new MyObj(new ImageIcon("duke.jpg"), "Label 1", "Label 2"));
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.pack();
jf.setVisible(true);
}
}
Produces
This would typically be done by sublcassing JPanel and, in the constructor creating 3 labels (1 for the image) and adding them to the panel using a suitable layout manager.
Something like this ?
image with two labels http://img297.imageshack.us/img297/5223/capturadepantalla201005i.png
I created a subclass of JPanel and in its constructor I layout the components so it can be used exactly as you thought:
ImageAndLabels demo = new ImageAndLabels("image.png", "labelOne", "labelTwo");
window.add( demo );
Here's the complete source code for this window. May help you to get started.
import javax.swing.*;
import java.awt.Font;
public class ImageAndLabels extends JPanel {
public static void main( String [] args ) {
JFrame frame = new JFrame("image and labels");
frame.add( new ImageAndLabels("./logo.png", // logo
"Grouping swing objects", // label 1
"<html>Hey.<br>" // label 2
+"I want to make an object I can add to my java swing application.<br>"
+"The object when instantiated would contain an image and 2 labels - "
+"is there a way to do this using java swing?</html>") );
frame.pack();
frame.setVisible( true );
}
public ImageAndLabels( String imageURL, String textOne, String textTwo ) {
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
add( new JLabel( new ImageIcon(imageURL )));
add( new JLabel( textOne ){{
setFont( new Font("Arial", Font.BOLD, 20));
}});
add( new JLabel( textTwo ));
}
}
You can add multiple Swing components to some container component - usually JPanel:
JPanel panel = new JPanel(new SomeLayoutYouLike());
panel.add(..);
panel.add(..);
Read the section from the Swing tutorial on Using Layout Managers. Use the appropriate layout manager to layout the components as you wish. Then add the compnents to a JPanel.
well, the main point of swing is to avoid instantiate your objects with parameters...
for example: (rather not do that unless this vars are imperative to the creation of the object)
MyFrame(Object o1, Object o2...)
for serialization purposes, you would rather use an empty constructor, and to set the external values form out side of the frame(in this case), this way you would never get things mixed up... and avoid much NullPointerException debugging, later on if you would use serialization.
if you want to design components, you should use NetBeans, very simple, very user friendly, allows you to align and locate you labels, as for the ImagePanel.. I had one but I converted it to a scaling image panel.. with scaled layers over it.
If you need, I'll post it here.
Hope this helps,
Adam.
Related
I'm using the NetBeans GUI builder to handle my layout (I'm terrible with LayoutManagers) and am trying to place a simple JLabel so that it is always centered (horizontally) inside its parent JPanel. Ideally, this would maintain true even if the JPanel was resized, but if that's a crazy amount of coding than it is sufficient to just be centered when the JPanel is first created.
I'm bad enough trying to handle layouts myself, but since the NetBeans GUI Builder autogenerates immutable code, it's been impossible for me to figure out how to do this centering, and I haven't been able to find anything online to help me.
Thanks to anybody who can steer me in the right direction!
Here are four ways to center a component:
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
class CenterComponent {
public static JLabel getLabel(String text) {
return getLabel(text, SwingConstants.LEFT);
}
public static JLabel getLabel(String text, int alignment) {
JLabel l = new JLabel(text, alignment);
l.setBorder(new LineBorder(Color.RED, 2));
return l;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JPanel p = new JPanel(new GridLayout(2,2,4,4));
p.setBackground(Color.black);
p.setBorder(new EmptyBorder(4,4,4,4));
JPanel border = new JPanel(new BorderLayout());
border.add(getLabel(
"Border", SwingConstants.CENTER), BorderLayout.CENTER);
p.add(border);
JPanel gridbag = new JPanel(new GridBagLayout());
gridbag.add(getLabel("GridBag"));
p.add(gridbag);
JPanel grid = new JPanel(new GridLayout());
grid.add(getLabel("Grid", SwingConstants.CENTER));
p.add(grid);
// from #0verbose
JPanel box = new JPanel();
box.setLayout(new BoxLayout(box, BoxLayout.X_AXIS ));
box.add(Box.createHorizontalGlue());
box.add(getLabel("Box"));
box.add(Box.createHorizontalGlue());
p.add(box);
JFrame f = new JFrame("Streeeetch me..");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(p);
f.pack();
f.setLocationByPlatform(true);
f.setVisible(true);
}
});
}
}
By using Borderlayout, you can put any of JComponents to the CENTER area. For an example, see an answer to Stack Overflow question Get rid of the gap between JPanels. This should work.
Even with BoxLayout you can achieve that:
JPanel listPane = new JPanel();
listPane.setLayout(new BoxLayout(listPane, BoxLayout.X_AXIS ));
JLabel label = new JLabel();
listPane.add(Box.createHorizontalGlue());
listPane.add(label);
listPane.add(Box.createHorizontalGlue());
mKorbel's solution is perfect for your goal. Anyway I always like to suggest BoxLayout because it's very flexible.
Mara: "thanks for your response, however the NetBeans GUI Build uses GroupLayout and this is not overridable."
Not true! Right click anywhere inside JFrame (or any other GUI container) in NetBeans GUI builder and select "Set Layout". By default is selected "Free Design", which is Group layout, but you can select any other layout including Border layout as advised by mKorbel.
There's many ways to do this, depending on the layout manager(s) you use. I suggest you read the Laying Out Components Within a Container tutorial.
I believe the following will work, regardless of layout manager:
JLabel.setHorizontalAlignment(SwingConstants.CENTER)
I'm fairly new to JFrame and I want to know why my items are not showing up on the window. I know i dont have a ActionHandler but I just want my textfield's to show up on my window. Here's my code:
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
public class FirstGUI extends JFrame{
public void GUI(){
setTitle("Welcome");
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setSize(600,600);
JLabel title = new JLabel();
title.setText("Apple Inc. Member Login Port");
title.setFont(new Font("Arial", Font.PLAIN, 24));
JTextField login = new JTextField("Login",10);
JPasswordField pass = new JPasswordField("Password");
add(title);
add(login);
add(pass);
}
public static void main(String[] args){
FirstGUI a = new FirstGUI();
a.GUI();
}
}
but when i run it i get this:
but when i run it i get this:
You get an empty screen because you add the components to the frame after the frame is visible.
As has already been suggested you need to use an appropriate layout manager. FlowLayout is the easiest to start with.
invoke setVisible(true) AFTER adding the components to the frame.
So the code should be more like:
panel.add(...);
panel.add(...);
add(panel);
pack();
setVisible(true);
I agree to MadProgrammer's suggestions (+1)
Well, lets take a look at your program though
You actually have created a JFrame with components in it. Its working fine as well, but your question of "why are my items not showing up in the JFrame" is not because you did something wrong but because missed out something i.e. revalidate()
Try:
public static void main(String[] args){
FirstGUI a = new FirstGUI();
a.GUI();
a.revalidate();
}
I'm not saying this will give you perfect UI.. what I'm trying to say is this will help you understand the Swing better. Learn about Swing Layout managers and then work on your UI to have better results
revalidate(): This component and all parents above it are marked as needing to be laid out. This means the Layout Manager will try to realign the components. Often used after removing components. It is possible that some really sharp swing people may miss this. I would think that you will only know this if you are actually using Swing.
The default layout manager for JFrame is BorderLayout.
This means that your components are essentially all been added ontop of each other.
Try changing the layout manager to something like FlowLayout (for example)...
Take a look at A Visual Guide to Layout Managers and Using Layout Managers for more details.
Also, avoid setSize where possible, use Window#pack instead
Update
I'd also like to introduce you to Initial Threads which should be used to launch your UI code...
The only one reason :
setVisible(True); method for the frame should be put on the end of the code.
if you give this line on the top of the code that is when you create a frame. This will cause that problem.
Don't add the components directly to your frame. Instead add to the content pane, which is where a JFrame stores all of the components that it draws. Usually this is a JPanel.
Here is an example:
public class GUI
{
private JPanel content;
public void GUI
{
/*Other code*/
content = new JPanel();
add(content); //make content the content pane
content.add(title);
content.add(login);
content.add(pass);
}
If that fails, call setVisible(true) and setEnabled(true) on all of your components.
On a side note you may want to make your GUI function a constructor.
import javax.swing.*;
import java.awt.*;
class Myframec extends JFrame
{
Myframec()
{
Container c = this.getContentPane();
c.setLayout(null);
this.setBounds(10,10,700,500);
this.setTitle("Welcome");
this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setBounds(0,0,700,500);
panel.setBackground(Color.gray);
panel.setLayout(null);
c.add(panel);
Font f = new Font("Arial",Font.BOLD,25);
Font f1 = new Font("Arial",Font.BOLD,20);
JLabel lable = new JLabel();
lable.setBounds(130,10,400,100);
lable.setText("Apple Inc. Member Login Port");
lable.setFont(f);
panel.add(lable);
JTextField login = new JTextField("Login",10);
login.setBounds(120,150,400,30);
login.setFont(f1);
panel.add(login);
JPasswordField pass =new JPasswordField("Password");
pass.setBounds(120,200,400,30);
pass.setFont(f1);
lable.setFont(f);
panel.add(pass);
c.setVisible(true);
this.setVisible(true);
}
public static void main(String[] argm)
{
Myframec frame = new Myframec();
frame.setVisible(true);
}
}
So I am attempting to use MVC(model, view, controller) to format my code and when attempting to add the view to the actual application I get an error that says that "java.lang.IllegalArgumentException: adding a window to a container
at java.awt.Container.checkNotAWindow
at java.awt.Container.addImpl
at java.awt.Container.add"
While I know what the error is I have no idea what I should do(not use MVC or find some sort of work-around) and would appreciate any help. Below I will have the code of the two classes.
Here is where the application is run from:
import javax.swing.*;
import java.awt.*;
/**
* Write a description of class FencingApplication here.
*
* #author (your name)
* #version (a version number or a date)
*/
public class Application
{
public static void main(String[] args){
InputView view = new InputView();
InputModel model = new InputModel();
InputController ctrl = new InputController(view, model);
JFrame window = new JFrame("");
window.setSize(500, 600);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c = new Container();
c.setLayout(new BorderLayout());
c.add( view, BorderLayout.CENTER );
JButton btList = new JButton( "List" );
JButton btPools = new JButton("Pools");
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(1, 2));
buttonPanel.add(btList);
buttonPanel.add(btPools);
c.add( buttonPanel, BorderLayout.NORTH );
btList.addActionListener( ctrl );//where is the action performed method defined
btPools.addActionListener( ctrl );
window.setVisible( true );
}
}
And here is the view class:
import javax.swing.*; //Jframe/JButton/JLabel/etc
import java.awt.*; //container
import java.util.*;
/**
* Write a description of class InputView here.
*
* #author (your name)
* #version (a version number or a date)
*/
public class InputView extends JFrame implements Observer
{
JLabel lbPaste = new JLabel("Please paste the seeding here.");
JTextArea taPaste = new JTextArea();
JButton btPools = new JButton("Pools");
JLabel lbNum = new JLabel("Please input the number of pools you want to have.");
JTextField tfNum = new JTextField();
public InputView()
{
JPanel numPanel = new JPanel();
numPanel.setLayout(new BorderLayout());
numPanel.add(lbNum, BorderLayout.NORTH);
numPanel.add(tfNum, BorderLayout.CENTER);
JPanel pastePanel = new JPanel();
pastePanel.setLayout(new BorderLayout());
pastePanel.add(lbPaste, BorderLayout.NORTH);
pastePanel.add(new JScrollPane(taPaste), BorderLayout.CENTER);
Container c = getContentPane();
c.setLayout(new GridLayout(2, 1));
c.add(numPanel);
c.add(pastePanel);
setTitle( "Pools" );
setSize( 350, 500 );//width then height
setVisible(true);
setResizable(false);
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
public void update( Observable obs, Object obj )
{
}
}
Thanks in advance for any help!
Container is the superclass of e.g. Panel, JPanel, Window, JFrame, etc.
JFrame is a window, so you shouldn't (and in fact can't, as you found out here) add it to another component. JFrame is a top-level container.
Actually, it's probably the case that you shouldn't be using new Container() directly at all. For example, if you want a panel, you should use JPanel. It's kind of hard for me to tell exactly what you intended, since adding a JFrame to another component is an error. I see you adding stuff to c but I don't see you doing anything else with it.
So:
JFrame is a window.
JFrame has a content pane, which is the panel inside the window. (The default content pane is actually a JPanel, even though getContentPane() returns it as a Container.)
If you want to put stuff in a JFrame, you add the stuff to the content pane.
You don't need to add a JFrame to anything, just create it with new and call setVisible(true).
Those are the basics of how to use a JFrame correctly.
I also highly recommend the Swing tutorials if you haven't read them. They are really pretty good.
I'm fairly new to JFrame and I want to know why my items are not showing up on the window. I know i dont have a ActionHandler but I just want my textfield's to show up on my window. Here's my code:
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
public class FirstGUI extends JFrame{
public void GUI(){
setTitle("Welcome");
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setSize(600,600);
JLabel title = new JLabel();
title.setText("Apple Inc. Member Login Port");
title.setFont(new Font("Arial", Font.PLAIN, 24));
JTextField login = new JTextField("Login",10);
JPasswordField pass = new JPasswordField("Password");
add(title);
add(login);
add(pass);
}
public static void main(String[] args){
FirstGUI a = new FirstGUI();
a.GUI();
}
}
but when i run it i get this:
but when i run it i get this:
You get an empty screen because you add the components to the frame after the frame is visible.
As has already been suggested you need to use an appropriate layout manager. FlowLayout is the easiest to start with.
invoke setVisible(true) AFTER adding the components to the frame.
So the code should be more like:
panel.add(...);
panel.add(...);
add(panel);
pack();
setVisible(true);
I agree to MadProgrammer's suggestions (+1)
Well, lets take a look at your program though
You actually have created a JFrame with components in it. Its working fine as well, but your question of "why are my items not showing up in the JFrame" is not because you did something wrong but because missed out something i.e. revalidate()
Try:
public static void main(String[] args){
FirstGUI a = new FirstGUI();
a.GUI();
a.revalidate();
}
I'm not saying this will give you perfect UI.. what I'm trying to say is this will help you understand the Swing better. Learn about Swing Layout managers and then work on your UI to have better results
revalidate(): This component and all parents above it are marked as needing to be laid out. This means the Layout Manager will try to realign the components. Often used after removing components. It is possible that some really sharp swing people may miss this. I would think that you will only know this if you are actually using Swing.
The default layout manager for JFrame is BorderLayout.
This means that your components are essentially all been added ontop of each other.
Try changing the layout manager to something like FlowLayout (for example)...
Take a look at A Visual Guide to Layout Managers and Using Layout Managers for more details.
Also, avoid setSize where possible, use Window#pack instead
Update
I'd also like to introduce you to Initial Threads which should be used to launch your UI code...
The only one reason :
setVisible(True); method for the frame should be put on the end of the code.
if you give this line on the top of the code that is when you create a frame. This will cause that problem.
Don't add the components directly to your frame. Instead add to the content pane, which is where a JFrame stores all of the components that it draws. Usually this is a JPanel.
Here is an example:
public class GUI
{
private JPanel content;
public void GUI
{
/*Other code*/
content = new JPanel();
add(content); //make content the content pane
content.add(title);
content.add(login);
content.add(pass);
}
If that fails, call setVisible(true) and setEnabled(true) on all of your components.
On a side note you may want to make your GUI function a constructor.
import javax.swing.*;
import java.awt.*;
class Myframec extends JFrame
{
Myframec()
{
Container c = this.getContentPane();
c.setLayout(null);
this.setBounds(10,10,700,500);
this.setTitle("Welcome");
this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setBounds(0,0,700,500);
panel.setBackground(Color.gray);
panel.setLayout(null);
c.add(panel);
Font f = new Font("Arial",Font.BOLD,25);
Font f1 = new Font("Arial",Font.BOLD,20);
JLabel lable = new JLabel();
lable.setBounds(130,10,400,100);
lable.setText("Apple Inc. Member Login Port");
lable.setFont(f);
panel.add(lable);
JTextField login = new JTextField("Login",10);
login.setBounds(120,150,400,30);
login.setFont(f1);
panel.add(login);
JPasswordField pass =new JPasswordField("Password");
pass.setBounds(120,200,400,30);
pass.setFont(f1);
lable.setFont(f);
panel.add(pass);
c.setVisible(true);
this.setVisible(true);
}
public static void main(String[] argm)
{
Myframec frame = new Myframec();
frame.setVisible(true);
}
}
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.