this is my first question on stackoverflow so pls don't be so hard with me (and my English), I'll try my best asking a good question.
The problem is about what the title suggests -> setting the background of a JTextpane (specifically setting it transparent). As the setBackground-method takes a color argument, the way i went was with an alpha value = 0. This leads to the following visual artifacts:
example picture of the visual artifacts when running the code below
I will describe it in detail now, say what i've already tried and then post a minimal example for everyone to be able to recreate the bug easily.
I have a JFrame (myFrame) holding a JPanel (Test()) in which i paint. The background of this JPanel is set to green as you can see in the code. I did this to differ between the background of the TextPane and the actual background of the panel.
We also have a JTextPane inputfield -> which takes user input (it displays what you write). This is held by a JScrollPane scrollpane.
So the Target (meaning what i try to achieve): is a User input field, which is transparent, but still displays the text the user puts in. I tried to achieve this by setting the background of the inputfield and the scrollpane to a transparent color.
I would really appreciate it, if you don't just type something like (you need to setOpague(false) for ....) if you don't know exactly what you're talking about, because i nearly tried everything i can think of and read every post i could find in the internet about the problem. I will post some of them at the end. So...
What i already tried:
The usual way i found while searching for something like "How to make TextPane transparent" was to setOpague(false) at itself as well as the scrollpane and the viewport of the scrollpane. 1. Reading about what the method actually does i don't think that is a proper solution. 2. setting Opague(false) on these three leads to everything being invisible so, that's not good. Packing the frame again after setting the background. Either nothing was fixed or the components became completely invisible.
I also tried: setBackground(null), setting the Background of just the inputfield (just every single component and every possible combination amongst the three (scrollpane, viewport, inputfield)), mixing setOpague(true)/setOpague(false)/setBackground(...) in every way i could think of. Overriding the paintComponent method of the textpane and scrollpane seemed like a good approach, but i did not come very far with it.
So here is the code:
public class Test extends JPanel {
JTextPane inputField = new JTextPane();
JScrollPane scrollpane = new JScrollPane(inputField);
#Override
public void paint(Graphics g) {
super.paint(g);
inputField.setBounds(10,10,100,100);
scrollpane.setBounds(10,10,100,100);
}
public Test(){
this.setOpaque(true);
this.setBackground(Color.GREEN);
inputField.setBounds(10,10,100,100);
scrollpane.setBounds(10,10,100,100);
inputField.setBackground(new Color(0,0,0,0));
scrollpane.setBackground(new Color(0,0,0,0));
scrollpane.getViewport().setBackground(new Color(0,0,0,0));
this.add(scrollpane);
}
public static void main(String[] args) {
JFrame myFrame = new JFrame();
myFrame.add(new Test());
myFrame.pack();
myFrame.setSize(640,480);
myFrame.setPreferredSize(new Dimension(640,480));
myFrame.setVisible(true);
}
}
And here some links to posts I read which describe similar problems:
Java - Transparent JScrollPane
Transparent JEditorPane in a JScrollPane over a background JPanel
setOpaque(true/false); Java
I would really appreciate if someone can help me with the problem or even only suggest me an alternative solution. I'm writing a little chat-program atm for a project for my university and i think transparent message fields are a neat idea. I will try to answer here as fast as i can. Thx in advance.
Do not use transparent color as background - kind of hard to delete with it (e.g. when component is being repaint (and opaque)).
Do not use setBounds (unless using null LayoutManager). In below example I used setPreferredSize but still better to correctly use LayoutManager (I am a bit lazy, and lot of work to do at the moment).
public class Test extends JPanel {
JTextPane inputField = new JTextPane();
JScrollPane scrollpane = new JScrollPane(inputField);
public Test(){
this.setOpaque(true);
this.setBackground(Color.GREEN);
inputField.setPreferredSize(new Dimension(300, 100));
inputField.setOpaque(false);
scrollpane.setOpaque(false);
scrollpane.getViewport().setOpaque(false);
this.add(scrollpane);
}
public static void main(String[] args) {
JFrame myFrame = new JFrame();
myFrame.add(new Test());
myFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
myFrame.setPreferredSize(new Dimension(640,480));
myFrame.pack();
myFrame.setVisible(true);
}
}
The whole code of main should be called on the EDT (e.g. SwingUtilities.invokeLater) since it is manipulating swing components but that is not part of the question (and not that relevant here since setVisible is the last command - components not being displayed while changed).
Your program gave me some errors when launching, occasionally. Make sure to run a swing GUI from the EDT (invokeLater()).
The line that is causing your issue is:
scrollpane.getViewport().setBackground(new Color(0,0,0,0));
Also - is there some reason you are setting bounds manually instead of using a layout manager?
Maybe I didn't understand your question, or you want to have an image in the background - but could you not just set the color of your text area to be the same color as your JPanel?
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
public class Test extends JPanel {
JTextPane inputField = new JTextPane();
JScrollPane scrollpane = new JScrollPane(inputField);
public Test(){
this.setBackground(Color.GREEN);
scrollpane.setPreferredSize(new Dimension(300, 300));
inputField.setBackground(Color.GREEN);
this.add(scrollpane);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame myFrame = new JFrame();
myFrame.add(new Test());
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setPreferredSize(new Dimension(640,480));
myFrame.pack();
myFrame.setVisible(true);
}
});
}
}
Related
I want do design a simple login format and in order to do so I want two JTextFields for Username/Password and a Login Button. The Login button is display as expected but when I add the JTextField, nothing shows in my JFrame. Would be nice if someone could help a beginner out...
Here's my code (I know it's ugly but this is just a "code sketch"):
package bucketlistpackage;
import java.awt.Container;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class GameFrame extends JFrame {
public GameFrame(String title) {
super(title); //sets title of frame
startFrame(); //sets details of main frame
final Container logincont = getContentPane(); //creates content pane
JFrame loginframe = new JFrame();
usernameField(loginframe);
loginButton(loginframe);
logincont.add(loginframe);
}
private void usernameField(JFrame loginframe) {
JTextField usernameF = new JTextField("Username", 1);
usernameF.setBounds(50, 50, 50, 20);
loginframe.add(usernameF);
usernameF.setVisible(true);
}
private void startFrame() {
this.setSize(1000, 1000);
this.setVisible(true);
}
private void loginButton(Container cont) {
JButton loginB = new loginButton();
loginB.setSize(300, 150);
loginB.setText("Login");
cont.add(loginB);
}
}
The problem lies on how you are adding component to one another in your case.
You are adding a JFrame to a Container, when in all case it should be the other way around.
The other problem is that you are not using Layouts to manage the components positions on the JFrame.
Another problem as well is that you are not refreshing the windows after adding all the stuff on it.
A bit of a resume on how Java works with native UIs:
Java creates a new thread for the UI. So if you open the debugger you will see AWT threads as well as the main threads and others. This means that you have to manage this in a correct way, because after the application starts SWING and the functions you determine for reactions will lay the ground on how it will behave. Your main thread will die, but the visual threads will keep active.
If you are just starting to program I would encourage you to practice a bit more native java language before moving to SWING or AWT. This libraries can be really painful and tricky to use.
The other thing is SWING library follows a hierarchy for the components:
JFrame > JPanels > Components
In your code you have already worked with all of them but in a disorganized way. JFrame is the main application window, where the graphics will be displayed (can also be a Canvas or whatever class you want to use for that matter). JPanels are organizers, you can use different layouts to organize whatever is inside it. And finally the Components are well... everything! A component can be a JTextField, but it can also be a JPanel, or JButton.
The idea with SWING is to create multiple Panels and organize the end components inside them, using the help of the different layouts to see whats the best approach to make them attractive in many different window sizes.
Finally, if you are using Eclipse, there is a plugin called WindowBuilder which might help you. I don't recommend you using it if you are very new to Java since it will make you depend a lot on it instead of learning how to actually code with SWING.
Hope this helps!!!
Btw, to fix the code above I would do something like this:
public GameFrame(String title) {
super(title); //sets title of frame
startFrame(); //sets details of main frame
final Container logincont = getContentPane(); //creates content pane
logincont.setLayout(new BorderLayout());
usernameField(logincont, BorderLayout.NORTH);
loginButton(logincont, BorderLayout.CENTER);
this.revalidate();
this.repaint();
}
private void usernameField(Container loginframe, String direction) {
JTextField usernameF = new JTextField("Username");
// usernameF.setBounds(50, 50, 50, 20);
loginframe.add(usernameF, direction);
usernameF.setVisible(true);
}
private void startFrame() {
this.setSize(1000, 1000);
this.setVisible(true);
}
private void loginButton(Container cont, String direction) {
JButton loginB = new JButton();
loginB.setSize(300, 150);
loginB.setText("Login");
cont.add(loginB, direction);
}
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 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 can't make the pack() method work. I tried several things. My code looks like this at the moment:
Class 1:
public static void main( String[] args )
{
java.awt.EventQueue.invokeLater(new Runnable() {
public void run()
{
JavaGui mygui = new JavaGui();
// mygui.setSize(1154, 753);
mygui.setVisible(true);
mygui.pack();
Class 2:
public class JavaGui extends javax.swing.JFrame
{
public JavaGui()
{
getContentPane().setLayout(null);
..
getContentPane().add(panelLeft);
...
getContentPane().add(panelRight);
I tried putting the pack method in everywhere, but it's not going to work with this way of adding gui elements. Any suggestions why? I also tried adding everything to a JFrame instead of the getContentPane(), but I can't make that work either.
Don't use null layouts together with pack(). The pack method tells the layout managers and components to size themselves optimally, and if you instead use null layouts, then the gui risks shrinking to a minimal size, since there is no layout to hold it together.
Don't use null layouts at all for the most part. Using these risk your creating rigid GUI's that are almost impossible to extend, improve, debug.
Don't use setSize(...) and pack(). The layouts mostly respect the preferred sizes of components, not their sizes.
Instead:
Use a pleasing and sensible combination of nested JPanels, each using its own layout manager.
Let the components and the layout managers size themselves.
Then pack should help.
The general order that I do is to add all components to the GUI, then call pack(), then setLocationByPlatform(true) (I think), then setVisible(true).
For better help, please check out the Swing Layout Manager Tutorials.
Here are a couple examples to other questions on this site that use various layout managers:
A combination of BorderLayout and GridLayout to create a calculator
BorderLayout and BoxLayout Combination for labels and JTextFields
Using GridBagLayout to create flexible label/textfield grid
I would recommened beginners on building up swing guis to use a good ide with a builtin gui designer like eclipse and windowbuilder or netbeans with matisse. It will help you building up a prototype of your desired gui and gives you an insight how the layouting is done in the source code.
Experiment with the differenet layouts and what is happening when some values are changed.
one does not simply build up a well behaving gui without understanding how the layout works, so doing the recommended tutorials and looking at examples as already posted by Hovercraft Full Of Eels is absolutely necessary.
For your case i just guess what you were up to. Because youre mentioning left and right panels i suggest a JSplitPane which let you divide your screen in two areas which are customizable in size and orientation.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
public class JavaGui extends JFrame {
//SerialVersionId http://stackoverflow.com/questions/285793/what-is-a-serialversionuid-and-why-should-i-use-it
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
//Calls to Gui Code must happen on the event dispatch thread that the gui does not get stuck
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new JavaGui().setVisible(true);
}
});
}
public JavaGui() {
// Set the desired size of the frame to determine the maximum size of its components
setPreferredSize(new Dimension(1024, 768));
// Set the default close operation, if press x on frame, destroy the frame and exit the application - others are just destroy the frame or just hide the
// frame
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// BorderLayout because we just need a centric gui with one component, here JSplitPane in full size
getContentPane().setLayout(new BorderLayout(0, 0));
// JsplitPane is a bit special as it depends on the divider location between both panels, for the sake of a small example we take the default -1,
JSplitPane splitPane = new JSplitPane();
// 0.5 divides extra space equally to left and right component when resizing the frame - so specifiying a size for the left and right component is not
// necessary
// use the divider location default -1 to let the width of the left component decide where the right component begins, in that case because of the
// resize weight half and half
splitPane.setDividerLocation(-1);
splitPane.setResizeWeight(0.5);
getContentPane().add(splitPane, BorderLayout.CENTER);
// For the panels the same layout as default as the intention is not stated in your question
JPanel leftPanel = new JPanel();
splitPane.setLeftComponent(leftPanel);
leftPanel.setLayout(new BorderLayout(0, 0));
JPanel rightPanel = new JPanel();
splitPane.setRightComponent(rightPanel);
rightPanel.setLayout(new BorderLayout(0, 0));
// Add a button Panel to the south for doing something - flow layout for letting the components flow to the right side
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
getContentPane().add(buttonPanel, BorderLayout.SOUTH);
// Close Button for closing the frame
JButton btnExit = new JButton("Destroy this frame, but let application run");
btnExit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
dispose();
}
});
buttonPanel.add(btnExit);
// Set every component to its preferred size
pack();
// Make it visible
setVisible(true);
}
}
If you want your JFrame to work with a null layout, rearrange your code so that it looks like this:
public class JavaGui extends javax.swing.JFrame
{
public JavaGui()
{
setMinimumSize(1154, 753); // Make sure you do setMinimumSize() instead of setSize() when using pack() so that the JFrame does not shrink to 0 size
setLayout(null);
add(panelLeft);
add(panelRight);
pack();
}
// Next is main method
Main:
public static void main(String[] args)
{
java.awt.EventQueue.invokeLater(new Runnable() {
public void run()
{
new JavaGui().setVisible(true);
// Do not do any formatting for your JFrame here
}
});
Before, you were modifying the JFrame after it was set visible, so that usually does not work, except for pack(). All components and settings for your JFrame should not be in the main method if you are using an anonymous inner class.
You can also use other layouts. Null layouts are for getting pixels in precise locations, which is used for advanced GUI design such as creating a custom GUI, but it seems that you are making a generic GUI with JPanels. For this, I would recommend using a GridBagLayout, which keeps everything centered if the frame is resized and is easy to use. To use a GridBagLayout, you have to replace setLayout(null); with setLayout(new GridBagLayout()); and set GridBagConstraints. Here is some example code of making a panel with a component and a GridBagLayout:
JPanel pane = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
if (shouldFill) {
//natural height, maximum width
c.fill = GridBagConstraints.HORIZONTAL;
}
//For each component to be added to this container:
//...Create the component...
//...Set instance variables in the GridBagConstraints instance...
pane.add(theComponent, c);
// Source: Oracle Docs
Hello
I'm an amateur trying to learn/improve my understanding of Java by writing a score card for archery. I ‘m trying to produce a GUI and so far have successfully produced on a JPanel a row of 18 labels of differing sizes and colours suitable for scoring a dozen.
I then tried to add five of these 'labels panels' to another panel to build up a grid and save having to create and add as many as 150 labels in some cases . No success so far as the original labels panels will not show up. All the panels are displayed on a JFrame
I've tried a number of different ways of getting the code to work, using the Java tutorial and googling the internet and studying similar problems on this site but I'm going round in circles. I must have missed something somewhere and hope that you may be able to help.
I'm using Java 6 and JGrasp v1.8.8_01 as an IDE
The following code for the labels panel has been cut down as much of it is repetitive.
import javax.swing.*;
import java.awt.*;
public class ArrowScoreLabels extends JPanel{
public JPanel createContentPane(){
JPanel panelForLabels = new JPanel();
panelForLabels.setLayout(null);
//Code creates 18 labels, sets the size, position, background colours, border and
//font and adds the labels to the’panelForLabels
JLabel scorelabel1;
scorelabel1 = new JLabel("",JLabel.CENTER);
scorelabel1.setBorder(BorderFactory.createLineBorder(Color.black));
scorelabel1.setFont(new Font("Arial", Font.ITALIC, 26));
scorelabel1.setLocation(0, 0);//first value differs for each label
scorelabel1.setSize(35, 35);
scorelabel1.setOpaque(true);
panelForLabels.add(scorelabel1);
panelForLabels.setOpaque(true);
return panelForLabels;
}
}
Running the following class shows the 18 labels on panel
import javax.swing.*;
import java.awt.*;
public class TestArrowScoreLabels {
private static void createAndShowArrowLabels() {
//Create and set up the window.
JFrame frame = new JFrame("To score one dozen");
//Create and set up the content pane.
ArrowScoreLabels asl = new ArrowScoreLabels();
frame.setContentPane(asl.createContentPane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(676, 73);
frame.setVisible(true);
}
//Main method to show the GUI/
public static void main(String[] args) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
createAndShowArrowLabels();
}
});
}
}
The following code for the second panel is similar, compiles but only shows the second green JPanel and not the panel with the labels.
import javax.swing.*;
import java.awt.*;
public class FiveDozenScorePanel{
public JPanel createContentPane(){
//A bottom JPanel on which to place five dozenpanels.
JPanel fivedozenpanel = new JPanel();
fivedozenpanel.setLayout(null); //requires absolute spacing
fivedozenpanel.setSize(676,185);
fivedozenpanel.setBackground(Color.green);
//Label panels for five dozen
ArrowScoreLabels dozenscorepanel1, dozenscorepanel2,
dozenscorepanel3,dozenscorepanel4,dozenscorepanel5;
//Create the 5 dozenscorelabels.
dozenscorepanel1 = new ArrowScoreLabels();
dozenscorepanel1.setLocation(5,5);//y value changes for each panel
fivedozenpanel.add(dozenscorepanel1);//plus the other 4
fivedozenpanel.setOpaque(true);
return fivedozenpanel;
}
private static void createAndShowDozenPanels() {
JFrame frame = new JFrame("To score five dozen");
FiveDozenScorePanel fdsp = new FiveDozenScorePanel();
frame.setContentPane(fdsp.createContentPane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Display the window
frame.setSize(700, 233);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
createAndShowDozenPanels();
}
});
}
}
I've also tried frame.getContentPane().add(fdsp); - frame.pack(); and read so much about paint methods that I'm totally confused.
I can get the ArrowScoreLabels image to appear directly onto a JFrame rather than a JPanel but only one of them and not five.
I would appreciate being pointed in the right direction. Thankyou for your time.
Update - 14th Dec 2010
I have managed to display the panelForLabels Jpanel on another Jpanel on a JFrame. This was done by adding the following code to the class ArrowScoreLabels. The original createContentPane() method was renamed createRowOne(). The panelForLabels was coloured red and the fivedozen panel yellow to ascertain which was showing. However I was only able to persuade the programme to display one row of labels despite a great deal of experimentation and research.
public static JPanel createContentPane(){
//Bottom panelto hold rows of labels
JPanel fivedozenscorepanel = new JPanel();
fivedozenscorepanel.setLayout(null);//requires absolute spacing
fivedozenscorepanel.setSize(660,180);
fivedozenscorepanel.setBackground(Color.yellow);
fivedozenscorepanel.add(createRowOne());
fivedozenscorepanel.setOpaque(true);
return fivedozenscorepanel;
}
The only way I displayed the 5 rows of 18 labels was to create all 90 in the ArrowScoreLabels class and then add them to one JPanel using absolute spacing and then to a JFrame.
I've taken note of pstantons advice - thankyou for that - and I'm looking into using the MigLayout Manager.
simple answer: use a layout manager. don't use absolute positioning.
just comment out all of your calls to setLocation and setLayout and swing will use the default FlowLayout.
for more control over the display, use a different layout manager.
also, if you use multiple panels you will have trouble aligning things in different panels unless they contain the same number of components which are exactly the same size so consider using one panel for all of the labels.
you can achieve just about any layout you need using MigLayout.
EDIT: in your example, there's no need for ArrowScoreLabels need to extend JPanel since you are doing the work in createContentPane to construct a separate JPanel. later in your code you call new ArrowScoreLabels() wich will just return a blank JPanel, instead you need to call new ArrowScoreLabels().createContentPane()
if you want ArrowScoreLabels to extend JPanel, implement public ArrowScoreLabels() ie the constructor instead of createContentPane.
I've the impression you don't set a size to your dozenscorepanel1. So, set a size :-)
Be careful with the layout null, because it's a pain ; you always forget something. Write your own, or use an existing one.